From d897fcd73e3d65d65dee95456ced29288bf63bb9 Mon Sep 17 00:00:00 2001 From: Yamo4490 Date: Sun, 8 Jun 2025 00:55:10 +0900 Subject: [PATCH] 02 --- Assets/External/Fantasy Skybox.meta | 8 + .../External/Fantasy Skybox/ReleaseNotes.txt | 3 + .../Fantasy Skybox/ReleaseNotes.txt.meta | 15 + .../Free Stylized Hand-Painted Skybox.meta | 8 + .../BD Studios Post-Processing Profile.asset | 1522 ++++++++++++ ...Studios Post-Processing Profile.asset.meta | 16 + .../BD_Lighting.lighting | 64 + .../BD_Lighting.lighting.meta | 15 + .../Demo.unity | 3 + .../Demo.unity.meta | 14 + .../Materials.meta | 8 + .../Materials/Cloudy01.mat | 33 + .../Materials/Cloudy01.mat.meta | 15 + .../Materials/Cloudy02.mat | 33 + .../Materials/Cloudy02.mat.meta | 15 + .../Materials/Cloudy03.mat | 33 + .../Materials/Cloudy03.mat.meta | 15 + .../Materials/Cloudy04.mat | 33 + .../Materials/Cloudy04.mat.meta | 15 + .../Materials/Dawn.mat | 33 + .../Materials/Dawn.mat.meta | 15 + .../Materials/Dawn_Cloudy.mat | 33 + .../Materials/Dawn_Cloudy.mat.meta | 15 + .../Materials/Day_Clear.mat | 33 + .../Materials/Day_Clear.mat.meta | 15 + .../Materials/Midnight.mat | 33 + .../Materials/Midnight.mat.meta | 15 + .../Materials/Midnight_Stars.mat | 33 + .../Materials/Midnight_Stars.mat.meta | 15 + .../Materials/Midnight_Stars02.mat | 33 + .../Materials/Midnight_Stars02.mat.meta | 15 + .../Materials/Sunset.mat | 33 + .../Materials/Sunset.mat.meta | 15 + .../Materials/Sunset_Cloudy.mat | 33 + .../Materials/Sunset_Cloudy.mat.meta | 15 + .../Textures.meta | 8 + .../Textures/Cloudy01.png | 3 + .../Textures/Cloudy01.png.meta | 129 ++ .../Textures/Cloudy02.png | 3 + .../Textures/Cloudy02.png.meta | 129 ++ .../Textures/Cloudy03.png | 3 + .../Textures/Cloudy03.png.meta | 129 ++ .../Textures/Cloudy04.png | 3 + .../Textures/Cloudy04.png.meta | 129 ++ .../Textures/Dawn.png | 3 + .../Textures/Dawn.png.meta | 129 ++ .../Textures/Dawn_Cloudy.png | 3 + .../Textures/Dawn_Cloudy.png.meta | 129 ++ .../Textures/Day_Clear.png | 3 + .../Textures/Day_Clear.png.meta | 129 ++ .../Textures/Midnight.png | 3 + .../Textures/Midnight.png.meta | 129 ++ .../Textures/Midnight_Stars.png | 3 + .../Textures/Midnight_Stars.png.meta | 129 ++ .../Textures/Midnight_Stars02.png | 3 + .../Textures/Midnight_Stars02.png.meta | 129 ++ .../Textures/Sunset.png | 3 + .../Textures/Sunset.png.meta | 129 ++ .../Textures/Sunset_Cloudy.png | 3 + .../Textures/Sunset_Cloudy.png.meta | 129 ++ Assets/Scenes/123.unity | 3 + Assets/Scenes/123.unity.meta | 7 + Assets/Scenes/SampleScene.unity | 3 + Assets/Scenes/SampleScene.unity.meta | 7 + Assets/Scripts/3rd.meta | 8 + Assets/Scripts/3rd/mmd-for-unity-master.meta | 8 + .../.MMDIKBaker/Local.testsettings | 10 + .../.MMDIKBaker/MMDIKBaker.vsmdi | 6 + .../.MMDIKBaker/MMDIKBaker/IK_Test.vmd | Bin 0 -> 16640 bytes .../.MMDIKBaker/MMDIKBaker/Program.cs | 26 + .../MMDIKBaker/Properties/AssemblyInfo.cs | 36 + .../.MMDIKBaker/MMDIKBaker/TrueMyHeart.vmd | Bin 0 -> 414006 bytes .../.MMDIKBaker/MMDIKBaker/miku.pmd | Bin 0 -> 474665 bytes .../MMDIKBakerGUI/Form1.Designer.cs | 166 ++ .../.MMDIKBaker/MMDIKBakerGUI/Form1.cs | 120 + .../.MMDIKBaker/MMDIKBakerGUI/Form1.resx | 120 + .../.MMDIKBaker/MMDIKBakerGUI/Program.cs | 21 + .../MMDIKBakerGUI/Properties/AssemblyInfo.cs | 36 + .../Properties/Resources.Designer.cs | 71 + .../MMDIKBakerGUI/Properties/Resources.resx | 117 + .../Properties/Settings.Designer.cs | 30 + .../Properties/Settings.settings | 7 + .../bin/Debug/MMDBoneBakerLibrary.dll | 3 + .../MMDIKBakerGUI/bin/Debug/MMDIKBakerGUI.exe | Bin 0 -> 11776 bytes .../bin/Debug/MMDIKBakerGUI.vshost.exe | Bin 0 -> 11600 bytes .../bin/Debug/MMDModelLibrary.dll | 3 + .../bin/Debug/MMDMotionLibrary.dll | 3 + .../.MMDIKBaker/MMDIKBakerLibrary/IKBaker.cs | 62 + .../MMDIKBakerLibrary/Misc/BezireCurve.cs | 61 + .../MMDIKBakerLibrary/Misc/CCDSolver.cs | 123 + .../Misc/DefaultIKLimitter.cs | 273 +++ .../MMDIKBakerLibrary/Misc/IIKLimitter.cs | 23 + .../MMDIKBakerLibrary/Misc/IIKSolver.cs | 18 + .../MMDIKBakerLibrary/Misc/MathHelper.cs | 224 ++ .../MMDIKBakerLibrary/Misc/Matrix.cs | 393 ++++ .../MMDIKBakerLibrary/Misc/Quaternion.cs | 123 + .../MMDIKBakerLibrary/Misc/SQTTransform.cs | 160 ++ .../MMDIKBakerLibrary/Misc/Vector2.cs | 17 + .../MMDIKBakerLibrary/Misc/Vector3.cs | 120 + .../MMDIKBakerLibrary/Model/MMDBone.cs | 58 + .../MMDIKBakerLibrary/Model/MMDBoneManager.cs | 153 ++ .../MMDIKBakerLibrary/Model/MMDIK.cs | 50 + .../MMDIKBakerLibrary/Model/ModelConverter.cs | 70 + .../Motion/AnimationPlayer.cs | 50 + .../Motion/MMDBoneKeyFrame.cs | 73 + .../Motion/MMDFaceKeyFrame.cs | 34 + .../MMDIKBakerLibrary/Motion/MMDMotion.cs | 20 + .../Motion/MMDMotionTrack.cs | 95 + .../Motion/MotionConverter.cs | 104 + .../MMDIKBakerLibrary/Motion/MotionHelper.cs | 103 + .../Properties/AssemblyInfo.cs | 38 + .../.MMDIKBaker/MMDIKBakerTest/MatrixTest.cs | 177 ++ .../MMDIKBakerTest/Properties/AssemblyInfo.cs | 35 + .../MMDIKBakerTest/QuaternionTest.cs | 135 ++ .../.MMDIKBaker/MMDIKBakerTest/Vector3Test.cs | 95 + .../MMDModelLibrary/CoordinateType.cs | 20 + .../.MMDIKBaker/MMDModelLibrary/MMDModel.cs | 46 + .../MMDModelLibrary/ModelManager.cs | 106 + .../Properties/AssemblyInfo.cs | 36 + .../MMDModelLibrary/Ver1/MMDModel1.cs | 530 +++++ .../MMDModelLibrary/Ver1/ModelBone.cs | 89 + .../MMDModelLibrary/Ver1/ModelBoneDisp.cs | 33 + .../MMDModelLibrary/Ver1/ModelBoneDispName.cs | 38 + .../MMDModelLibrary/Ver1/ModelHeader.cs | 63 + .../MMDModelLibrary/Ver1/ModelIK.cs | 60 + .../MMDModelLibrary/Ver1/ModelJoint.cs | 132 ++ .../MMDModelLibrary/Ver1/ModelMaterial.cs | 126 + .../MMDModelLibrary/Ver1/ModelRigidBody.cs | 140 ++ .../MMDModelLibrary/Ver1/ModelSkin.cs | 114 + .../MMDModelLibrary/Ver1/ModelVertex.cs | 89 + .../MMDMotionLibrary/CoordinateType.cs | 20 + .../.MMDIKBaker/MMDMotionLibrary/MMDMotion.cs | 40 + .../Motion2/CameraMotionData.cs | 93 + .../Motion2/FaceMotionData.cs | 39 + .../Motion2/LightMotionData.cs | 46 + .../MMDMotionLibrary/Motion2/MMDMotion2.cs | 197 ++ .../MMDMotionLibrary/Motion2/MotionData.cs | 81 + .../MMDMotionLibrary/MotionManager.cs | 89 + .../Properties/AssemblyInfo.cs | 36 + .../TraceAndTestImpact.testsettings | 9 + .../3rd/mmd-for-unity-master/.gitignore | 10 + .../3rd/mmd-for-unity-master/CHANGE-LOG | 74 + .../Editor/Config/Config.cs | 233 ++ .../Editor/Config/ConfigWindow.cs | 34 + .../Editor/ExpressionManagerEditor.cs | 104 + .../Editor/Inspector/InspectorBase.cs | 66 + .../Editor/Inspector/PMDInspector.cs | 87 + .../Editor/Inspector/PMDScriptableObject.cs | 7 + .../Editor/Inspector/ScriptableObjectBase.cs | 10 + .../Editor/Inspector/VMDInspector.cs | 84 + .../Editor/Inspector/VMDScriptableObject.cs | 7 + .../Editor/MMDEngineEditor.cs | 562 +++++ .../Editor/MMDLoader/LoadedWindow.cs | 37 + .../Editor/MMDLoader/PMDLoaderWindow.cs | 61 + .../MMDLoader/Private/AlphaReadableTexture.cs | 123 + .../AlphaReadableTextureDirectoryImporter.cs | 28 + .../MMDLoader/Private/AvatarSettingScript.cs | 359 +++ .../Editor/MMDLoader/Private/ComputeSkin.cs | 31 + .../Editor/MMDLoader/Private/MMDFormat.cs | 841 +++++++ .../Editor/MMDLoader/Private/MMDMathf.cs | 108 + .../Editor/MMDLoader/Private/ModelAgent.cs | 141 ++ .../Editor/MMDLoader/Private/MotionAgent.cs | 93 + .../Editor/MMDLoader/Private/PMDConverter.cs | 1015 ++++++++ .../MMDLoader/Private/PMDLoaderScript.cs | 499 ++++ .../Editor/MMDLoader/Private/PMXConverter.cs | 2033 +++++++++++++++++ .../Private/PMXLoaderScript.PMD2PMX.cs | 411 ++++ .../Private/PMXLoaderScript.PMX2PMD.cs | 453 ++++ .../MMDLoader/Private/PMXLoaderScript.cs | 639 ++++++ .../Editor/MMDLoader/Private/VMDConverter.cs | 559 +++++ .../MMDLoader/Private/VMDLoaderScript.cs | 326 +++ .../Editor/MMDLoader/VMDLoaderWindow.cs | 52 + .../Editor/MorphManagerEditor.cs | 123 + .../Editor/PhysicsManagerEditor.cs | 93 + .../XFileImporter/Private/XFileConverter.cs | 163 ++ .../XFileImporter/Private/XFileFormat.cs | 348 +++ .../XFileImporter/Private/XFileImporter.cs | 34 + .../XFileImporter/XFileImporterWindow.cs | 29 + .../Scripts/3rd/mmd-for-unity-master/LICENSE | 12 + .../3rd/mmd-for-unity-master/README.md | 3 + .../Resources/ExpressionManagerScript.cs | 97 + .../Resources/HalfLambert.shader | 103 + .../Resources/IK/BoneController.cs | 104 + .../Resources/IK/CCDIKSolver.cs | 145 ++ .../Resources/MMDEngine.cs | 135 ++ .../Resources/MMDSkinsScript.cs | 64 + .../Resources/Morph/BoneMorph.cs | 113 + .../Resources/Morph/GroupMorph.cs | 36 + .../Resources/Morph/MaterialMorph.cs | 269 +++ .../Resources/Morph/MorphBase.cs | 16 + .../Resources/Morph/MorphManager.cs | 354 +++ .../Resources/Morph/UvMorph.cs | 36 + .../Resources/Morph/VertexMorph.cs | 36 + .../Resources/PMDMaterial/LICENSE | 202 ++ .../PMDMaterial/PMD Material Transparent.mat | 46 + .../PMD Material with Outline Transparent.mat | 48 + .../PMDMaterial/PMD Material with Outline.mat | 48 + .../Resources/PMDMaterial/PMD Material.mat | 45 + .../Resources/PMDMaterial/README.md | 3 + ...shPmdMaterial-CullBack-NoCastShadow.shader | 55 + .../Shaders/MeshPmdMaterial-CullBack.shader | 49 + .../MeshPmdMaterial-NoCastShadow.shader | 55 + ...aterial-Trans-CullBack-NoCastShadow.shader | 56 + .../MeshPmdMaterial-Trans-CullBack.shader | 76 + .../MeshPmdMaterial-Trans-NoCastShadow.shader | 66 + .../Shaders/MeshPmdMaterial-Trans.shader | 86 + .../Shaders/MeshPmdMaterial.shader | 49 + .../Shaders/MeshPmdMaterialDummy.shader | 55 + ...terialOutline-CullBack-NoCastShadow.shader | 66 + .../MeshPmdMaterialOutline-CullBack.shader | 60 + ...MeshPmdMaterialOutline-NoCastShadow.shader | 66 + ...Outline-Trans-CullBack-NoCastShadow.shader | 71 + ...shPmdMaterialOutline-Trans-CullBack.shader | 91 + ...dMaterialOutline-Trans-NoCastShadow.shader | 81 + .../MeshPmdMaterialOutline-Trans.shader | 101 + .../Shaders/MeshPmdMaterialOutline.shader | 60 + .../MeshPmdMaterialShadowVertFrag.cginc | 42 + .../Shaders/MeshPmdMaterialSurface.cginc | 89 + .../Shaders/MeshPmdMaterialVertFrag.cginc | 45 + .../Resources/PMDMaterial/Toons/toon.png | 3 + .../Resources/PhysicsManager.cs | 30 + .../Resources/toon/toon00.bmp | 3 + .../Resources/toon/toon01.bmp | 3 + .../Resources/toon/toon02.bmp | 3 + .../Resources/toon/toon03.bmp | 3 + .../Resources/toon/toon04.bmp | 3 + .../Resources/toon/toon05.bmp | 3 + .../Resources/toon/toon06.bmp | 3 + .../Resources/toon/toon07.bmp | 3 + .../Resources/toon/toon08.bmp | 3 + .../Resources/toon/toon09.bmp | 3 + .../Resources/toon/toon10.bmp | 3 + .../Scripts/3rd/mmd-for-unity-master/logo.png | 3 + .../3rd/mmd-for-unity-master/readme.html | 129 ++ .../3rd/mmd-for-unity-master/tutorial.md | 3 + Assets/Scripts/AssetBatchRenamer.cs | 89 + Assets/Scripts/AssetBatchRenamer.cs.meta | 2 + Assets/Scripts/AvatarComponetCopier.cs | 755 ++++++ Assets/Scripts/AvatarComponetCopier.cs.meta | 2 + Assets/Scripts/Bitd.meta | 8 + Assets/Scripts/Bitd/Materials.meta | 8 + Assets/Scripts/Bitd/Materials/FakeShadow.mat | 768 +++++++ .../Bitd/Materials/FakeShadow.mat.meta | 8 + .../Bitd/Materials/FakeShadow_Body.mat | 768 +++++++ .../Bitd/Materials/FakeShadow_Body.mat.meta | 8 + Assets/Scripts/Bitd/Scripts.meta | 8 + Assets/Scripts/Bitd/Scripts/ARKitAdder.cs | 297 +++ .../Scripts/Bitd/Scripts/ARKitAdder.cs.meta | 11 + .../Bitd/Scripts/BlendshapeModifier.cs | 261 +++ .../Bitd/Scripts/BlendshapeModifier.cs.meta | 11 + Assets/Scripts/Bitd/Scripts/DduDda.cs | 94 + Assets/Scripts/Bitd/Scripts/DduDda.cs.meta | 11 + Assets/Scripts/Bitd/Scripts/FunctionAdder.cs | 292 +++ .../Bitd/Scripts/FunctionAdder.cs.meta | 11 + .../Bitd/Scripts/LiltoonOutlineModifier.cs | 145 ++ .../Scripts/LiltoonOutlineModifier.cs.meta | 11 + .../Bitd/Scripts/LiltoonRimLightModifier.cs | 278 +++ .../Scripts/LiltoonRimLightModifier.cs.meta | 11 + .../Bitd/Scripts/LiltoonShadowAdder.cs | 142 ++ .../Bitd/Scripts/LiltoonShadowAdder.cs.meta | 11 + .../Bitd/Scripts/LiltoonShadowModifier.cs | 287 +++ .../Scripts/LiltoonShadowModifier.cs.meta | 11 + .../Bitd/Scripts/LiltoonStencilPassSetter.cs | 143 ++ .../Scripts/LiltoonStencilPassSetter.cs.meta | 11 + Assets/Scripts/Bitd/Scripts/MatsReplacer.cs | 274 +++ .../Scripts/Bitd/Scripts/MatsReplacer.cs.meta | 11 + .../Bitd/Scripts/MissingScriptRemover.cs | 100 + .../Bitd/Scripts/MissingScriptRemover.cs.meta | 11 + .../Scripts/MultiUnitypackageInstaller.cs | 122 + .../MultiUnitypackageInstaller.cs.meta | 11 + .../Scripts/NilotoonMaterialMatcapSetter.cs | 213 ++ .../NilotoonMaterialMatcapSetter.cs.meta | 11 + Assets/Scripts/BlendShapesRename.meta | 8 + .../BlendShapesRename/BlendShapesRename.cs | 112 + .../BlendShapesRename.cs.meta | 11 + Assets/Scripts/Camera Composition.meta | 8 + .../Camera Composition/Camera Composition.zip | 3 + .../Camera Composition.zip.meta | 7 + .../Camera Composition/CameraComposition.pdf | 3 + .../CameraComposition.pdf.meta | 14 + .../Scripts/Camera Composition/Changelog.txt | 3 + .../Camera Composition/Changelog.txt.meta | 14 + Assets/Scripts/Camera Composition/README.txt | 3 + .../Camera Composition/README.txt.meta | 14 + .../Scripts/Camera Composition/Scripts.meta | 8 + .../Scripts/CameraComposition.asmdef | 14 + .../Scripts/CameraComposition.asmdef.meta | 14 + .../Scripts/CompositionOverlay.cs | 81 + .../Scripts/CompositionOverlay.cs.meta | 18 + .../Camera Composition/Scripts/Editor.meta | 8 + .../Scripts/Editor/CameraComposition.cs | 236 ++ .../Scripts/Editor/CameraComposition.cs.meta | 18 + .../Camera Composition/Scripts/Resources.meta | 8 + .../Scripts/Resources/Overlays.meta | 8 + .../Resources/Overlays/overlays.cross.png | 3 + .../Overlays/overlays.cross.png.meta | 117 + .../Resources/Overlays/overlays.diagonal.png | 3 + .../Overlays/overlays.diagonal.png.meta | 115 + .../Overlays/overlays.goldenratio.png | 3 + .../Overlays/overlays.goldenratio.png.meta | 115 + .../Overlays/overlays.goldenspiral.png | 3 + .../Overlays/overlays.goldenspiral.png.meta | 115 + .../Overlays/overlays.ruleofthirds.png | 3 + .../Overlays/overlays.ruleofthirds.png.meta | 115 + .../Scripts/Resources/Prefabs.meta | 8 + .../Prefabs/Camera Composition.prefab | 3 + .../Prefabs/Camera Composition.prefab.meta | 14 + Assets/Scripts/Editor.meta | 8 + Assets/Scripts/Editor/MMD2UnityToolMenu.cs | 41 + .../Scripts/Editor/MMD2UnityToolMenu.cs.meta | 11 + Assets/Scripts/Editor/Private.meta | 8 + .../Scripts/Editor/Private/CameraVmdAgent.cs | 43 + .../Editor/Private/CameraVmdAgent.cs.meta | 11 + .../Editor/Private/FbxConverterTool.cs | 41 + .../Editor/Private/FbxConverterTool.cs.meta | 11 + .../Editor/Private/VMDCameraConverter.cs | 317 +++ .../Editor/Private/VMDCameraConverter.cs.meta | 11 + Assets/Scripts/FindUnusedBones.meta | 8 + .../FindUnusedBones/FindUnusedBones.cs | 109 + .../FindUnusedBones/FindUnusedBones.cs.meta | 11 + .../MaterialAndTextureCollectorWindow.cs | 248 ++ .../MaterialAndTextureCollectorWindow.cs.meta | 2 + Assets/Scripts/MaterialMover.cs | 287 +++ Assets/Scripts/MaterialMover.cs.meta | 2 + .../Scripts/NilotoonMaterialMatcapSetter.cs | 214 ++ .../NilotoonMaterialMatcapSetter.cs.meta | 2 + Assets/Scripts/ObjectNameChanger.cs | 198 ++ Assets/Scripts/ObjectNameChanger.cs.meta | 2 + Assets/Scripts/QA_Select.cs | 47 + Assets/Scripts/QA_Select.cs.meta | 11 + Assets/Scripts/RecompileScript.cs | 12 + Assets/Scripts/RecompileScript.cs.meta | 11 + Assets/Scripts/RenameHumanoidBones.cs | 127 + Assets/Scripts/RenameHumanoidBones.cs.meta | 2 + Assets/Scripts/SkyboxRotator.meta | 8 + Assets/Scripts/SkyboxRotator/SkyboxRotator.cs | 44 + .../SkyboxRotator/SkyboxRotator.cs.meta | 11 + Assets/Scripts/TimelineStopper.meta | 8 + .../TimelineStopper/Notification Receiver.cs | 32 + .../Notification Receiver.cs.meta | 2 + Assets/Scripts/TimelineStopper/PauseMarker.cs | 10 + .../TimelineStopper/PauseMarker.cs.meta | 2 + Assets/Settings/DefaultVolumeProfile.asset | 1832 +++++++++++++++ .../Settings/DefaultVolumeProfile.asset.meta | 8 + Assets/Settings/Mobile_RPAsset.asset | 135 ++ Assets/Settings/Mobile_RPAsset.asset.meta | 8 + Assets/Settings/Mobile_Renderer.asset | 130 ++ Assets/Settings/Mobile_Renderer.asset.meta | 8 + Assets/Settings/PC_RPAsset.asset | 137 ++ Assets/Settings/PC_RPAsset.asset.meta | 8 + Assets/Settings/PC_Renderer.asset | 294 +++ Assets/Settings/PC_Renderer.asset.meta | 8 + Assets/Settings/SampleSceneProfile.asset | 159 ++ Assets/Settings/SampleSceneProfile.asset.meta | 8 + ...niversalRenderPipelineGlobalSettings.asset | 261 +++ ...salRenderPipelineGlobalSettings.asset.meta | 8 + 355 files changed, 34487 insertions(+) create mode 100644 Assets/External/Fantasy Skybox.meta create mode 100644 Assets/External/Fantasy Skybox/ReleaseNotes.txt create mode 100644 Assets/External/Fantasy Skybox/ReleaseNotes.txt.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/BD Studios Post-Processing Profile.asset create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/BD Studios Post-Processing Profile.asset.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/BD_Lighting.lighting create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/BD_Lighting.lighting.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Demo.unity create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Demo.unity.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy01.mat create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy01.mat.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy02.mat create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy02.mat.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy03.mat create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy03.mat.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy04.mat create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy04.mat.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn.mat create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn.mat.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn_Cloudy.mat create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn_Cloudy.mat.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Day_Clear.mat create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Day_Clear.mat.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight.mat create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight.mat.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars.mat create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars.mat.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars02.mat create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars02.mat.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset.mat create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset.mat.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset_Cloudy.mat create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset_Cloudy.mat.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy01.png create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy01.png.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy02.png create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy02.png.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy03.png create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy03.png.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy04.png create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy04.png.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn.png create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn.png.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn_Cloudy.png create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn_Cloudy.png.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Day_Clear.png create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Day_Clear.png.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight.png create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight.png.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars.png create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars.png.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars02.png create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars02.png.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset.png create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset.png.meta create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset_Cloudy.png create mode 100644 Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset_Cloudy.png.meta create mode 100644 Assets/Scenes/123.unity create mode 100644 Assets/Scenes/123.unity.meta create mode 100644 Assets/Scenes/SampleScene.unity create mode 100644 Assets/Scenes/SampleScene.unity.meta create mode 100644 Assets/Scripts/3rd.meta create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master.meta create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/Local.testsettings create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker.vsmdi create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker/IK_Test.vmd create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker/Program.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker/Properties/AssemblyInfo.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker/TrueMyHeart.vmd create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker/miku.pmd create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Form1.Designer.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Form1.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Form1.resx create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Program.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/AssemblyInfo.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Resources.Designer.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Resources.resx create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Settings.Designer.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Settings.settings create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/bin/Debug/MMDBoneBakerLibrary.dll create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/bin/Debug/MMDIKBakerGUI.exe create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/bin/Debug/MMDIKBakerGUI.vshost.exe create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/bin/Debug/MMDModelLibrary.dll create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/bin/Debug/MMDMotionLibrary.dll create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/IKBaker.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/BezireCurve.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/CCDSolver.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/DefaultIKLimitter.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/IIKLimitter.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/IIKSolver.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/MathHelper.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Matrix.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Quaternion.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/SQTTransform.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Vector2.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Vector3.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/MMDBone.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/MMDBoneManager.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/MMDIK.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/ModelConverter.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/AnimationPlayer.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDBoneKeyFrame.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDFaceKeyFrame.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDMotion.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDMotionTrack.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MotionConverter.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MotionHelper.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Properties/AssemblyInfo.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/MatrixTest.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/Properties/AssemblyInfo.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/QuaternionTest.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/Vector3Test.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/CoordinateType.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/MMDModel.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/ModelManager.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Properties/AssemblyInfo.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/MMDModel1.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelBone.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelBoneDisp.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelBoneDispName.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelHeader.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelIK.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelJoint.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelMaterial.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelRigidBody.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelSkin.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelVertex.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/CoordinateType.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/MMDMotion.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/CameraMotionData.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/FaceMotionData.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/LightMotionData.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/MMDMotion2.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/MotionData.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/MotionManager.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Properties/AssemblyInfo.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/TraceAndTestImpact.testsettings create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/.gitignore create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/CHANGE-LOG create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/Config/Config.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/Config/ConfigWindow.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/ExpressionManagerEditor.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/InspectorBase.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/PMDInspector.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/PMDScriptableObject.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/ScriptableObjectBase.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/VMDInspector.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/VMDScriptableObject.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDEngineEditor.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/LoadedWindow.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/PMDLoaderWindow.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/AlphaReadableTexture.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/AlphaReadableTextureDirectoryImporter.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/AvatarSettingScript.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/ComputeSkin.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/MMDFormat.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/MMDMathf.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/ModelAgent.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/MotionAgent.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMDConverter.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMDLoaderScript.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXConverter.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXLoaderScript.PMD2PMX.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXLoaderScript.PMX2PMD.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXLoaderScript.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/VMDConverter.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/VMDLoaderScript.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/VMDLoaderWindow.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/MorphManagerEditor.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/PhysicsManagerEditor.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/Private/XFileConverter.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/Private/XFileFormat.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/Private/XFileImporter.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/XFileImporterWindow.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/LICENSE create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/README.md create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/ExpressionManagerScript.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/HalfLambert.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/IK/BoneController.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/IK/CCDIKSolver.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/MMDEngine.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/MMDSkinsScript.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/BoneMorph.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/GroupMorph.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/MaterialMorph.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/MorphBase.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/MorphManager.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/UvMorph.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/VertexMorph.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/LICENSE create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material Transparent.mat create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material with Outline Transparent.mat create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material with Outline.mat create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material.mat create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/README.md create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-CullBack-NoCastShadow.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-CullBack.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-NoCastShadow.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans-CullBack-NoCastShadow.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans-CullBack.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans-NoCastShadow.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialDummy.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-CullBack-NoCastShadow.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-CullBack.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-NoCastShadow.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack-NoCastShadow.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-NoCastShadow.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline.shader create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialShadowVertFrag.cginc create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialSurface.cginc create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialVertFrag.cginc create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Toons/toon.png create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/PhysicsManager.cs create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon00.bmp create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon01.bmp create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon02.bmp create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon03.bmp create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon04.bmp create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon05.bmp create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon06.bmp create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon07.bmp create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon08.bmp create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon09.bmp create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon10.bmp create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/logo.png create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/readme.html create mode 100644 Assets/Scripts/3rd/mmd-for-unity-master/tutorial.md create mode 100644 Assets/Scripts/AssetBatchRenamer.cs create mode 100644 Assets/Scripts/AssetBatchRenamer.cs.meta create mode 100644 Assets/Scripts/AvatarComponetCopier.cs create mode 100644 Assets/Scripts/AvatarComponetCopier.cs.meta create mode 100644 Assets/Scripts/Bitd.meta create mode 100644 Assets/Scripts/Bitd/Materials.meta create mode 100644 Assets/Scripts/Bitd/Materials/FakeShadow.mat create mode 100644 Assets/Scripts/Bitd/Materials/FakeShadow.mat.meta create mode 100644 Assets/Scripts/Bitd/Materials/FakeShadow_Body.mat create mode 100644 Assets/Scripts/Bitd/Materials/FakeShadow_Body.mat.meta create mode 100644 Assets/Scripts/Bitd/Scripts.meta create mode 100644 Assets/Scripts/Bitd/Scripts/ARKitAdder.cs create mode 100644 Assets/Scripts/Bitd/Scripts/ARKitAdder.cs.meta create mode 100644 Assets/Scripts/Bitd/Scripts/BlendshapeModifier.cs create mode 100644 Assets/Scripts/Bitd/Scripts/BlendshapeModifier.cs.meta create mode 100644 Assets/Scripts/Bitd/Scripts/DduDda.cs create mode 100644 Assets/Scripts/Bitd/Scripts/DduDda.cs.meta create mode 100644 Assets/Scripts/Bitd/Scripts/FunctionAdder.cs create mode 100644 Assets/Scripts/Bitd/Scripts/FunctionAdder.cs.meta create mode 100644 Assets/Scripts/Bitd/Scripts/LiltoonOutlineModifier.cs create mode 100644 Assets/Scripts/Bitd/Scripts/LiltoonOutlineModifier.cs.meta create mode 100644 Assets/Scripts/Bitd/Scripts/LiltoonRimLightModifier.cs create mode 100644 Assets/Scripts/Bitd/Scripts/LiltoonRimLightModifier.cs.meta create mode 100644 Assets/Scripts/Bitd/Scripts/LiltoonShadowAdder.cs create mode 100644 Assets/Scripts/Bitd/Scripts/LiltoonShadowAdder.cs.meta create mode 100644 Assets/Scripts/Bitd/Scripts/LiltoonShadowModifier.cs create mode 100644 Assets/Scripts/Bitd/Scripts/LiltoonShadowModifier.cs.meta create mode 100644 Assets/Scripts/Bitd/Scripts/LiltoonStencilPassSetter.cs create mode 100644 Assets/Scripts/Bitd/Scripts/LiltoonStencilPassSetter.cs.meta create mode 100644 Assets/Scripts/Bitd/Scripts/MatsReplacer.cs create mode 100644 Assets/Scripts/Bitd/Scripts/MatsReplacer.cs.meta create mode 100644 Assets/Scripts/Bitd/Scripts/MissingScriptRemover.cs create mode 100644 Assets/Scripts/Bitd/Scripts/MissingScriptRemover.cs.meta create mode 100644 Assets/Scripts/Bitd/Scripts/MultiUnitypackageInstaller.cs create mode 100644 Assets/Scripts/Bitd/Scripts/MultiUnitypackageInstaller.cs.meta create mode 100644 Assets/Scripts/Bitd/Scripts/NilotoonMaterialMatcapSetter.cs create mode 100644 Assets/Scripts/Bitd/Scripts/NilotoonMaterialMatcapSetter.cs.meta create mode 100644 Assets/Scripts/BlendShapesRename.meta create mode 100644 Assets/Scripts/BlendShapesRename/BlendShapesRename.cs create mode 100644 Assets/Scripts/BlendShapesRename/BlendShapesRename.cs.meta create mode 100644 Assets/Scripts/Camera Composition.meta create mode 100644 Assets/Scripts/Camera Composition/Camera Composition.zip create mode 100644 Assets/Scripts/Camera Composition/Camera Composition.zip.meta create mode 100644 Assets/Scripts/Camera Composition/CameraComposition.pdf create mode 100644 Assets/Scripts/Camera Composition/CameraComposition.pdf.meta create mode 100644 Assets/Scripts/Camera Composition/Changelog.txt create mode 100644 Assets/Scripts/Camera Composition/Changelog.txt.meta create mode 100644 Assets/Scripts/Camera Composition/README.txt create mode 100644 Assets/Scripts/Camera Composition/README.txt.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/CameraComposition.asmdef create mode 100644 Assets/Scripts/Camera Composition/Scripts/CameraComposition.asmdef.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/CompositionOverlay.cs create mode 100644 Assets/Scripts/Camera Composition/Scripts/CompositionOverlay.cs.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/Editor.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/Editor/CameraComposition.cs create mode 100644 Assets/Scripts/Camera Composition/Scripts/Editor/CameraComposition.cs.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Overlays.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.cross.png create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.cross.png.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.diagonal.png create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.diagonal.png.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenratio.png create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenratio.png.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenspiral.png create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenspiral.png.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.ruleofthirds.png create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.ruleofthirds.png.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Prefabs.meta create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Prefabs/Camera Composition.prefab create mode 100644 Assets/Scripts/Camera Composition/Scripts/Resources/Prefabs/Camera Composition.prefab.meta create mode 100644 Assets/Scripts/Editor.meta create mode 100644 Assets/Scripts/Editor/MMD2UnityToolMenu.cs create mode 100644 Assets/Scripts/Editor/MMD2UnityToolMenu.cs.meta create mode 100644 Assets/Scripts/Editor/Private.meta create mode 100644 Assets/Scripts/Editor/Private/CameraVmdAgent.cs create mode 100644 Assets/Scripts/Editor/Private/CameraVmdAgent.cs.meta create mode 100644 Assets/Scripts/Editor/Private/FbxConverterTool.cs create mode 100644 Assets/Scripts/Editor/Private/FbxConverterTool.cs.meta create mode 100644 Assets/Scripts/Editor/Private/VMDCameraConverter.cs create mode 100644 Assets/Scripts/Editor/Private/VMDCameraConverter.cs.meta create mode 100644 Assets/Scripts/FindUnusedBones.meta create mode 100644 Assets/Scripts/FindUnusedBones/FindUnusedBones.cs create mode 100644 Assets/Scripts/FindUnusedBones/FindUnusedBones.cs.meta create mode 100644 Assets/Scripts/MaterialAndTextureCollectorWindow.cs create mode 100644 Assets/Scripts/MaterialAndTextureCollectorWindow.cs.meta create mode 100644 Assets/Scripts/MaterialMover.cs create mode 100644 Assets/Scripts/MaterialMover.cs.meta create mode 100644 Assets/Scripts/NilotoonMaterialMatcapSetter.cs create mode 100644 Assets/Scripts/NilotoonMaterialMatcapSetter.cs.meta create mode 100644 Assets/Scripts/ObjectNameChanger.cs create mode 100644 Assets/Scripts/ObjectNameChanger.cs.meta create mode 100644 Assets/Scripts/QA_Select.cs create mode 100644 Assets/Scripts/QA_Select.cs.meta create mode 100644 Assets/Scripts/RecompileScript.cs create mode 100644 Assets/Scripts/RecompileScript.cs.meta create mode 100644 Assets/Scripts/RenameHumanoidBones.cs create mode 100644 Assets/Scripts/RenameHumanoidBones.cs.meta create mode 100644 Assets/Scripts/SkyboxRotator.meta create mode 100644 Assets/Scripts/SkyboxRotator/SkyboxRotator.cs create mode 100644 Assets/Scripts/SkyboxRotator/SkyboxRotator.cs.meta create mode 100644 Assets/Scripts/TimelineStopper.meta create mode 100644 Assets/Scripts/TimelineStopper/Notification Receiver.cs create mode 100644 Assets/Scripts/TimelineStopper/Notification Receiver.cs.meta create mode 100644 Assets/Scripts/TimelineStopper/PauseMarker.cs create mode 100644 Assets/Scripts/TimelineStopper/PauseMarker.cs.meta create mode 100644 Assets/Settings/DefaultVolumeProfile.asset create mode 100644 Assets/Settings/DefaultVolumeProfile.asset.meta create mode 100644 Assets/Settings/Mobile_RPAsset.asset create mode 100644 Assets/Settings/Mobile_RPAsset.asset.meta create mode 100644 Assets/Settings/Mobile_Renderer.asset create mode 100644 Assets/Settings/Mobile_Renderer.asset.meta create mode 100644 Assets/Settings/PC_RPAsset.asset create mode 100644 Assets/Settings/PC_RPAsset.asset.meta create mode 100644 Assets/Settings/PC_Renderer.asset create mode 100644 Assets/Settings/PC_Renderer.asset.meta create mode 100644 Assets/Settings/SampleSceneProfile.asset create mode 100644 Assets/Settings/SampleSceneProfile.asset.meta create mode 100644 Assets/Settings/UniversalRenderPipelineGlobalSettings.asset create mode 100644 Assets/Settings/UniversalRenderPipelineGlobalSettings.asset.meta diff --git a/Assets/External/Fantasy Skybox.meta b/Assets/External/Fantasy Skybox.meta new file mode 100644 index 000000000..5e6bd2c20 --- /dev/null +++ b/Assets/External/Fantasy Skybox.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ef1cb0fe8d3d5584d968a603ac0bde56 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/Fantasy Skybox/ReleaseNotes.txt b/Assets/External/Fantasy Skybox/ReleaseNotes.txt new file mode 100644 index 000000000..b4d47111d --- /dev/null +++ b/Assets/External/Fantasy Skybox/ReleaseNotes.txt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:662b405c9bb5f9eda217ceb19b6e0de80b4c3e23621c950e3f754b26404db156 +size 3122 diff --git a/Assets/External/Fantasy Skybox/ReleaseNotes.txt.meta b/Assets/External/Fantasy Skybox/ReleaseNotes.txt.meta new file mode 100644 index 000000000..9942622e0 --- /dev/null +++ b/Assets/External/Fantasy Skybox/ReleaseNotes.txt.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: f14307b5201ecdf4e89f2c843bdec16c +timeCreated: 1434912371 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 18216 + packageName: Fantasy Skybox + packageVersion: 1.6.7 + assetPath: Assets/Fantasy Skybox/ReleaseNotes.txt + uploadId: 709120 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox.meta b/Assets/External/Free Stylized Hand-Painted Skybox.meta new file mode 100644 index 000000000..dfcf7461b --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 617f13ee40e80a14f839790660d6261c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/BD Studios Post-Processing Profile.asset b/Assets/External/Free Stylized Hand-Painted Skybox/BD Studios Post-Processing Profile.asset new file mode 100644 index 000000000..f135814bb --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/BD Studios Post-Processing Profile.asset @@ -0,0 +1,1522 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-6121356625829328324 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 40b924e2dad56384a8df2a1e111bb675, type: 3} + m_Name: Vignette + m_EditorClassIdentifier: + active: 1 + enabled: + overrideState: 1 + value: 1 + mode: + overrideState: 0 + value: 0 + color: + overrideState: 0 + value: {r: 0, g: 0, b: 0, a: 1} + center: + overrideState: 0 + value: {x: 0.5, y: 0.5} + intensity: + overrideState: 1 + value: 0.26 + smoothness: + overrideState: 1 + value: 0.128 + roundness: + overrideState: 0 + value: 1 + rounded: + overrideState: 0 + value: 0 + mask: + overrideState: 0 + value: {fileID: 0} + defaultState: 1 + opacity: + overrideState: 0 + value: 1 +--- !u!114 &-6114600444338696570 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 48a79b01ea5641d4aa6daa2e23605641, type: 3} + m_Name: Bloom + m_EditorClassIdentifier: + active: 1 + enabled: + overrideState: 1 + value: 1 + intensity: + overrideState: 1 + value: 0.4 + threshold: + overrideState: 1 + value: 0.73 + softKnee: + overrideState: 0 + value: 0.5 + clamp: + overrideState: 0 + value: 65472 + diffusion: + overrideState: 0 + value: 7 + anamorphicRatio: + overrideState: 0 + value: 0 + color: + overrideState: 1 + value: {r: 1, g: 0.9494407, b: 0.9103774, a: 1} + fastMode: + overrideState: 0 + value: 0 + dirtTexture: + overrideState: 0 + value: {fileID: 0} + defaultState: 1 + dirtIntensity: + overrideState: 0 + value: 0 +--- !u!114 &-5399058212381721059 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: c1cb7e9e120078f43bce4f0b1be547a7, type: 3} + m_Name: AmbientOcclusion + m_EditorClassIdentifier: + active: 1 + enabled: + overrideState: 1 + value: 1 + mode: + overrideState: 1 + value: 1 + intensity: + overrideState: 1 + value: 1.19 + color: + overrideState: 1 + value: {r: 0, g: 0, b: 0, a: 1} + ambientOnly: + overrideState: 1 + value: 0 + noiseFilterTolerance: + overrideState: 0 + value: 0 + blurTolerance: + overrideState: 0 + value: -4.6 + upsampleTolerance: + overrideState: 0 + value: -12 + thicknessModifier: + overrideState: 1 + value: 1 + directLightingStrength: + overrideState: 0 + value: 0 + radius: + overrideState: 0 + value: 0.25 + quality: + overrideState: 0 + value: 2 +--- !u!114 &-270372995244880535 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 556797029e73b2347956b6579e77e05b, type: 3} + m_Name: DepthOfField + m_EditorClassIdentifier: + active: 0 + enabled: + overrideState: 1 + value: 1 + focusDistance: + overrideState: 1 + value: 4.2 + aperture: + overrideState: 0 + value: 5.6 + focalLength: + overrideState: 0 + value: 50 + kernelSize: + overrideState: 0 + value: 1 +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 8e6292b2c06870d4495f009f912b9600, type: 3} + m_Name: BD Studios Post-Processing Profile + m_EditorClassIdentifier: + settings: + - {fileID: -5399058212381721059} + - {fileID: -6114600444338696570} + - {fileID: 7703522721035351794} + - {fileID: -270372995244880535} + - {fileID: 154684449965798654} + - {fileID: -6121356625829328324} +--- !u!114 &154684449965798654 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: b94fcd11afffcb142908bfcb1e261fba, type: 3} + m_Name: MotionBlur + m_EditorClassIdentifier: + active: 1 + enabled: + overrideState: 1 + value: 1 + shutterAngle: + overrideState: 1 + value: 270 + sampleCount: + overrideState: 1 + value: 10 +--- !u!114 &7703522721035351794 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: adb84e30e02715445aeb9959894e3b4d, type: 3} + m_Name: ColorGrading + m_EditorClassIdentifier: + active: 1 + enabled: + overrideState: 1 + value: 1 + gradingMode: + overrideState: 1 + value: 1 + externalLut: + overrideState: 0 + value: {fileID: 0} + defaultState: 1 + tonemapper: + overrideState: 1 + value: 2 + toneCurveToeStrength: + overrideState: 0 + value: 0 + toneCurveToeLength: + overrideState: 0 + value: 0.5 + toneCurveShoulderStrength: + overrideState: 0 + value: 0 + toneCurveShoulderLength: + overrideState: 0 + value: 0.5 + toneCurveShoulderAngle: + overrideState: 0 + value: 0 + toneCurveGamma: + overrideState: 0 + value: 1 + ldrLut: + overrideState: 0 + value: {fileID: 0} + defaultState: 4 + ldrLutContribution: + overrideState: 0 + value: 1 + temperature: + overrideState: 1 + value: 5 + tint: + overrideState: 1 + value: 0 + colorFilter: + overrideState: 0 + value: {r: 1, g: 1, b: 1, a: 1} + hueShift: + overrideState: 0 + value: 0 + saturation: + overrideState: 1 + value: 18.4 + brightness: + overrideState: 0 + value: 0 + postExposure: + overrideState: 1 + value: 0.37 + contrast: + overrideState: 1 + value: 18.5 + mixerRedOutRedIn: + overrideState: 0 + value: 100 + mixerRedOutGreenIn: + overrideState: 0 + value: 0 + mixerRedOutBlueIn: + overrideState: 0 + value: 0 + mixerGreenOutRedIn: + overrideState: 0 + value: 0 + mixerGreenOutGreenIn: + overrideState: 0 + value: 100 + mixerGreenOutBlueIn: + overrideState: 0 + value: 0 + mixerBlueOutRedIn: + overrideState: 0 + value: 0 + mixerBlueOutGreenIn: + overrideState: 0 + value: 0 + mixerBlueOutBlueIn: + overrideState: 0 + value: 100 + lift: + overrideState: 0 + value: {x: 0.98793775, y: 1, z: 0.9846576, w: 0} + gamma: + overrideState: 0 + value: {x: 0.9592483, y: 0.9712873, z: 1, w: 0} + gain: + overrideState: 0 + value: {x: 1, y: 0.97258776, z: 0.996861, w: 0} + masterCurve: + overrideState: 0 + value: + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Loop: 0 + m_ZeroValue: 0 + m_Range: 1 + cachedData: + - 0 + - 0.0078125 + - 0.015625 + - 0.0234375 + - 0.03125 + - 0.0390625 + - 0.046875 + - 0.0546875 + - 0.0625 + - 0.0703125 + - 0.078125 + - 0.0859375 + - 0.09375 + - 0.1015625 + - 0.109375 + - 0.1171875 + - 0.125 + - 0.1328125 + - 0.140625 + - 0.1484375 + - 0.15625 + - 0.1640625 + - 0.171875 + - 0.1796875 + - 0.1875 + - 0.1953125 + - 0.203125 + - 0.2109375 + - 0.21875 + - 0.2265625 + - 0.234375 + - 0.2421875 + - 0.25 + - 0.2578125 + - 0.265625 + - 0.2734375 + - 0.28125 + - 0.2890625 + - 0.296875 + - 0.3046875 + - 0.3125 + - 0.3203125 + - 0.328125 + - 0.3359375 + - 0.34375 + - 0.3515625 + - 0.359375 + - 0.3671875 + - 0.375 + - 0.3828125 + - 0.390625 + - 0.3984375 + - 0.40625 + - 0.4140625 + - 0.421875 + - 0.4296875 + - 0.4375 + - 0.4453125 + - 0.453125 + - 0.4609375 + - 0.46875 + - 0.4765625 + - 0.484375 + - 0.4921875 + - 0.5 + - 0.5078125 + - 0.515625 + - 0.5234375 + - 0.53125 + - 0.5390625 + - 0.546875 + - 0.5546875 + - 0.5625 + - 0.5703125 + - 0.578125 + - 0.5859375 + - 0.59375 + - 0.6015625 + - 0.609375 + - 0.6171875 + - 0.625 + - 0.6328125 + - 0.640625 + - 0.6484375 + - 0.65625 + - 0.6640625 + - 0.671875 + - 0.6796875 + - 0.6875 + - 0.6953125 + - 0.703125 + - 0.7109375 + - 0.71875 + - 0.7265625 + - 0.734375 + - 0.7421875 + - 0.75 + - 0.7578125 + - 0.765625 + - 0.7734375 + - 0.78125 + - 0.7890625 + - 0.796875 + - 0.8046875 + - 0.8125 + - 0.8203125 + - 0.828125 + - 0.8359375 + - 0.84375 + - 0.8515625 + - 0.859375 + - 0.8671875 + - 0.875 + - 0.8828125 + - 0.890625 + - 0.8984375 + - 0.90625 + - 0.9140625 + - 0.921875 + - 0.9296875 + - 0.9375 + - 0.9453125 + - 0.953125 + - 0.9609375 + - 0.96875 + - 0.9765625 + - 0.984375 + - 0.9921875 + redCurve: + overrideState: 0 + value: + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Loop: 0 + m_ZeroValue: 0 + m_Range: 1 + cachedData: + - 0 + - 0.0078125 + - 0.015625 + - 0.0234375 + - 0.03125 + - 0.0390625 + - 0.046875 + - 0.0546875 + - 0.0625 + - 0.0703125 + - 0.078125 + - 0.0859375 + - 0.09375 + - 0.1015625 + - 0.109375 + - 0.1171875 + - 0.125 + - 0.1328125 + - 0.140625 + - 0.1484375 + - 0.15625 + - 0.1640625 + - 0.171875 + - 0.1796875 + - 0.1875 + - 0.1953125 + - 0.203125 + - 0.2109375 + - 0.21875 + - 0.2265625 + - 0.234375 + - 0.2421875 + - 0.25 + - 0.2578125 + - 0.265625 + - 0.2734375 + - 0.28125 + - 0.2890625 + - 0.296875 + - 0.3046875 + - 0.3125 + - 0.3203125 + - 0.328125 + - 0.3359375 + - 0.34375 + - 0.3515625 + - 0.359375 + - 0.3671875 + - 0.375 + - 0.3828125 + - 0.390625 + - 0.3984375 + - 0.40625 + - 0.4140625 + - 0.421875 + - 0.4296875 + - 0.4375 + - 0.4453125 + - 0.453125 + - 0.4609375 + - 0.46875 + - 0.4765625 + - 0.484375 + - 0.4921875 + - 0.5 + - 0.5078125 + - 0.515625 + - 0.5234375 + - 0.53125 + - 0.5390625 + - 0.546875 + - 0.5546875 + - 0.5625 + - 0.5703125 + - 0.578125 + - 0.5859375 + - 0.59375 + - 0.6015625 + - 0.609375 + - 0.6171875 + - 0.625 + - 0.6328125 + - 0.640625 + - 0.6484375 + - 0.65625 + - 0.6640625 + - 0.671875 + - 0.6796875 + - 0.6875 + - 0.6953125 + - 0.703125 + - 0.7109375 + - 0.71875 + - 0.7265625 + - 0.734375 + - 0.7421875 + - 0.75 + - 0.7578125 + - 0.765625 + - 0.7734375 + - 0.78125 + - 0.7890625 + - 0.796875 + - 0.8046875 + - 0.8125 + - 0.8203125 + - 0.828125 + - 0.8359375 + - 0.84375 + - 0.8515625 + - 0.859375 + - 0.8671875 + - 0.875 + - 0.8828125 + - 0.890625 + - 0.8984375 + - 0.90625 + - 0.9140625 + - 0.921875 + - 0.9296875 + - 0.9375 + - 0.9453125 + - 0.953125 + - 0.9609375 + - 0.96875 + - 0.9765625 + - 0.984375 + - 0.9921875 + greenCurve: + overrideState: 0 + value: + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Loop: 0 + m_ZeroValue: 0 + m_Range: 1 + cachedData: + - 0 + - 0.0078125 + - 0.015625 + - 0.0234375 + - 0.03125 + - 0.0390625 + - 0.046875 + - 0.0546875 + - 0.0625 + - 0.0703125 + - 0.078125 + - 0.0859375 + - 0.09375 + - 0.1015625 + - 0.109375 + - 0.1171875 + - 0.125 + - 0.1328125 + - 0.140625 + - 0.1484375 + - 0.15625 + - 0.1640625 + - 0.171875 + - 0.1796875 + - 0.1875 + - 0.1953125 + - 0.203125 + - 0.2109375 + - 0.21875 + - 0.2265625 + - 0.234375 + - 0.2421875 + - 0.25 + - 0.2578125 + - 0.265625 + - 0.2734375 + - 0.28125 + - 0.2890625 + - 0.296875 + - 0.3046875 + - 0.3125 + - 0.3203125 + - 0.328125 + - 0.3359375 + - 0.34375 + - 0.3515625 + - 0.359375 + - 0.3671875 + - 0.375 + - 0.3828125 + - 0.390625 + - 0.3984375 + - 0.40625 + - 0.4140625 + - 0.421875 + - 0.4296875 + - 0.4375 + - 0.4453125 + - 0.453125 + - 0.4609375 + - 0.46875 + - 0.4765625 + - 0.484375 + - 0.4921875 + - 0.5 + - 0.5078125 + - 0.515625 + - 0.5234375 + - 0.53125 + - 0.5390625 + - 0.546875 + - 0.5546875 + - 0.5625 + - 0.5703125 + - 0.578125 + - 0.5859375 + - 0.59375 + - 0.6015625 + - 0.609375 + - 0.6171875 + - 0.625 + - 0.6328125 + - 0.640625 + - 0.6484375 + - 0.65625 + - 0.6640625 + - 0.671875 + - 0.6796875 + - 0.6875 + - 0.6953125 + - 0.703125 + - 0.7109375 + - 0.71875 + - 0.7265625 + - 0.734375 + - 0.7421875 + - 0.75 + - 0.7578125 + - 0.765625 + - 0.7734375 + - 0.78125 + - 0.7890625 + - 0.796875 + - 0.8046875 + - 0.8125 + - 0.8203125 + - 0.828125 + - 0.8359375 + - 0.84375 + - 0.8515625 + - 0.859375 + - 0.8671875 + - 0.875 + - 0.8828125 + - 0.890625 + - 0.8984375 + - 0.90625 + - 0.9140625 + - 0.921875 + - 0.9296875 + - 0.9375 + - 0.9453125 + - 0.953125 + - 0.9609375 + - 0.96875 + - 0.9765625 + - 0.984375 + - 0.9921875 + blueCurve: + overrideState: 0 + value: + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Loop: 0 + m_ZeroValue: 0 + m_Range: 1 + cachedData: + - 0 + - 0.0078125 + - 0.015625 + - 0.0234375 + - 0.03125 + - 0.0390625 + - 0.046875 + - 0.0546875 + - 0.0625 + - 0.0703125 + - 0.078125 + - 0.0859375 + - 0.09375 + - 0.1015625 + - 0.109375 + - 0.1171875 + - 0.125 + - 0.1328125 + - 0.140625 + - 0.1484375 + - 0.15625 + - 0.1640625 + - 0.171875 + - 0.1796875 + - 0.1875 + - 0.1953125 + - 0.203125 + - 0.2109375 + - 0.21875 + - 0.2265625 + - 0.234375 + - 0.2421875 + - 0.25 + - 0.2578125 + - 0.265625 + - 0.2734375 + - 0.28125 + - 0.2890625 + - 0.296875 + - 0.3046875 + - 0.3125 + - 0.3203125 + - 0.328125 + - 0.3359375 + - 0.34375 + - 0.3515625 + - 0.359375 + - 0.3671875 + - 0.375 + - 0.3828125 + - 0.390625 + - 0.3984375 + - 0.40625 + - 0.4140625 + - 0.421875 + - 0.4296875 + - 0.4375 + - 0.4453125 + - 0.453125 + - 0.4609375 + - 0.46875 + - 0.4765625 + - 0.484375 + - 0.4921875 + - 0.5 + - 0.5078125 + - 0.515625 + - 0.5234375 + - 0.53125 + - 0.5390625 + - 0.546875 + - 0.5546875 + - 0.5625 + - 0.5703125 + - 0.578125 + - 0.5859375 + - 0.59375 + - 0.6015625 + - 0.609375 + - 0.6171875 + - 0.625 + - 0.6328125 + - 0.640625 + - 0.6484375 + - 0.65625 + - 0.6640625 + - 0.671875 + - 0.6796875 + - 0.6875 + - 0.6953125 + - 0.703125 + - 0.7109375 + - 0.71875 + - 0.7265625 + - 0.734375 + - 0.7421875 + - 0.75 + - 0.7578125 + - 0.765625 + - 0.7734375 + - 0.78125 + - 0.7890625 + - 0.796875 + - 0.8046875 + - 0.8125 + - 0.8203125 + - 0.828125 + - 0.8359375 + - 0.84375 + - 0.8515625 + - 0.859375 + - 0.8671875 + - 0.875 + - 0.8828125 + - 0.890625 + - 0.8984375 + - 0.90625 + - 0.9140625 + - 0.921875 + - 0.9296875 + - 0.9375 + - 0.9453125 + - 0.953125 + - 0.9609375 + - 0.96875 + - 0.9765625 + - 0.984375 + - 0.9921875 + hueVsHueCurve: + overrideState: 0 + value: + curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Loop: 1 + m_ZeroValue: 0.5 + m_Range: 1 + cachedData: + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + hueVsSatCurve: + overrideState: 0 + value: + curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Loop: 1 + m_ZeroValue: 0.5 + m_Range: 1 + cachedData: + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + satVsSatCurve: + overrideState: 0 + value: + curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Loop: 0 + m_ZeroValue: 0.5 + m_Range: 1 + cachedData: + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + lumVsSatCurve: + overrideState: 0 + value: + curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Loop: 0 + m_ZeroValue: 0.5 + m_Range: 1 + cachedData: + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 + - 0.5 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/BD Studios Post-Processing Profile.asset.meta b/Assets/External/Free Stylized Hand-Painted Skybox/BD Studios Post-Processing Profile.asset.meta new file mode 100644 index 000000000..6561f4e7f --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/BD Studios Post-Processing Profile.asset.meta @@ -0,0 +1,16 @@ +fileFormatVersion: 2 +guid: 06cf16cc9cc7a4f4ca46f643b3c176a9 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/BD Studios Post-Processing + Profile.asset + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/BD_Lighting.lighting b/Assets/External/Free Stylized Hand-Painted Skybox/BD_Lighting.lighting new file mode 100644 index 000000000..88a3fa5dc --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/BD_Lighting.lighting @@ -0,0 +1,64 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!850595691 &4890085278179872738 +LightingSettings: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: BD_Lighting + serializedVersion: 4 + m_GIWorkflowMode: 1 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_RealtimeEnvironmentLighting: 1 + m_BounceScale: 1 + m_AlbedoBoost: 1 + m_IndirectOutputScale: 1 + m_UsingShadowmask: 0 + m_BakeBackend: 2 + m_LightmapMaxSize: 1024 + m_BakeResolution: 20 + m_Padding: 2 + m_LightmapCompression: 3 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAO: 0 + m_MixedBakeMode: 0 + m_LightmapsBakeMode: 1 + m_FilterMode: 1 + m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0} + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_RealtimeResolution: 2 + m_ForceWhiteAlbedo: 0 + m_ForceUpdates: 0 + m_FinalGather: 0 + m_FinalGatherRayCount: 256 + m_FinalGatherFiltering: 1 + m_PVRCulling: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 256 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_LightProbeSampleCountMultiplier: 4 + m_PVRBounces: 2 + m_PVRMinBounces: 2 + m_PVREnvironmentMIS: 1 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_PVRTiledBaking: 0 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/BD_Lighting.lighting.meta b/Assets/External/Free Stylized Hand-Painted Skybox/BD_Lighting.lighting.meta new file mode 100644 index 000000000..b9f07b96a --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/BD_Lighting.lighting.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: 187345041fe57664fae2aa351414b6b6 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 4890085278179872738 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/BD_Lighting.lighting + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Demo.unity b/Assets/External/Free Stylized Hand-Painted Skybox/Demo.unity new file mode 100644 index 000000000..bb5de33ca --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Demo.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d340095d6c5f504dd2232c9ac1d422e68422ba0e7b7f8c88ba62fead7c200969 +size 12013 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Demo.unity.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Demo.unity.meta new file mode 100644 index 000000000..380e77b32 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Demo.unity.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: f976c0a276862634f8b6bf2eaff818fb +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Demo.unity + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials.meta new file mode 100644 index 000000000..1438b814f --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e5cf77ccbc4290e4ca42aa61959b9d79 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy01.mat b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy01.mat new file mode 100644 index 000000000..cf32b26fc --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy01.mat @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Cloudy01 + m_Shader: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Tex: + m_Texture: {fileID: 8900000, guid: e31e2fa4fd8bdaa478f1675cf5762fd7, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Exposure: 1 + - _Rotation: 0 + m_Colors: + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy01.mat.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy01.mat.meta new file mode 100644 index 000000000..6b244b7b2 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy01.mat.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: da04fb2a289ef1b47bf5b07b9285dd70 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Materials/Cloudy01.mat + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy02.mat b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy02.mat new file mode 100644 index 000000000..920f7a0c9 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy02.mat @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Cloudy02 + m_Shader: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Tex: + m_Texture: {fileID: 8900000, guid: f1b504bff46c95346b5b1e99fd731eff, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Exposure: 1 + - _Rotation: 0 + m_Colors: + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy02.mat.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy02.mat.meta new file mode 100644 index 000000000..62f626edd --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy02.mat.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: d4393bf45f92e74499f230d78e8cab9f +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Materials/Cloudy02.mat + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy03.mat b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy03.mat new file mode 100644 index 000000000..8b19c3963 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy03.mat @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Cloudy03 + m_Shader: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Tex: + m_Texture: {fileID: 8900000, guid: 3d60c74e415eb044cb7c63f12a1d955e, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Exposure: 1 + - _Rotation: 0 + m_Colors: + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy03.mat.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy03.mat.meta new file mode 100644 index 000000000..9f1a9c580 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy03.mat.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: 896fe09c49b73a44ead00a982ee46e6b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Materials/Cloudy03.mat + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy04.mat b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy04.mat new file mode 100644 index 000000000..854239449 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy04.mat @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Cloudy04 + m_Shader: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Tex: + m_Texture: {fileID: 8900000, guid: 663e4e044569d5d4fab103ab8ae7719c, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Exposure: 1 + - _Rotation: 0 + m_Colors: + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy04.mat.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy04.mat.meta new file mode 100644 index 000000000..de626fb38 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Cloudy04.mat.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: b01d8a5305a527c4daeab5318708e238 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Materials/Cloudy04.mat + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn.mat b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn.mat new file mode 100644 index 000000000..96a7eb14b --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn.mat @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Dawn + m_Shader: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Tex: + m_Texture: {fileID: 8900000, guid: 41662f129e3c1054392aed1755433fd5, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Exposure: 1 + - _Rotation: 0 + m_Colors: + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn.mat.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn.mat.meta new file mode 100644 index 000000000..b828f887b --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn.mat.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: b73dc2c0c9eceae4486bdb5b744fceb9 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Materials/Dawn.mat + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn_Cloudy.mat b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn_Cloudy.mat new file mode 100644 index 000000000..b55d9fbba --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn_Cloudy.mat @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Dawn_Cloudy + m_Shader: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Tex: + m_Texture: {fileID: 8900000, guid: eb2951db9066f984f85ff41f6e9525f7, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Exposure: 1 + - _Rotation: 0 + m_Colors: + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn_Cloudy.mat.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn_Cloudy.mat.meta new file mode 100644 index 000000000..e55d8571f --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Dawn_Cloudy.mat.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: 3776415b8d326db4cb696fe00db0540e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Materials/Dawn_Cloudy.mat + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Day_Clear.mat b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Day_Clear.mat new file mode 100644 index 000000000..15abce43d --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Day_Clear.mat @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Day_Clear + m_Shader: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Tex: + m_Texture: {fileID: 8900000, guid: 4c6e3caff9a2c00459a8805bc96f8f69, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Exposure: 1 + - _Rotation: 0 + m_Colors: + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Day_Clear.mat.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Day_Clear.mat.meta new file mode 100644 index 000000000..9f26fb853 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Day_Clear.mat.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: 1e5e82b01cae80b44b78975b9c2d7741 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Materials/Day_Clear.mat + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight.mat b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight.mat new file mode 100644 index 000000000..877c149e8 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight.mat @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Midnight + m_Shader: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Tex: + m_Texture: {fileID: 8900000, guid: ba4f9681a4f907647a229035e27b138a, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Exposure: 1 + - _Rotation: 0 + m_Colors: + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight.mat.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight.mat.meta new file mode 100644 index 000000000..7191981ba --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight.mat.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: 5eae8f65eabf7ee4994b422cd10214bc +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Materials/Midnight.mat + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars.mat b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars.mat new file mode 100644 index 000000000..0800a852d --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars.mat @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Midnight_Stars + m_Shader: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Tex: + m_Texture: {fileID: 8900000, guid: 3b61a4965ad81044d8fd04c6738c08bb, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Exposure: 1 + - _Rotation: 0 + m_Colors: + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars.mat.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars.mat.meta new file mode 100644 index 000000000..c15904777 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars.mat.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: b7c00be18a6e7a2428b01c61aea8c5b6 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars.mat + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars02.mat b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars02.mat new file mode 100644 index 000000000..f1d8a2a12 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars02.mat @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Midnight_Stars02 + m_Shader: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Tex: + m_Texture: {fileID: 8900000, guid: e29caa9aad3602d40be0bdfa8138d34e, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Exposure: 1 + - _Rotation: 0 + m_Colors: + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars02.mat.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars02.mat.meta new file mode 100644 index 000000000..add2bd8e3 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars02.mat.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: b8b51e91d70758d4587a58e98389c07a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Materials/Midnight_Stars02.mat + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset.mat b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset.mat new file mode 100644 index 000000000..e33f9abdf --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset.mat @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Sunset + m_Shader: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Tex: + m_Texture: {fileID: 8900000, guid: 8a923fadf769f794a8d3a9806f92c8c9, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Exposure: 1 + - _Rotation: 0 + m_Colors: + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset.mat.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset.mat.meta new file mode 100644 index 000000000..fbcd17ba8 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset.mat.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: 170f2a047c448444ca1b8e2d20f504f1 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Materials/Sunset.mat + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset_Cloudy.mat b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset_Cloudy.mat new file mode 100644 index 000000000..0a9b3ec12 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset_Cloudy.mat @@ -0,0 +1,33 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Sunset_Cloudy + m_Shader: {fileID: 103, guid: 0000000000000000f000000000000000, type: 0} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _Tex: + m_Texture: {fileID: 8900000, guid: 7e3608d3009d2f74c8fc155c9ad6d76e, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Exposure: 1 + - _Rotation: 0 + m_Colors: + - _Tint: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} + m_BuildTextureStacks: [] diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset_Cloudy.mat.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset_Cloudy.mat.meta new file mode 100644 index 000000000..d7b0167eb --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Materials/Sunset_Cloudy.mat.meta @@ -0,0 +1,15 @@ +fileFormatVersion: 2 +guid: bebabbca203115940bf67dfe65237b36 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Materials/Sunset_Cloudy.mat + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures.meta new file mode 100644 index 000000000..1ea00afa0 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 29a3eadb29517be4183463ae9bf75130 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy01.png b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy01.png new file mode 100644 index 000000000..7c1679888 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f25f1f518b2ba233fe182990e49169a94844af78f888f9898810658d19a4bff +size 6177400 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy01.png.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy01.png.meta new file mode 100644 index 000000000..23ecd4223 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy01.png.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: e31e2fa4fd8bdaa478f1675cf5762fd7 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 2 + cubemapConvolution: 0 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Textures/Cloudy01.png + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy02.png b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy02.png new file mode 100644 index 000000000..e305a3770 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a79de0ed8c087e2576a9624aee6cbf6c6652ee18173676813371dfaf645bf88 +size 6927622 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy02.png.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy02.png.meta new file mode 100644 index 000000000..16332331b --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy02.png.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: f1b504bff46c95346b5b1e99fd731eff +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 2 + cubemapConvolution: 0 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Textures/Cloudy02.png + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy03.png b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy03.png new file mode 100644 index 000000000..d9d3d82e1 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4ddfb30a52015502542e96bd99316848a84b8dbfdf663ee018f74797272a79c +size 2292106 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy03.png.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy03.png.meta new file mode 100644 index 000000000..40150acbb --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy03.png.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: 3d60c74e415eb044cb7c63f12a1d955e +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 2 + cubemapConvolution: 0 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Textures/Cloudy03.png + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy04.png b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy04.png new file mode 100644 index 000000000..8fddff772 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b592ec8540d28ef7ed0ed8f3738dfe89ee2dad3e2ecf00616660a1dc2b12001 +size 4044120 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy04.png.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy04.png.meta new file mode 100644 index 000000000..4692ea53e --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Cloudy04.png.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: 663e4e044569d5d4fab103ab8ae7719c +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 2 + cubemapConvolution: 0 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Textures/Cloudy04.png + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn.png b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn.png new file mode 100644 index 000000000..657a3d978 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ef2cb30faf2f9de8eb26917b5822122edf83bf6ad7c5ac951152dad91411807 +size 143627 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn.png.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn.png.meta new file mode 100644 index 000000000..0444e6bd4 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn.png.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: 41662f129e3c1054392aed1755433fd5 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 2 + cubemapConvolution: 0 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Textures/Dawn.png + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn_Cloudy.png b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn_Cloudy.png new file mode 100644 index 000000000..4f8750ba1 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn_Cloudy.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8b89bd28c8432f024f8f7aaab17d7c2bb9c4f67042f416d2a3cba0dbac578fcc +size 8199689 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn_Cloudy.png.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn_Cloudy.png.meta new file mode 100644 index 000000000..ea2d7f95c --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Dawn_Cloudy.png.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: eb2951db9066f984f85ff41f6e9525f7 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 2 + cubemapConvolution: 0 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Textures/Dawn_Cloudy.png + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Day_Clear.png b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Day_Clear.png new file mode 100644 index 000000000..bb7e214d9 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Day_Clear.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac4462862f4523729338b04b3f4d5caa8f0de5d8b3db1de0c4e5d809417cb4aa +size 144424 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Day_Clear.png.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Day_Clear.png.meta new file mode 100644 index 000000000..e27b67921 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Day_Clear.png.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: 4c6e3caff9a2c00459a8805bc96f8f69 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 2 + cubemapConvolution: 0 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Textures/Day_Clear.png + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight.png b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight.png new file mode 100644 index 000000000..0534ea9b1 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:022e02a4e7855075297b274bf918a17b54f7cf7343132a6907b624784e479209 +size 4233467 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight.png.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight.png.meta new file mode 100644 index 000000000..931551e1e --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight.png.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: ba4f9681a4f907647a229035e27b138a +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 2 + cubemapConvolution: 0 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Textures/Midnight.png + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars.png b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars.png new file mode 100644 index 000000000..ecd972b2e --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5374d5aa16dd138309e88403cc89325a716fee9d03c9ab65212ee46f9a4ecae8 +size 4150157 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars.png.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars.png.meta new file mode 100644 index 000000000..4c2d394b7 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars.png.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: 3b61a4965ad81044d8fd04c6738c08bb +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 2 + cubemapConvolution: 0 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars.png + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars02.png b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars02.png new file mode 100644 index 000000000..018f27fac --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bce3b980ac2cf9045af951abe5c3d7ae013bee284bf57cd1deefd3e9268df361 +size 269933 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars02.png.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars02.png.meta new file mode 100644 index 000000000..e64b45ecf --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars02.png.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: e29caa9aad3602d40be0bdfa8138d34e +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 2 + cubemapConvolution: 0 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Textures/Midnight_Stars02.png + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset.png b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset.png new file mode 100644 index 000000000..028b8a2b9 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d58c36be1de7b92a3f84573c0a0588c3617db6428d98058b3a93084cab05840 +size 143773 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset.png.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset.png.meta new file mode 100644 index 000000000..4cd156d3b --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset.png.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: 8a923fadf769f794a8d3a9806f92c8c9 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 2 + cubemapConvolution: 0 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Textures/Sunset.png + uploadId: 627812 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset_Cloudy.png b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset_Cloudy.png new file mode 100644 index 000000000..17d0a67f6 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset_Cloudy.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f97d7645dbcedb34ba723a9cbf46571d401a6d0a794f6d84479d20dfe439907 +size 7191227 diff --git a/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset_Cloudy.png.meta b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset_Cloudy.png.meta new file mode 100644 index 000000000..002be6fa7 --- /dev/null +++ b/Assets/External/Free Stylized Hand-Painted Skybox/Textures/Sunset_Cloudy.png.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: 7e3608d3009d2f74c8fc155c9ad6d76e +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMasterTextureLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 2 + cubemapConvolution: 0 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 0 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Server + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 265475 + packageName: Free Stylized Hand-Painted Skybox + packageVersion: 1.0 + assetPath: Assets/Free Stylized Hand-Painted Skybox/Textures/Sunset_Cloudy.png + uploadId: 627812 diff --git a/Assets/Scenes/123.unity b/Assets/Scenes/123.unity new file mode 100644 index 000000000..728b16e84 --- /dev/null +++ b/Assets/Scenes/123.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05c0e49ed4e938ba8a2aa6f96754e37d3e736c5a0ad2991bf3c06bbfd7c4bfd2 +size 1853430 diff --git a/Assets/Scenes/123.unity.meta b/Assets/Scenes/123.unity.meta new file mode 100644 index 000000000..dd6bcae7c --- /dev/null +++ b/Assets/Scenes/123.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d3384ad04ecf0e049990c1f233d1e2ea +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity new file mode 100644 index 000000000..e3adddbbf --- /dev/null +++ b/Assets/Scenes/SampleScene.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b486fd6efc63d16941e828208257f27310635d5a0823bad13780ffed3b6b0233 +size 15750 diff --git a/Assets/Scenes/SampleScene.unity.meta b/Assets/Scenes/SampleScene.unity.meta new file mode 100644 index 000000000..9531828bc --- /dev/null +++ b/Assets/Scenes/SampleScene.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 99c9720ab356a0642a771bea13969a05 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/3rd.meta b/Assets/Scripts/3rd.meta new file mode 100644 index 000000000..a8668ee90 --- /dev/null +++ b/Assets/Scripts/3rd.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b48153ffb94284f07b4402360a8d6294 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/3rd/mmd-for-unity-master.meta b/Assets/Scripts/3rd/mmd-for-unity-master.meta new file mode 100644 index 000000000..467799b98 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ca2e40c29b72148aca866896cf8e5b3e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/Local.testsettings b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/Local.testsettings new file mode 100644 index 000000000..5ed2113bd --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/Local.testsettings @@ -0,0 +1,10 @@ + + + ã“れらã¯ãƒ­ãƒ¼ã‚«ãƒ« ãƒ†ã‚¹ãƒˆå®Ÿè¡Œç”¨ã®æ—¢å®šã®ãƒ†ã‚¹ãƒˆè¨­å®šã§ã™ã€‚ + + + + + + + \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker.vsmdi b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker.vsmdi new file mode 100644 index 000000000..1065f7d2a --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker.vsmdi @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker/IK_Test.vmd b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker/IK_Test.vmd new file mode 100644 index 0000000000000000000000000000000000000000..799a3771b6f201a39cdd4ad547ab9a76a41406b2 GIT binary patch literal 16640 zcmeI3!AliE9LL{-?sf1S{s|IviNHs-m!K>y2_@lGVy5(>grFjI7J>oSecO|lCkg8i z8k8AZiGoyz43cg^c@UgSQeEj|P_nX=8Z)dwp7mLHC z!Aq?tN+W}%tF6b1BgNLXwzdN~eS}iJ@$dR4bARf`9o6pl_!YlzyfH~G_`wArq4l{qLbh^t>Mplj=-2gQAO zz4}6&GWNN)j&P^3xK0>OE1t^H8uS0R-vxp7Q^%Nb%lbhCx?j9E{8ru-}uG~L)(@bOTts@*yV*uPR);f&? zTgQ{MduQIi2X!XlaLyzg&Y9I;P-hYj=S;%koEbiaI+JiXXA%zQ%$4~0`=}#bgxt?6 z8aGjc;i7ry@~WOyUK*f#XGZhDXBFu|6%gS#>)byY5stGCgu^KyvJR(!2!~TZ(t|1> z=|L5c^q>kzdQb%XY#mS1?wtu$K+=OMpcIF5CR72b z_Xt{W;UW{NfTRaiKq(IAOsE2q9#jD(IG6%b%PUd=(X$Fp0cq=i3h2Qy^zCHS0ToSI!;-G0RJD_Z3D!Q&>0>%BT!uk$m9qT&~j`bY~$NCP0V|@q0+4@c)cR!k6&AHH_^&J406c|%i zy3f0$z=*|l!f+g!Y1L@Iij{YN&mZ2iudDFo+H(8W&>3ql6bdb>twsF~jgF2EZ9C0x zy{f))vODKb)kuSq3pO#%$eD|E+>zwmD=lojt>fGs-UN3hk z)wEaNmwWXrRj*UuPNk|=ty(S6sBx2~6VlQ)jvO}f=?WudBp;1x(tP7c8<1(9+5-M9ev<+wm# z!tp5?6T4Bc%uEKs-peoiyLPEob(DNVBZ-;M4E78+{!a^vu*YDczo!y7;{wi%3z2dB z-M9evW#De|^6SEl-Lx>HMbpB;fqiP$ihPygnY(f6Q-5#(M(2wC);o7;^?il=VngJU z5zkosF+QTdr>Y^i$UX9&0v96V_`A?EonMBwGvJzM8;*93_?zu223!l@;LWI_X=8m)(fhX@b({|(1r>wext^#ex%}a=kIf)r?{&f`t&cCi=z_rYF z+j$)b2Hdm$!nN`dZtOA(EcOCK27tGLFuiv+;BMWTuCFTHOTYp&z4z=?3y}Qf?w9uk zXk7Y;JtNXx;i{gmto1&#J>wH4uX451PyyVHKkX}b<4-&E6?Z|BI|8QY^hs+hQTov{ zC%!bkzcoqA=gxp*le7H>0N1` zw8BSSC9S@%_MHL8MqO;x$g407I5z5hg7eS5Gr055zBAzbv+vUC`)c2%)xWNNHzIAp zrhED|t*za%Qn|9_HP03hf%DM8pL0R^M0qj>7pTOkeFg*aITw zq<=lrSNkrlzOVKjh4W9CzS?(b^?kMPOgP`{yR`bg+INO(9cPvd+nLVW@zhd z3)3r{VJ!Ox2m5zhM;xAblJX~C&-4|}=qlYu^zey0qpSD_XLJ?+;Krp-S}}r$3*FK) zOuEb$m-4FQ{o?7xMp)W65A_z{=*R+BW5fR7A47gr?iteCfDsu5#|8rBkZ|LEdEe>< z<-r(t4!EUxKMtmRm?KyJWP3y zc_8bZk8oz-mIa9U;c4&O!7yKAf%&1Uj6dxw9Px=+fV}W9B|?}JUm3UF0>l73Edq}C zRea=*xB`5HBgV3ia3h}^*=Ts%k=-UW1JLVVBHE6@jXmxI9GH`S4s+sZw^~mAtYZ42 zEkN0AN1Vex4s+9==_7Z(4s+85=OcG)-1#!h)9N!gUxqo$C86S!JrIc3$Z9$H!<^Z7 zK5@tFJD=c~ediM#v+sO@BmPWc{rCjuwC@1&`j_|B+-cwW0B5>SsVL=-JJWsYFI)@X z;7s?aZ*Zpj)Hk?s=_G)}M>rDE;TxP89^)gNuiTk!_b_ut%bvtcxN82wRrd?d>?*zq z(}eR)m?oT$!sK?AH=?eo+`b{mezo=QVZ=FXTsOOahc>b`_H6pzq)dXsesyBg5YKSq z(mC$FV9$>F?p=8>;jDdg*>Fgh7_MpeK9(@2e_-UB3ursvxI=BX1GQOib+-~YUsv0? zEKZp|vK#3tiSQ!X^pC?U1(9+5-M9evWyo1ZZHM9Jj6SYCl5w!gKVuFBoBVF{OohU= zHQ_iiE}ka?hzy{%!*F{xZBe%5uC^&>vHbeBu01?+hax&KT#Kh0>1+O&xvELcG1_At z2N5{#4@P86?oiHhL6EQeC1Bj~Dbht{!;utedqXXr!aY{tePefv=M=cB0OEv~S>+)) z8IhzCg5xf!gus!|RieTzuXDSxhbI~ijk`1a^8=E{9fpfC?!0ZN@sU&*PV%_Ja8bsc zC+<+&{e;?X-lt=fij)7&_%*UWm~u})GR%$ZW><4GXJWXS4brti3qPu|@#j^+FK-pD zJYcv%Z;n!0*KD7m6*{7In&h23G-qPCrcajE2aX@Gs@~`}T8o#2>nc}J+ZB2510~Oo zCA4J;wP}{ZM{{1Pmvd zJG9=FMr|ht&f-os9BMlZ_j;>qmTkTyAZmH_jXSm}L)}INVzr&I9)K2|1lkI`5J|M? zfPI%}(Hx1j=$LR!OQ&#%WJ)`|%anGD1ap#8+KW)`_I}nl#P>=P~f3LYTBa7mQTfo3&9ftHg`N3he!fve>p36zrb^oYE@Fl=NPNcpE?zp zl!QC;fk`0DBqB_nq;Tx6!CfHUCNXzk0bKQ3!^1T@%+pt%nGmJzLeL!K2}uA4!sJPS zbKW)D&i-;%?#{ut|LQhYopYp`9x5O23TJf{^ZAUVa26Rb&}|ZPcNyUJ##anInAuvb zG-ttp=?bmn9k_13LJtmzqk4VMvpYKjYbWfJL` zRC<(T!epe$9r+@8Wff)|{OZo*b;Czb?G1kWz|kzitWW{EI=ooxBa#dR$6eA@I1+P5 z935TTzp9u0@3nBPtM_Dq3&H;mz>75pBFQj!+$CLwBQYFV?=o15%KbBwi)~BT@y1_1RE}uJvr*TcQ_I!#&%>NmbXS!81_pWj>!G8XAWf6I*6phoZY3v+$J%1#9LeQTpzW~efOyk9CFpCNBOiX}bWKU@c)HJ@Y<*BUj4QovQiC`P0@jnYgIh$w;baTBNCG+9b3c zr`F1bLv2U&O!v#4#BSc7$(00QS~PP7Tk4(J#Ss zLN7#8#gE;Ewj-BK;-dEt0Nj7IZjIFbdPn$+&Ywgu9J5~8ngVUdnZt-A>mAm_oLz;$ zz0hKw0h9NOHOBk7E{Bb-(z8f6&&D!nV$RZY1kQP#?RubgrSC2%YYvW0?AEfA=dOZE z`eQgJw1~DtHTGr0A=QY$HD5kmeXIHX>ar#Uqu6&$@iVm@OYx)14}X`=Dx7M>tq8KY zBSCkLSp~!O8njl~Qg5ZczIuOsdC%6Ky9z4cjNvYJ_*D6zO*7?Cr_sRkiA#u6{XfU z_XLk{^_*DnIrL$Q^3glb2M2C@A^gnILnM!c39}CHP#uxBFpazRF_)CY4o1e^bxzgv z#2s>dv#wIUogEs(l`k`RgT|tMYHS9xjl&zpC>?ES1>XPu&Eb_2AJ36-hz#&|vz)X1fCGwrd;rc_E)C}_7l3n?1I>+| z>8b4ycP$WHa*gxKKV|dj=l*#^`EY}=kKj?5+|DwFtA2T>_QCV@!?TtY49DL)!?~K@ z)QW&S4{TOpOirnsTTMT*O!;Yc-QdB64FqUn+&%(^TYK;1;P<)nsRtX4QBpTF76r$Y zb_{pw-aLAT{0o%DMK|gRf4?9C&gpr;a8#(N1J9OGSAG42C^$Fn7~JATHPx1FtBHbR zo(DJXT2!vB=3P=n037FeaD&S;SXH0=wW27vSibU<<-xd))564OPKebzEk~XQWH^dv4q*Uu;%{RIhkPV*Pf#!qW@PCidN9@FLDvYTt2W9Dg@1z~9Yc zEZ0ZeX+56TwwEaXQMFOOB;NM6u}$yEdPQ!W#{R-#O-!=a2*ZhXa$*WxLBqD^K>zOT4+vRSRQ$4-xKV?_D9O{gZu8^K-T+lO(3z0DcmB*!Xniz(o zu7EJO0(9yM5CO*~F$_mt0Xnz>6zU4_3g^_sFdUODxB|k|6(9o6jXMShu7EIg1&DxS znwT4RU?YU7E5IWhr-`}2fh!&ECVhIym0b%M25CIoUnBWQsQ&)gTI8GCD6DGI< z!qgQY0xp&?!4(jut^g5mv4jb(fG~9hc!c9LF*jj?D)>Y(l$E^rH!TBdl&Ni3N9k(L*1m~YH zIon)5cif8L6P$m-vxYM`c&CO&{azLQm_R^RNjBHYac~4ioeU$8krZ0tk0x zxr=%-BMQGkWXxzB#2tYn+!45_M;3rPbF7W#&D9W@?tp26_qiZNc9E4LE2NtMSAgTJJF2(R-!@cXdmwQY)c` z_M(~9>j@6E9fs529hjJZZ>hwWuFegfs_cDt615$MTlLuPV5JAge6;eFD#2g+co!zh zM}t%159i%ST`&%}20EGuwhy3dqcSn(vB%z@#xo86NWMg&W`Stcjsq zl2-88OQoNzd25qh%DgZ88aWBhd<0em*s5D=R?=f6DT)Y{^eoaWtY?#$yKLwxp5{!W z?QCJ<9HtM4I_R7-Q*C3THB65zPymB2YK@yC8~+%*R* zVw?AVCr)8rqh3j7w$uE4kSRkw8?1E@NgW;RF7Z47gEk3;)4A{%0_VKM+jkrsw$0m5 z=^E^>l+a3_YpO4(Y#fZ`X_%u)tR1lSO7n3wcMoeCKDumpgmCKYDr^$F*-GYVe3~tR z!&kF%!;Jy4bwhtLMSJ3o421E2T4gh$!4de#!xi+CqePsT!}Ux8_fgCB;rb(H2K!cD zs|N>1Lq|5KL``*9C^TS=p75*ab)6R-D_UjyXP5$y`|(Rd=;Zi?at( z?id-fOfKpw*;o-gbrp7KHSH{9n8#?l5PZd&qJb?Z$yNk9fwL9CB4JkHx(Zof!q5>H}n$lvO?sve40<`h_`HC`}O z$y3QV?T88U3FvSs6b?Qbq#fF1k|vyWmz-V5IT$fq-*SH_Z|7sNUWRddA-49@7#eubI*u$YgWNg+Qk<9@oTNB0H#kXgVs3Df z;>6tGB*lrj!AXh}bAyu=7Vau}N=Op7+(y>H5(6~PBM=ZfGH9P27R!LhC)AC6lQe1h{& zm|WzreD1gv!6!KXgvmt?%jb?;5qyI4PncZfux#$erE_H^Fx=vf!vjxO86^APVQ7FnwKs#-;nZ08u#qgz4)7 zG%nrO1&G4=Crn=#Ahh?2qXO6z-Tj?%dgp20_g(?cdAw{Adw$e+dw0_Calwz9*n4%t zkp<{j@{>w|vtyL!dmqZ+QEfQ3C3mBnp(tLZH9Y^jBaf*oAIPt*z4Eh`70x`toSoE6 zPa;@eB0_;y*d__kL#r;`f9(bZhmzPTHmqf@0*<)?+~E2_@$EOw;@cwNn8(izPSU=)8{8-;zP;TnzU`4a!)p{vn3DF*-MEvq zZ|(*sY2Vxp?qMjtUC=DP?Xm4RCzTtVs9_Fa*iJW&o0H0%JH79lBRJwUdOz)3z1Pxl z%EHWfQQSC?i~=$LH|sS*#Yl08MU?8Gp4twf3llQ+yRE2B{(@LZ+ zfN$6&hU*BAKbhEEfArDa;e@* zM@_0{DAtDiMyXk00S+bHAu?wEU0Qu#;ShIZ0s3oBt^DRnLx*y_> zbd`-Wh8x@s+S@E-;Ta!*yLj^-EozmFNWvZbV|U4lz>!9}pCg$unSZ`T{afd;;7rZ? zf#ayFqyWH*cixQrQ)7pEZg&CI!ZSWN+s<6?thO^rtL-Ss+K!R9tB~dOMB!y>gQpIt zpopMMkLKHWOt2$KoXoSIK&-+3q8M7sg>`5TIYjbvSefnUd>+xxQ{`3 zI6k|0@Uu}PB0vU4eijUq_gddpf^ipuk!5FOBNDiC-X&ed@nx9)QC9C8@Yr(zH}kDi z;iqQa8X+(|9CS5fAcM98GZ$?;mgH*%K|6R(DQDvB$h`h9bB=PAvHR#L-#Wr|s?vk8iVDODxgI^JXYInGwV79dN7i_Oycf z=^th!Hm@o|HR7`AvEp~zSMLXN7aF0hKmDG5xlbR@+#%;MhFgDlmojMjciQ;GRm!?I zlRU$rVNPxjG{P#q(0k4lxW)6GNvoMiKg5mZ=x+u4`EgIhb&|!V->M8$yOg?LSypPY zGXGK;HGhlSJ;Nbkl1a>YP5bz?a&7S?t>&AR^nKqO2SGC1oSwSEk+x&sxC?DZF4zU2 zB(xouB8}m$J-nz^-2Q_4#)Pu^`LbLUi<^Q&Ar=_!&l|MbhM9t zs)aF$k$s?my(z_va@)lY0UpW5S`HiQ%SR zny$REvY>Wh{WfLpM;!#faczg;q6~9S+@UF&%$c8*KCRzzvPdK~b*rH~{F9!`cpq`5 z4NTFdqsE#ud6K9`@C|ks#vM<>xZ`w{z5s_yg1kysgt??P4!!KIV*G-U_AoboV-Ism zVz?myw`=GyWz?)<%8RGY8C?DLW)9;$tyVj$;0gQtsV2rqs)<>osfpQS0F?yk0dV*d zT0Mq$C~)?#yt{GG6fGMLP0<+c?4OmCf$Q$jPq!Sa z-`dlARbJFp`rDGTK8b8Q1V;t}zIr}*)i5i&?P%|L+#xM`D8iDgMZbgKL|2bNCJF8; zqD>M6_a@>_-?3eLw9Z<+?RNvT?K`|jFru~_h2Xl*KNP%c_(G*a*O`e$GGFuDRnP)7 z9N=CaeOdqS+QjhahxUXC`rH@K8$EMLo)_&Ynp*d4ie|>XX*=7tzhNxfBwi6l!sD;E zBCrLBP4bjxBwc_kGD}?}wBEf1aNP@)3$N(jOnq*0iwKZ`;PQn*@}5*B#paIf0a13? zE)OEv0%Yw0p-Bw4U5AOi^?!b!9DKC(S*_KRMukakJ*C`bdwE4G0)`vhBcv3$yQKQn zs#(g|e#ZIcp5TxshT*>Y>vFLFi_^3cotJAHM~aBp=QJ@4mvHWiR=(A<;X#83>D7n+ zL$okY+#!$O%g`nM`Fx3ft?2}H+nn!I(naix_%p#iC5|BI`Q(L2=7OVliS_FEGAQlH zIZWWnG;R_3`>_e?YZc0cY$)={2?s7p;%R5-CTYP@lEE?3gkxdKnVISQ^ARONdEoR+ z0$26X{!00>XEO$^D7=N><=k^RgS@Anuzk^NAk(H~WXxfX+K#BTE8AyALTkpWYp=bQ zwe6UzfzDcpWS$3lm$V)6JXj=dI|BFWd+Q^|OH5GzdH6qL&Lo_f7YQ;qJ(fwZ@nN(b zPf~v-yGxXI@Mqd2-jpG_N~zzLNAB(3SADhI?OC{EHUfBN41Xru>ZK&L5!hVi-_CkdZ9GJsZdoEf_Qp1-uF5QMO-&yY>K2YC-dKy#+-y;r0> zVD2{LOHk?zED&70^LXt>lZ8*wn7ez{}rm=`=oGN<;thU)cs}eQihMJ=UJFY z@v8=F($>0};kUX~P^VN~6~V%Uxftdpdyfo}FwC8IjY-V@GFk6+gE zx;7`gqw}T+5u|osfpPntaqHZmcTi$Pdg=qgS!g`D=a9YhlbV> z(018@(*RBp0f%CZq78GKTklgeI*vg$95N>xLEDu+zb|t7@>|;cO4B1YXXKNkXVRL< ztY=b^&Y5=KFncDuOEfXAJT>kr7>+JDRte}EU4YQIBg4GNsaw<#Vy!n&j1NC|>#wK2T!u#@yx(ea$>VvN-L}|}iVW8_2?J$;sYs+?K$^-Nb z@(rduSR@FOYr6*lF5l33%6p?btMf{xWr1VSIBaA=%aC6&655U^Pd;YwH& z6W?~+`3M*;%Asb)$YzS=jSq7U4$qn5k7MA3iQ(i3bL??C7_cx!!=d%AJoHTWOUy8L z#Q3=hGjyrEo;=38eTN2uZ0-z$tEDxKxp8L-*t;+duTg8?;0%wSe{kR&HneEUpKM{W zDcUDEqpNfu(Zd1vQt}U~ay+c)ANS3otFRS;EkJZdU?g1;EYe&NY!d4#WKXwVm9gP^ z`%b7iR~FntdSv+3pA6W!t-D(L2uwM#jAa@_$c$x5nkEVRGE5=JSdQkcmAH{@xMj^j zX8laxkzlAusXJ_M?aeMg$Vr9au3gHJnEq=Gy-UB9+7Lb(=cfEB==dQ#iHTlbk$tz( z5~2B_ZIOz>xodvZR*d~d|7k@x0rnjiLSKi%`Q$!bg}B?%poYHorMk*b<(|%Xrh@ka zdQev(`*+Su^kyhJ{|Xb0y&Y5iiMnCKT!m()J zOdu~rg6F|`7d#I<39bMRZYDfF-`@BLf$31}ZR7p&`UebH2tc(H;+V&eCeARQ9wI@{ zyl(2sWPthiw@Q&QS3Xu#Q(iLQ_FsC!fJ@s{#&W?i)e+QMZZj8=%t^)6PVD+7+^sE^ zU+=bjSop7B-ZS8$B@wf%X9~wi=J5lc8%dz1JImJHENMsc0dCrbjarvHiTch%bF;!( z`{t%!2$2NN*eEye8eSumv&_{T#*>)j;%pdBa&a~c2eLITNyXXR;3O4ibAuCAwFwnx zbAyvqoXrhRQgJpnI7!9X+~6b?XLEy-RGiHXPEv6;H#kYf+1%hH6=!pU6F1B`*S8y- zIdclvGi9qrNYBJ@lJ!gsN7otS<^^M^qTdx>Sxb)i%Sq>K?!2*IS z*&+i7j%3q2uP5JI8q9O$UA^r$X_~gddn6Tt3%PJ-{s}Ov5Z?p*&CC~#NEQxCZyWZV z{bhJIih?6>{jM zprsp}q=J@iaFPmIy1_{*Xz2zgsi37BoVa0rT?%;Q8I&E}h#V7xT3%;A4 zWqD;uRm^7ynixr&Vx$#YYdILXyJo&XI6#OF_4h8?nhGSiYM&rnaL-rkkyWa6b zU?>_U8#5RYNuy8MU1J}C8|Emxkiad>Uo!GujTZVt3qM!+A#V?Jwkczc3%c#X1_IlK zp#y=DFspD89RzOUmtDg1((cw;mw7u29OI5fD^czkNx8E~Vk|o%Z?jZOBXDFx4c-Dn zslJWX7_?oOFB{CP=j2O#rx8nvbiwdsx%( zV`u9{fDF7s>#NLx`YNmz9Lq)lM~Ab{9tle$o(!#uYl|aNkz(aI!S0djwF5+`^#CC2LdOvXQFY3YjpH2_lNT4uKN1+j#Cm_9cbqi z<`dA{Q{b;B7ko5Gdmxx3^%}9eL^a~ljxgM@qK%c5w1mXExt`Y>T;_5oZxW8{Dj2TJ z)~^!VU5g}E?w_o`bJgJ!qkpi;+>LO@?JQ$B(pBusyRL!`3h@EXc~FQ?aO^k+pWxWp z7V_aZzlu+A{t1&i%~n2l+-bHx!TBdl?lfEZ+;OMb`UK~nFu8+5WOIj(Q^#nCbpb-hsmm9puL}@Zug;UI2zS>%aNLZZWnQlv4Y7c@XbgA#ld2e;>AJVzs3)Jl zYq;P@LP5>wNxubwHN5+{k5th%&@Qher2G0X>1z@-+CxCO$k4Mi(WE42=a3u^U`2=tb z=a4IWw7s=VT-003NV*4Pk>Jk+_o+>SFgaHMhLap*j^QK+nPWI6Oi4lJZg7%<%-!I` zMW1r605>>ELFR67l7h_L;3Nf^yTM5cGIxWM6lCrOCn?C>4Ng*!xf`6MAagf3QNtX$ zzA;>s6Tm$!udu_lXGA*PdCknka8XVG_XLO5yGKBuh;pUE@8IR#^MKS^%pDJHhw?IA z?nbwIQNSdIlN>OK;Uou4VmK;HSpk!7aFPNh-QdJUQe|f~Pn8rf>BgO;fJrwvNdc2? zaFPNh-QXkzOuE5I3Yc_*lN2!N1}7y`#IG_vl2-GO+E7tO7LJfP(|KYJ zD~ia1e{M7*8FAnhOoleB^mC<(SX7fD6B%5~4`MWIuOj2TIV0=EdFn6LWnN#lk8VD4QdD>+Q6QvztVT!M0&Z$PSxuZK= zezhGc&W43a<}Dw(I%&yKDltnE-TqZ@Z7 zo(L_POJEgnjBcsPhC|7W1nzp3%wcDX%iu#~OeYoci4nLv8rKe; zs&-AO)8w|0*(2Fc5*}mbpt1ZxMA8g3c9&+T*(6S8Bye?eJ*w|0dRn{fO!KU8tS~#x z8b&06gI_t5h&d8Geq6au0(ZS+M!MkKbetHSRs5Qw(cUYZUBg|XV~yBApt+MonBCJp zRQt46lm_KWX33rO+A~r99f4!{cUM|3j1X3x`FE^H6zgm>q>z!&Rjywh6uEJ5DINls z+NQCQ?zjFVN%u3ao7Gil+cC8kx1Hp`EeuDvBbTJWEjKtxfm?2Hq9Qs_2)!Geq`)mV zI7xw9Zg7$Ux7^?)1#Y>)NebL@gA*6H#YGO|Nvvh---17Os-=%@cR<_x7MJ&G%wuRy zi)nD7$YBik*0F=iu5*)=hR@!m_PcnGfH{*hCo$akj;YGC&y3OseX>NWz5P`Ia9m6~ zfeTHTs&$>wDA=h^S9DB?9c#pnxwJGfD0l)VbX%GjC0XGGM&ig}%w722$-(2f^M#K! z8lz9x&{zO>+*U7!`}N*D`iuD&=pPi_s8sm-1p#oJIq5bK#Dx@2bmnkj?u^9_ek@&7 zGu*0eH38fia7^)YgKJ&6cDUe@Dgxj*>(xz|;sPcOpBU3s+_>vMv~c*XxMxLi$Asy| zow(JUbHTZB2eC%sFPeHkfR*lW#S-Ryr|%4ZJE@5PVRBw0H}0C0d@@|SWN86#+%R{8 z8-Ai}_~MniqTpf)vwD+S;ll4dBnpo8OgHYt4RdbG$qmk&%)EPz&>j#TchsCz4>lU3 zqzYJo&>j$mqZW{|xadYbLBIk8aLzp-3`bW4S;4MuaFT*u-QZx(RPzd0fKYW%H#o3> z)F*$f=y}{xI5y1P;J^Y>M+jJeC>$H+Zg7%?RUlA}IF-bb-U!Z_VqKhy|=s<`y%*BOaXU8N-1(QS-VUp1Gj&X;D$@)kV ztO$j~uLy2%l2!yaxB;*tj1jUTaB8jFoGC7ZK078!>S$OIz7)SAxCs+X5>lKAqxC{ig?0HuF&|&ei;ZTT$Y&aBRAsdeE zEYlDR*>EVtA_Y3dv0FY>OMI|bS)V%6n!s4k^qRwkLM#Y(JKvukdGY*s_0d~0v+SGO zXVcShM}r*bFk~?gj3ncZ9CK;yBcQY+0#~Kewn&%U6V!jMm5%~v4rEqchYoW_(qV3q z<}kNOJgX46MlbxREFE~O{@JfzMu6lK;;0S6_RSGVcS+b?qw)_|U&Y|go>gQYu7u#+ zrszh2vs#H}!^F%gc3mTK04upFw3~q1jrds9E}qT zjtvC%1b_>`i;*P6!b!po7f0f*G8=ec5gpMhDx3R}?D=$el96=1v&bw}o6veUAK*IQ zzgH>Wq_w*3ws{dCQ2>bU!3jf84gvkz;M0N$0nYCzincRSLZ36@_Rq_ z3steea06Q`4{qw&R)7D`1pSeShy%yDwj*7|c}1zXWpqY1O?lim$8dWu?o<-PIo14E zFDgB17Z=@j7%oZ$5>MQrw!?65G=E;d<-Ui*cg{Gk@9P}rnLCssjp0P6NTUSsrg4G5 z#m<39v1doCcQlh0=UUaK<+x>72=u-|1>@ zlbAaK=Y9#Y5p3lF3sZC*Kh#xP0C%&7z7hUX|2lkZ)4B-bblL-*g1@|<08$`)h5zaqFw8Aj|xue z=N%5snQq*fe}eaMhv3|}JD=V}E4I=*cc^Dpa}g$KyUya<4j-P|FV7#f2URH$EVBA& z@OWeIHUi?#?L^eFqo3LQ!8Px~M3v0(Fqd4e6T|U?!tR+&52x!LBV*bKD1;uvi4LJh zQQsI&a@045W5Sda_3Z{HDeBt|PF$QAm-p%hCn@UN4Ng+jw;PsxLG$2GM3i?T+Qmt6fqr)0H12UY&fQz+^DXCwhLd5!rcYX zpb5vt1!&O-E~Yt2`X=~bnJ^JaG%?3rFt~UUAC*Yp#-*2vtX{QM|8rEXSY+}AUYjDS&RanoYvSlO{rbQAL9NKc?O8R3s$wh!Moa7?F7>>$T zR$R0joTRvDH#kw%K~Y?^8=Ryfz;1AoiU7O8Ns5bhgOgMQ*bPoxTr`)M;|3=#`ZPN> zLaMk3#_ZS#sgjBSy9ra=Fz2G+Fr4T@LnzG_ujUfY$abC}fZ;@+vy5DDNpbvgF4_f0 zly--~h1-sSi#oI#dHgVUqCI{n3eJr?lS|tqVag9RNf^mO3MoyLcDSs&L__Ba4atT> zQE;;1P!ybOIHt5yXMk)t6a`1%u6KqSGf7zM->4RiqTm>JZlO)ICt972(hNOj&qPsh zvf*HuJF^S%FlV!hBu~2=oG4E_>zUM?B*K(?Ha!=Ovy@4XzE?dIugod1PHVhisFJ4= zR~G)J4vQa`&aLL{5nPe?K2Y-fSVCKtaEp?okP)~Qg5DT_u4u$o$H#MI93lh!T{35K zVc5$7F5lkx2tn;o>}})y^7;qDgkHZ*5#aIT;>0$R=Q^%}>n|&(x8J4Ker-nZodcx= zz;WEI0;qp~s}vb?eq{y`{katgcC)J3pBMwhIN#{%gcfC0ime&w`B|zR&;6h{^ ze>X0`eHq}8jezIOzUBT<-rQAR-`;UbVygq~oIUfV=1de0is6nGZLFlEB_!6(^}OET zviB((gy}R%FkG3fUnRD?7D=q!KUsh0DwlS2liYD0KMY6O$-ca6(WnxF4{%Oh#V0tH zyzdhn+b)z3$3+GB1m~YHxoX(*x#RL)eS-5(n4HH?K6jkQ&nGzlgvmt($mR}3!C|ENu|KqG0OA34@D_PY9Ub9 zh_v9C--g05GJt&1#8{5uiw+TJVCSZcWdqL61Hzt%D0x7h933b#bS3%I9aog>!XR}p z8t(4+c#e!iWPrb$#T9_za<|HkHX}F ze=wXwuJF+aZ3;mwle4QhN${(1WB`%iSK%}<3>Rg0(j#{U9Me@WT$JrXuW(LR0ET12 zbZlFQfOF%H!8x`qM8L5r+KoF$kk?R`^GfFnS zr{xv7zA;?c#Gkcgi_3>+7ri~)v(se(t2tN6+-+ysAxvXup6$yUgd;@6q}ko90VGJR z#oVzK!F)GDc|+v$%_@GVpe2Tj63XkTXClWwhKmx)>lH2=tGP3jR|H&)VV>#;Imf(0T)Y{j!<3^aIu8x z2<7z%mz~wz8OkdHE|xGIp}ZpCVhK~!Fh?O4#L+Q5l2-GO+EAIhWqX7yHm}kUi@A;f z5|&s5sVk(&6(fnG!%2c)g(Go|4(xdlU91KKfiAc^^9i0DAc zjM$&K{+_?Irr*|8mh~C3Y4;!ziKv`o->s`S%t@}XOhwNM*NoYAsH)E@S@+4quk07wR=DW7I+} z8s{d*ow1s;6~T==hq3I5J1WdrZRaqSJ;9*_a4bwRtK@y7w-HjbB$c96SsBT?F(s2xKaG*TMIH1Q3 z&SAZJ?3tYP>INt2fF3tEhxICgyIAASVZC~U%g%b|v|dHP#hSz&$SZ}&m`*C>6C-eU zG_D=mlTuQx)8w|0*(2FcyRH#)b3x!1sa(WJk}~EbiId84mt;9X&$JILAaHeaJ*syo zP(;7&O!KU8;0<*a^FbtmGyJ8HqXt21BtwlOak}5LFlUZ@^OJDRho^D5Msf>e-FXdKmZC*hoC%l z3L*i{d6%U7Ilc^VruAx>lQ?I2&gkRXBN+#){4?fIu!&j6&*P>Hr-@;>;x)%8yEnX@ zvGiJA{p)6igV7Tl3Yc6+n#gg@*grUU;pvKcX3{*p`Y*=W79Qca>_QCJeE1?|^uAw} zySBX_y!uc};tKEthXP12+>pFY5^ME)KO?iuX65G^-nl~oBp7b%9iJ%EnjO>oJhf4) z`cex4+;Lho?kX*wZltgIW9F(RHOFX=bu>&8Pr^iQoEIJ4gnVoYbu-zo;)T@D@rx z9wCRCaczg;7?k<$y=S6vhvB+5tY*!bdF~KCXJRor zlE>X-)OI}SeITIqPBt7GcNk8&eSocX?#-(A9u3h(73~JlE)o}6D>>>+BBViKBBz09rD%^xNnjh>dR&&gv0+&7R%tT#_JDRu4Jbsj9+%Xb- zVqB_bZ-8r3Qc_i9d`}qu>EDjCzb{7t~Ra1 z?KkXJI&~S7VMCEm!r|V4hlVCh)xzq~V5d4Kv%mpY@$ePkPKYoGT-g%^gX$N3gQ4H= z5e^4c3Y`hyL^Znl$!5KD$qxFlf9LB!IxdH&ofhq9o_0#o1aNS6GRMB*hqp-FRi?tj z_dNZOvMlmuuwusaC~!=eH|L8++${pQR+B&0t3Fm(8}i9KS2*_fvrQTH_nUtVy9+%N zo(D1Ej9F6h(J4$4_1%1GGriFYP3!kwMd5I0+^qq)LEXD2ZXC5zId!0wD;yhlR!6l? ze<19zyOcYdG?VvPsB30sC-}DeC43Sia4-IL$>8d_?Fp_^G;59xJH)V5$P~p!ThSUCfGz6sMviI*;bHKRcP98y|xqrvL409%O z4$pQxoP10;cSS4T>e=w1!GrYbL;oS!g~r7a`Vbj2>Kj!l#BhUqgp?w8msG!6HA@-W zubSteJLGA{a9{m(IoSWjXfR z-5E6qK`?i+;ShJv0(Yk>Y*fqroTe3BI{|SBHUb!Q0mmt9h$P0c<1W!NITE)Wfg6xM zN!`Eukp5KrSA@f%DS9hyJNC9}=V_%ypTWw|kLoHFKWXK8&P1vahU-+PRj|Z@-#1_S z=tA(ye(wiCq7?zdW#sIsRN{3rlMgUrGO=t9P{) zrAU)gHQC9Gr8lmMumNGdJ4_OYvV+j3WM-03l7!cSE**D_q~p#a&2eXw z#7VWn5z4y@o_+FgYGme&JM|R>-;LN%V8)(DvNw7ep762o1bKEHOGZaaf5Q{wbr7J6S^(X6tAmtNq)&=Sg_+a~ChTi&K0 zx!-$NL2yISBqllx8!bRP5qCQp)X>+yR9E?_+|wD)ROs)yXCk<75!}_fRrN8e%4zc& zp054VMehgnptK{bi5-~VxOTHmvlE+r_et>Hf4s*$Ad>`b`ULvM7gk;#Ju9QY#@>3t z+r2v&(X4{u*0=vgDben#@@4x?!G(`M;koV5tb*Y>79GE7+tTL}8$9<##{84sl?ODd zV7RKCuLj@Sb0nCzZECRDE#8MYnpH4drPd!S@77TD4a0Y9C4PO`voO(WegFo7dhM>z z3umUN{r69f@Z*APhMEf~D`bR7y1cTxba}N&yuAJh&mYrfo4V)6FT(@xUSq&<%PZ`{ zka9O{0YxNPULAK08^QjvVSjMC3W2-lzUd)&3rs3CGeX`WHriOt>p)yIvbnsqi2*Hi;m%Hf*?(aJ;Z|YV5Tw>Cy zfIjW8cUJ(4=)l4xZD(KJH$zd{(OKZGM)6l7cQ>7&=0DISVndNn_AqB)}=#6Ks%mN1k% z3@6%HMn^|sxG3i%c(PtW@pHx+VK}?p$S3c!3OXMFkGub^Xcg=?;0t}~U-k7qzk1(C zpm4053x*rCWQ!J5y6Z2`dsFFL%DbnXp5?@Xn=l*`=GjZ<^@&G22^i)^@ohKm7~D7i zUM-rYDT%L&7= zIn#XizTTl!O{_(WhC|CMR{S#VogDl*cfRn^Mq~7`8yXAfDw9@>|I^yPa~lY+?L8X& zzK?esffR{yY&ks$2G`~7DXQH%C*A)Bn_-oLENr_=xwK!^jtn;VKq?TmP`vcly?yCBj3J?)NOr zwECR&is7bI&aI{&S*H9nyKeB{!Uh81vRFXZOMjrdkyh#Q8{M6xrNv_ngg1s34v&iS zuGXS-Kio4#yKzug!E@%i6|I$ZEy{;C-F{jx{$3H!ZHEe{yAAWv`^$&FXez>M#8onP zgDZLZ&hXwzO+0gljvvCpq{gxW#=z7U@R*l zjAc}w+6@kjWmSZ+OySr9mYBOAl9ac91ZuzJOH=m6?g*Hq}oEKD|64II>ss+7C|iZY&$SlXl%&3@5s) z7zqNcE&gP~8TOrja1b7|b;RL`Cnkra;I zh42`7K)g*tri>xXSaYT*T?HM`b3~swBGiwjcB#LXH%@urkkx|frN=O zWd?ToSsM?BnmyS~snt&N9&3b7J96tP)tb}_7kcj@&pi{h9p2q+q-KJsVwR(C6b^L4eI%i@&jBfF8dON3Vd zN)tQ|uM|Ya@pt0_+?V0mBw*6gR5CN82{Uot93#fBW4At@y9(08+_Y#@px%XvBB^lC zBrq8?k}6GrT8rQg+5N)$1c6%`5UHsG;EPP~aAUgKdipRJAD;ehn{@e`neV%*sGyOp^pTsqnblvuTU6C3m$=Ig91jw{_4!8xY%0EU6cxw zo@Ny`XVT4V!d@cmQl3u5i8!oWYKOrmVHUvj*%=b8Z1BZD{9|aciHI=Rwyq% zWlVISGE&+*BTdZFaPZN)u7Xws%$;aBG!QVH_zg9#XJR%vHbPR>ZXrok-16GSW!#yP^*)KA$YIRgT8JF}9wLViLga9&kjUYQFFC?N zG2AH#cI^Pcu8SeqH9=Ugs}-N=gD{=Ju9!Qs%>seN5bWAge6Xt<9GoH@&MP3;6)6u` zn4-046fo(=9UK-P9w97X(#NjC#TvPB2ZzOnKNlat=mrOe#fQHU5W$GHdfnjQu=sE- z0b9MOXX5ov@(JJ=jtz5hQ#2Q1;U>&su#tUUz(zLO40VI63Y(z?1Z;+)-AOk%QIiU=};K>(_ zHnO9QyIOQ3yPbfIY&1nK$#*M?3bHQ-mJTz8Wu(NDJ8^F%TWJqkQi9fDERaH-d%7s4~V%K zF?ZAzpn@wv5#b7;a4eSu!%+#m|{WNf5WL!h{K~09Ar30COjP&diQ0AQfBzst8vA&6J5HOmGFLB3uC|F~_ZE zf-683;R--O2-rp_)T*lXYUTU%TXIg`TxXStT@r3n1_w+o9JWUP{zyjR3;)$r-hVt< zzyg#VS3oMb0#p&M0F-Uv)^^|uP(`=`P(FeioTy0*sYb6N)kv~^hv7uqcO;U^5vYuX zdFMBWH-A!mpkA-V*u;xZh%!m6eRIs6X!{On(HKs$1=JgL70DJ5h7-R4arPaC6Tg~s z)+>e+%^mXi;ej9;4h5OZhC?1d*>K3?CmRlV{A9zS6(QQ0GIn?I?s-6t4%u+X(ShM4 z4|5D>3zB^DE=nevJ^=O=cJRsCnFn6ML6|?}kaFC79iPh zXaSN9hZZ2&aBSRBOGMpZ-&M&yfjgM)l?RYDC$EKHL*_EUtO$@!w) zxPv-=s)Razm^<-GJLijb;|>bzsUiyNAz!o`92C}5#T3>vxQkHigCazBOwu$ocC&xu$pt;S}e@c;H}lbTiXb{ zwbulAYmxOD?dT|*L+`>w=A>*mWZz*p@pC4pv|~71kmQqhVWJ(bO~~^g8V+SSO$Io2 zmQ#uDD=$QlB=ZKK}yWRyixb{ru=Au25k+f%8B&n9h)e1n_g=8SOU*3l~ zT7W_TH$B%{bzTXj_V=k5NlhHb<-HODf+Lj>mJT~ro2+-a|5%h|y#p~B)#MyC_TkU5 z4=d#FTBQl-$%cUdn#Az_9b@gAA3xGM2sr%#an}&I>o{O`xb=aP%2St)8`YW^B$=Ws z&~uzwXFw!b&B61)?h@OaBLfJoIl#U3-^}oR{Q+*|i7aqlg^312Uw~`Zsz#)1i*)_* z|E-JIoRLp<{vDfjSyQq}n6@1w$w1(A71Vb90nYvMJ`fClrmcyU1GsvZPpa4Qod`a? z^r&%)yA5x1ceADEP}`9}foo#3CQ_!Bt&2nKp^x zNZ{7NdixS5{}vxCn3zj3Vc1XaaIn1Y8If)USzzu&C!!*MCWaFo?1}~gfxGTNpy}-) zI9DYFj;}=|83?59=v^{rawN1J7fFS=8$RzvYt5TE%X_dZ;*LyWWFX90wAE!GK;Lr= zr5hc0s743oZd><#iR~t+`iF(`>1A?yFKCIlBRgC>U!J0#t~6R1JUcb(Fh>Iokuk>| zT7ZZ!$EBBwtX{QMZ}r>q2pe(cyF*uDU4@ouVtoUVq^rOb#O?<0@;Vyerd8{rZJJwF zt+KnkaPCmsxvh84eN$CCw$*#jM8cd7+`X~!WuvS_?H?8~VWxsG;bjZcIwPBI9I(@J z5orpOeHosOHf5a4Ynv^93twK*YF-2Wf`N7BhHE`|hnnl}QX$~Vagiz7G#J?=kI0xx zJL1j>*SKPtkOK=odWS>Y5wFpnF7K#!%rCAsZvC6PFxfz$3mog}h@|TsyPKu$oNxuM zi8)5t(I}qqcLx zor^0e91d~U8o0an`Cw@12fEU9b4J#-W4aKP9wM1)#AFL?M^qz=#N*BhmoVmxa5z+7 z1y5p<&soNBk`F${aN-X>23^HANnV7m@^IC-$lxjyl`qPd%hEI1MmB4GraZ9D0OO9R z7K|ia#Yw_iY81_2`v{mj@u&N7H99by=mY7{Fn0c*X< zQ^wrjM4d8*YIL~4Nji?f4NlZ?45*5Q8=R<;{-}zD8=RzJPD1Gat6e6t@Rf&^L9ZnU zpEHr`dn219>H9si?^NCz`HL2*m|r{GYOsJTCvKQKxvQM-Ug6vs#xh%6Gc$ig-0i+p z)bbqFerBj=?oi={XkA6*2?A(EAYs^*FEvr$@0nj2vHw@$b0#vDu`r2j#g_Ev>O4df zCV?E^zk||YpLf5CAx!tKLZIMEHDBIc-$*qgWhL^x+Ce494^0^UUzWDB3@#}DnF9Zq z!9__hNeugok<{R_NNkdDU1j0rEO6e{T5g!9LeKoC%f;}E-+UDO@QV0hj)duiYxV9O zA&{-(0#^Xig%HU+?XF5Y+9i>l<%CN5<8ddsq(6p}T+$!Ii7)BT^~|@SXC@rT5xV=p zk;LvTKXo4nG`)g#6_#y5b!EPYjEUW>9WFeHi7qXULg-0_$=~Y@kMtQe zS-r2`%!rdy(_0H8%dt02{h4fEn{HcJB#b-9m*LrHH7A}2=hf%vhuW+m@rjS@|6Z#) z$9vnM{k!c5?u%^~wGS7^h3gk99p3ZF?Vj~aG!RG-g8Sutm?Jpii*{b=bAQxwq4v*{jWZ&57gL^S?Y+(e>MCR(!Ts_sOazA`sUjP{)|4|r zWy!;HwCMvxsI}93TZ23^6AyFI#kbMEIffIxZ;lE$V>s~zoVlKf^IjiqxJ#>ZXo!+9 zs)W||oi{uWb5!XLt44e;711*}Uo;k` zM15O|pGh(sf!;O3V@UW4y-OA#u1FN-j=@Q)7wrZos?;h{{D?54U7{2}R4>|%J8|`* zInTp77w&$q{7Yi$NfBx-7i)xv`Ok}f4mN%N5&eT_r|Vy&^%O9xaISARVM;1b?FJ{Q zJhdB~sPfd*In1mCH#kWJoZa9g6>xTg6E&+KUo@Uo{=Vb#re5{WWhAW%DANvmSK1LA zIpoE8QMg2a(?!4`=WsM(iml4aO=1HPcZ}1@1O5xUyOwk;7xU2*d=CXuE$}dBDd!C|+vFs?C;g)vPs$%!x%&Ee;!{d%| z_vymtlo5}3x9`wC0)|U2xgzn6mUrosUYf6^*YIxNp-KqYHlN+^e&wmr6ZDEhLctz) zdT%>q-(l`L&e*J_P2CcF;_a6+3WvQ4SfRt*!MA&y=z1oLX%Z4+iX#e0)LY#c= zxHGb4!=b2e0yn1NPvK%$@~HpS&7%P6xX2EdnZCh-fe}d~7};H#++mZZ`_zttW89J5 zNe2%7=)Gs6f+u)Zkx+blg(Jp~aChIWog##tr{0@myw^RW8A3gu@hYT@!R{)F@MNw4 zo+Nv(j=LoNfg?efT&4^YCV|U(i4bNMxE1F%sbh{0RWesrM(yVv4*6An0hT^WN(k-k zIxT#z!|Vv{}#ks7-RV-Enws&c?+< zX-5~R+n$>k0g_y)=F5)yW__CmnKP0MgaAoWhU`UBJdNxlI7tGx#+sl__o=fsj_5k= zNSOIRY46%~ba=wnR-r&(UIe&uTy`=e`}@I3MbZ@+NrdSnL6{tgg?R=Zp7O@>(99Wk z>MIJq8=+XK@D4A#?btw|ZO2I3b{1*2olW9|I09Gb^CqEoC+~@j8@@CGWZ*d12k@4f z05*a>?#z@iYZ#iOHSQ=$xUS0Ij_%JJ&?F^#B=)DlrhTOb+4)Mbs)hVs`J5#uEvE(QpeA6 z7kVa70vzWx!f?%pZBUXfOwt=2>!(jV)5bF#3PQkel+#prhZoE$h#f@6u4|CHH*nx5g1=iwxk9(%j(-usl_ z-%1Y_{JE|6?I`bCy=WkiIkU)~!l8NVx`$soG(AFKdll+Y8{SgiyOv^4(R5a1Q#6|- zL*|^!NOPE5b5527@YCe^j%!DQ8v5Fo>gqq0dphx%3jI9`6ZxXgIiSeLt97gDV^)<5 z&TDvj^G_GO3ll9s=K+AKZCO=2`Kj5P-$2^_b;Arh|$1TJ^p7b5T$m{iK#rf<4@piD_Ai92;=>@tTrDZ6JPlLW(MF-d62EoPD+ zk|^zPvAe`1;Ye(fV7M$MiShsK2O=^Xa9o*O47aU9s?w$SDCO23OM)L9c-6C>iCh5` zF4Zx%$wxxN%loW?Nmo{j7~4A=0`1?B7VzbSXt$)&z~e}2z!#71xob1Y2p2lQ~B2h82n zOVgECRuoBC4`^YT`*W>K@q*d&^n&S9cnuaw|>ul&a^v8(+Y{-c+}5^e zc>6<#^|7-n2xvPl#t(D%`Mr~azvj*tKGSH7K4U{;&)lIME<6yNLtez3X=q~hmXmBa zw8JGIjua!c&f&uAo#KOxU^j=v?08_>ng|<@H?!yhwoR_J5Cmf1fTyR0x*Gp(sLQEfDzz}X1kNj z*ar)UD=vpf*pz{9urC{{ITu@tg-PJZwQNz%aO<|!1PIfBW2MF2;F2oW4i{Qd#WNgo zFrEO08@=$OvUK3B`k&ua-9k8fHEF0}R?f{Q;&eZ5yD+=sjx`5eUKvT1c8fG^1e*j+ zjB^FJ33K4k!r`>IXFUrO=_+_244Qpa)29C!d~#wL{o^Cvg^6?(3|F!E+xmySzEigD zETIlbx?ccy*R_DARL-rYA6cgVG`p^LaA5-haNK4n;cig(?im|LtyE4OXvG{Isqkxf zd7o9#K==&?!mgpilu@&aDSubn8v&TWZ*S%>W|g#B?JVao>ul6l%t#Wk558iHBwM{s z5_%@*S8?l^WA>L1?`Y~>twpvuPHz`~Ko7TFh~dPan8Wo<3@7;r8v^Itrk8w#4dzbr z5jGf3^bs~FK9e~1@inC1*G9?Cu^YTc4kO1t=8i(kI>N>cPT1KNyr-Q^V)*L$;8kPp z?6yOMIms=rZrq7F!Um;3xXqbwo+ul>e5I~{1?ajKQ0whqCo!ujUNO zd>66aaSM=J+etd0#|=)@0X-<0(M6c45X!4b2<3HygSJZ*p{pQAhio|Hd5{f<{3^2H zz$a#u7N;&$*>Iq=`w2()@0dC1Htr;yROJRI>ZB^P8A{tO6-5rim@~&63y)!reYzRS zNV*wnk>+NoP2zYJ0{7yPfuW(-PAMNB%o@SSY7Vn#90*_G&a6Qsu@Sfu0N#rmX8=RGa$e1Px+5>WHJ4wfWxxtB2jZokgi8XRw`|6}@jw{hG z*z3zTwG-F8>zODT2gBuj<3h0U_>TIVH4PHWp7I`zgQ^s|sYZ`9sTIEMy@x!jMo4MD z=#(V=3=thh;8v=DOc_)Z(TzKCJ~1w$19SI5!%y_C=a*|G>TV6L_|p4UFFHdFbGPTT zrsSGmP1`p2T=13mlfAbczg>vOotzWm#vZ53E9P$5pUbrx`xjK%e11`IS$*&04&}XK zIMO+T^X3>9P^WIjR%V;$xdqB?XiKDZ$PutxU9^YoQmRO>Z=dOYbE<9&Cp+(qt$O4iLhwMAq zaL59Z4TtPI*>EUzg`B$LetCD}pn>owg41_w*B-62R&V>=0B!pY@48A_eQp7g%^f;*&8L?y)Lw*K5~}Fkbl?^mcWyO0M4dZ{Vjf1qFlQ$-emiYd1PhZX4_0E1sY@`D zx&kbccpe;yoLQ2p$iZ0dmw>k8vkUP+=zn>PQZ8S)@QfMP^d~Fj@Z5GN0UX28pgZON z#9ax1O=bHZvSo`b5mDC3T9R$4*$&!+tBotYa#EdPJ?Agf@hV0qro^!9gLe`Ky zA`wNF(B%KV=brbR^ZsUz>Fd1j{h#lcTQv$lP%x@hlqwBrNSn{vpOibhvGV@bVEM)^gFOc&fDP`?q?0PFb~C z`U1*>Y9tXA6gnVNjrxWV3xw-Xy@ir*{d&h8BiiJSIn;1vngbb6Y|(xZ@tH7pzmvIptI$yY{RiWN|7_nK zqHtey{KK$kF3Q-^%BE-2@xRX<7t!Iy9SNB9iwT(ILM&3dfV^%52(ge22O))2H3US-!Bnr+i zA_@+o0^Hz;XW1{pvuvCyOm|I6!of6`O+0xgFAV*YGHqR*hkLFMB-O>)GZ{$vLuU>=` z->a814&z`Jt&&gwqU75v_uX%x9Xjm2Dz9l1V+nD{9oYcJBdJ%f8=R;np5RBoZJz(u zQuWO~v-CgLk5TST^IpCT3>^q}vEKr9*NNNu_Q^-}xSzcz#8D~Q6pNC`gG(j)z{$jI zc?al?nvU_Me@TS!z-d5kb0?}3vAHtY1teQmfwUtx?j&_0c7v1DiP#NJQYT_JI7yv| z-QXm3B6folb%>d%noRVQzY(}?E+39N#8MhevAuc??jm=pa2*6v;*Q?0wWF>m*&BP0 z@dH~l!ily;!0n*YZDI_DyTN;JVBq+LPXaU z&d`Byq6;`1hnQXRk-!nLAA9dP-Spx9fL0)}-AvG^MZmfT<|hBK z)oy@%w|PWIPI%z#nX+#L$dr){$M&5W^FZgWT@_!Med-8Z!4C+kSQsg4x1`1tGA0wPpYbBh3I3izF8i7Zrflt66$3 zp5VoAz3p9{gs1?7V{B14@_)}d0vPsj?j$!pMmW)pkKqt=8_ZM0?KDn+%L#g@r3Cj+ z^(sap>SE2ioC)e=N^s_Kp{vF7Qh~%A*>Iq6$%bR1k!jqQ4F?LBd^pY&P>YFar^fQJjWIfEA00h}nywn{<=bMomLTJ)6o*wR%evpkY`^4H|$s6uZ>t+Oih zEQmeawZswA4$YP5sRD3V38B`n8r6j2Z<0y~Ugb=-GEGQxsZeg5Pdp*W%lkHGE7Ji- zdZ-1Vhnhe*uEM0-QW4c>8G;b75&{`S+WkRTtpJD|mMzvog-N%;6xS?1qRAa#`gY?^ zQulT@I7!{x-QXm3Z+C-})V!*pQW{LLz3B~SXyiQ0oZy!dcl6Gy(`K!Dd5VZC7Mu^r4erTJw*vjndDnnI zd!6kf)>00|h(<=16LS|v0Ir9_CKe&M2y@2_`|`Qt_ML1vh=Rk7Ah|a^!ii7!=PYq7x)ZS}w6h}`xf9(g5p)EE6WzNIbOhNO0Zecx8ikMMC}FivAsPqa zL|02QWfgX2;@mOrh@r#ZOh7vZ5RKg6#C59T0=Hx@6=;>{#+|5EiJ(r(=Z-5@gDX>V zwKRm2TrCaZ#8*q>>P5RP6=DkT?-bIoz<^6_n@eg0>BgO;Mv!iB;u=93+G}cqDXF`k z8+YQ)Om3;jK2;z*Mm8LzKj2`B?(S#CJTOU2Hg^z>6Ct=rX+R*>%H|Hl+6cf!QdtJy zD{cf+@MH3yXCDwaLuJE(t5-H0b2*u2IN5N_p%yVX&IE^|5nChVJzj*73RDu=`wljO zZ0=wq$cBTBAR7)gf^0b02=d`LSFh}qX{wWv5+01DVh16ZgX!A+ffYq$wZ6@`Xhxbv z5iK%Y6wxM0SQ;0EK;bY5p@tcRK-)2R4MJcm(~JtBa5AF;z!V^RsX$2KAB4N+uYKj; z)6K8u>oG4x$f&`+8___L_}co1{%BGKF`CplY}vA9clrX7%$@U75*N*rQ4oDf;hfJW z>Qv=e!;1Q@PSKi{(|etEGI#rjuD5(#51d%Ze)b+fLQWMYTy}8EWazO-jrsDg#21e} zqkq2gUAi)3$&2e0 zw6h5bVsF_pt~-#l>x$!3I(Hn2`|fY@{TZe#3ywZJ-@om(@yX!WHfPmM&27%eRBNA_ z8zE9U0<6r;Fn5ns+@q|DTaZ|Ab$u z%C}x~{=q zC#Hqy-1W@fEs?%|{vghZ*ta@Wh4(ch&24Ux^oXYQqRCwx*RnfV^^lm81~$U(I+gUb zZ`M%HlxP%a5-mItH3Pu?UE?`@)XEat+`5-y&fN4qm`rFlC9!|2EVFP{V=0h3mIb?p zX^SM=oIEy34l&NsE?W{a;h1q)HXN)>I(LC3cY}H2v|!`Q3qo{7e&4^1aU-1kV*qJ` zVs=Thg$JWcnn@Djfg`EVZc7^EyP^M`Z0_JT$CbJ7t(x^)c+d5M?XUv1-w$8|%@V3r;W@rXDGwHsQ7>149iS8n87^#@uAt@;( z?kI=hM})$~$v4u%iegmDBQoaLH7XuW$v~zmMMK^z!inyW0Fs#7 zQjydn+YL@sk8BW)+~6d&26lrJ)fyO16*o9Z-E7_9#GRSkAtpOwA9A=Bg79FLmC#99 z2~9*<35a>X!4%!16u5IMO;G&fCW%XkvTPn&|M?ID1EcJ@gK*HcFn3HS`k~ToHPpAg zXYRlhFvA5-lq3cUmm6HG+@W|E+1$u4}c&7gJZC@?I|*e6I-iY~D}wWj%k;x9-gs z{HWzK0=VPyfDle{(`pL$u%^}CMI+AiEn74K(|3g6m?=O$9A~785FE3sL`_KKc$_-dtWocD4r(4y1@P9<=f1h_?TW=?*mq`%!$r__zp*DJ5KdP=|{ z#`O#xN#Nu*g5=IjGGPrZ0M}65c1e6nX4r$$YqzOE;bVf{*KWF+{T#q9TwQvnd7D)vp3y(45tjr3N z?3c+z0e5sTS01^n?_EDt$=|J(Qha+EU$L1v0v8+nszj4o-wclZ`%O4Tns62w4!W~R z;=g;S24vQPGsaXzEx0h8C5h4d&ixVLN8sj;4(9Kx)B5MXJVc!lTTkyacU|D~>+OAM zW)9Y_bt7(isG9^Njie%fWse?^=3rXfq2R}JDug>{HEg%RJW8tnj1*rBE+x3<)NzJr z8`sXevJBd5N^tgodLK;CUS-39_9`0=)JfTJETY3yCuPGKOT`XUrf?4iXA2!~_les2 z*}62y)$uqQu$mDgR?wZ*0X!UZXOiJ)9DCQ3BbqDD#<;8S!qR@!oLh0^?L^R?hpW0@v$u!doYHRXEVjJ_hp&LuwIW4*HGj)?1(lf=xqi>KT;iQqj|Kq_6V26HW0YSm(>kUFFQ>w(yFae*FQhz#l0gFhv$1k**DjQ zV+RG>cVwx@k$u7T9V1ha#JE%C8iA{rsY&SV8sq$f*31bx=aDXzSR#o;QE7xol5sR* zpC{?Qb9_qWOpe4ujKcNVmT}9y#6JGU$CHfsFdNcQVbX>(WFeDeq7fr$^-EaX>xW}q}8=Bg-ufKS!%&|5U{mH)Xn3h4{jQCOlNB@efOpXlSckGvw!`&f& z_4E9vL!r$5{N+|HP7X&#kIp_DA0W-8!agP3Ie(daH!Kwj_jutEq2JDp^VjV?60TT# z?%4R4bH~X4btBv(aM`-n_J1<3uV3w7Jvn!5^vGf}?mKhzOp*;IBhA6INWvW#WRCd= zF*lx6zFB`gaOAu9gZGb)aGsgf!y)v>DN24cNIRk(gYB!d+lPDTF=TU?tX298!7!GFCgi)4SvS8Eu0&HSrFkiJ2 z;$(AYZ1c#$f%Yn!yU(VL`+MjmYcP||ow-&%fBFS~y`L+2o;y&MWpf8dbX3}?sA8?_ z$8Nnj&L8}Gk?X1A5NkQ@IDD$GPw8!LB&;#r8D$j;*P?Ts*ffDY{zsc`3*x?`vVb8v zl2eO{%|M#MgAJ#Jr&wp7a7U9T$X~ z#B7qlaoX#j~Z-azuABkaI&6&VH!imzzunO@1L+sBt74l_!bt;QZ8>JNuUjD{N(&i8+svzgqn0 zY9(%2+F*&9zb0$0Wa)QC)@%3fCLK$;8?V1a3v!q)_bFWBqF% z^h&-m+31n`+R%W=Qlz72lJqurl4NCaBw3l9=^OnBa)J;hG&awbtb{xF$Ga&2VvS_O zfgb_kM8`aU9|7U`ffYWOxKu>L!C)es9V7iujo-u`MHnq!IZsJVBaB}=zRw|g6u;K&P?P^@;09i+dSvzOVo^~ z^Jxi1)2nH-8+F==c=F$iX25-iaC1IBuT=~jD|dI)38ld`LwofE2TKLv@>U+D?%ViD zVDW=T^*xP^cohL~*1kiyrj6?9U;jR1WrND2v?}dCq$-IgI5?u`!raMODi(LL;b86% zPV_d1eTQ(O2NQ($?PTsACbY*ADLRS>#;n=^kW>S5d`dMSj>OUg$u1ybVEl#{7+)X; z#+>2}j8sQ>=kpDr^ZCa4?>>J&nL25CC;wx5JM>wmJ|O3_a0P&l2l|HauLWp@Z2LfHVyq>{GhUc{2_ehmpI|cL%9m=JwIso%=S> zzbPrjV?L~43y{ndV1CR@0Tzj794B{I(-aoY9Sr6yGMHDg_KzL3L{}5*Y038;j2@7w z4kno3oNyDKxGV?GwnfvybUu5FT@N(8l_O?qr|DXi(%y9hV=&#}HqTk6{W7eCFKgYK z+IGdeVINY)aAi_XgJ%D`u>zvtfIB*O&gb2`OSGvowg+-=YpMQL%XP(me6%&lb4p_#OcNrrMe`(qd$_e0ws~sY z+5Wq5-6z7G;g@G+pn#0xKaIlc^)BIVQo|!^t&s)PEwi?}Ua!p2Z(gsAG;ec@3}3G{ zi50h~>D&2qnRh~Ya>xR;U6&cYoJrnq1h~y{o4=Z7l)827B=uU~TzZk&T|Hkw5ZZ)r zPfnYxKAY}6wcVsl{$BnXp5Z_=`kM^qs9?NqB8rUJ`SuGam|D z`DCFw1v4~#Qyszm@xIMrBU~bI>7Q;9y4H4_zuwVjLOitN5Hl_LY@6GLeez$}c7Ai4 zvrm)x5hz@qD;Gm+NK`(juN!)i22wWL;xdBtR z@!!ejj!DtXi^TRFIb>)&3EOv!H20lFqF8$a=B_~dKYUfbZ>fFRV6y(`Cn8i5E?x!U z2DdGxX8x+UdV6eD^~@p>a9l14!X=b>RLRsQyLPZpg}~~SB4icLe2PH``!8u~x_K3} zZC_kfdd%wXd7Fcg3gHs2FV!j?nO`pPk1v&kS|ZG+Tq8(?qZ>e(JI7d|9o{05aUi7w z`7eZaPT|72tI}|@vTl5tK^s?mX$TLt zN`i2^%XZfFCwlqvo%>bEe8Bt4gu&bf*Q>ou=uh643TUr5cNFB^vSA_Ot=(-s&mG8_ zl)GiaUeMd`>aOM7P${{rVp@ZlO%F(_aM73wvJ|O0W*UcWG77j`;WC(wmM+jb3Q6wZ z4l%U&(ZRGI0drStOoDa&Bqia>9J0`#m{9m}WpLqd5Ng^fB4}cPdOYxI1t*JV-!YQt2=q5Bl5*!H(J6Bu_T9c&{WLnD^vNW|DZ@$8bncu_!>)Z)Mo(Mf z-SiDhg@zO!eQHgJLacdViSb_9gp4C_%&x+W+ooNGk#wnWwr(IX=q@dRJC!A0=t7eU z!PUj57;xO&S$3QMnjpZ16mBJhS!v@DrT3?4)PEX$VZik?g@<`Wcpz*TwtB1k15eT; zng%qodd^Wml8wOW2zOxa$bam3yq}q1#-ZFfpVvcQ=)ZnnbM7R#oYIh$>3ph}7-HS% z%Qt!#jlc(la5dU|r`G!TM&i1=N3}Imy~~*ZN6$>>v-jEJ)~Rx4p@@70?l!*#a876; zf*)Ua0k2o_`dvgdAkbb>H*XbKuU=SCWb=%||7ia7-g`Mghy}tGt&&gwqU75v_uX%x z9XjlNsnBiiusq=0v88f~xShrca5+s4Oga7#Ig`PK-@PBvhK|t80(9Xnp1_fpcR0ht zW#^K}hBMU3$iYGCihS<4I)3uuxa$@7UG#yIiQDoH&>J-!<4gaNcfk*YhaGT4x1HQY z>96L~id=1|&o5&{!Fe(;g4==)=H$~gl;|n(v8Ag{wk{v?*W_`yElhVIb6c3CDT!HP zXIK)mNkbBIoGLh&VHozOh<(SECU99QCZ2chKm*!K=B~#ppH<#BxMA?0Rav)C98SM8 zjbJR62}r5|5hED;lAFW>;;r)7r3M3S6d9w|{T0>_j7yFF~4d{_Zo3J=T@E^U2wx`_d zwz6#MI80e)DvzlwGtyL+Ei&xCv+q0k`;JT1lnn>>ooqO`@8rXAHZj}?nI^B(&z`&C zOMkqP-t}|uDhWgdAlzkNZh!4ryVZzD@Hy(dfWp>h>v}bf&tXG{ZG1Ki9X4rP zuVx}+5_#yUQm@Tvb@6~q`t<|PZJ{tJUO? zO#Coiy^J(ny%rf|d~TD3J5G3@gGrj_`bV7~q$aH>lPrRfwJ2rZz;1IkT&WHw-(2Zy z0_S|p{s=1RkD!R?j{tTRH@8LjpWt110665%p4z& z@9qb1F5E@k&iAoiD~E6+)n-^K&SfJ)dj+wU!L3@kRUcV+Q3&CfEt+{EEL*YZ%njS3 z*{6nB%eyW3jUd}Q3Gpfz(Sh8Vr^tWq+yR0gH4ax;IZiKGp|@{b?dhRg-6jTNk36r1 zLURJGzOpNBu~;n25^mKsBL6@~q?T#=Ha|7v#B9$p`d&}|InKI-+Aizo`8Eef_B2?T zX2BDU6g=^XD0l+O@@{~8?nG{NPS$l={rQ8`jHSH?Zoz$b58$3&c*IgkL|ED(F$dw^ ze`%`)Cnl?xyUo$`EqWusV9JJrrGkT*>6xd4^XE2K59ObzUn^3<^F{zTZZr?Xw_Pe(>Dz7=7jrC6}P~%jBqPnI;?&;X@vUE z_58|DcfCh+5L>jf8a9QyusM@Iy4@rGr+(>c9bn-VYD>|~A!wbM#92vt$Nvj=;rKVl z_8-blP2_IvQ~$? zb8XU#-fklRj#DRbBQ$KDHyC?xkiPeawQ8>>}L67-|rfKdO z4g^1%+>zD)M(B+kd38Ba0bJ(}x49dBq@;gmL+?#qKqaBvIiG47@>?g%UxmHraDl5A z;Yv>#qNdF`(pPF`5v^Ny?>Yj^-D8BiarZZe?yS8QT$y)Th;k}6qQhtulG@6Au0b__ z*3U(pDh6DnwmAsx>BwN_Yqn=I9mK$%g(3QWdE>1BeeZpa2<@aY0daj;MXrFP7m(vq z8dAuSB>jO4kD+sSWZjO?`03NtQ#F=^4h-I-mAx@m8ImQfen09X&%r<7>UG(7QDvL| ztu4*!Jz^hRy>4)HFhyvu;OcdOi>Fv3;K0=@8xBn0vf-Es&NQFOhGQnU2*H81)`dH= zQs`sLnao4SthFpli)`~$a=19pGTr9*yzz5(mHyqP!QL+*I8`zexaGmAp_A`bh^=sS zUWmeQhZqx^i2>6r0!)6x4#*61=ZMebKBbli?hvDcS!LELBLVg0En`FEw;hk8fU^x3 z&I~nE#+cQ}B&jXh@sFXl=wxs^Z@m}%{iDmh99ZN>d+yl3ADCr2g87f3M>G#d zxwFDYl9Do|Fn2bjck?OR2&UcKT^`ovRj4ntTW0`a1 z!4}P>`{BN0P~mq`E7KZG!VKVG4v_7R55NB6GxO2Jct8t@?`f8+mU9WRTfGwK$l5B>h!Uj`Z!|{g>X0ff` z`C2~+`O5U~u7CQsh$uKN8mET~cRRZOqQ3n`XXo4*=a@Zr25HY-n6&23Br%s{oeP}U zjbN4QWF?N-ob~qaQ=|TGfzIG7(d3dFpBXi;Ft-y^jz+ItrsAS?~xB)3yv3QL7$TF|+a(AF8@*pdmqdq1M# zdPO)nWdp5^fH#6U|@C%Si*czjKDvgrphjpnsOD z*#nI{pP8^!kh^MySfu9_&cP1R;~EsV0CJ+gy)qB zr%GJqD3jd6#}?^F>TbRJ1h-!TGUZFJXl06I8Ija1Dt4C1w^Bg5rMPr zyUTDyi`LD-Cf1m6*JZ=*(5Qjs1JsYuar%V73t7L^b~U}DET~QljM3x>Bd_i)$yO#W zAgL7X_>|bhc#<4qT&26`30%H{ZT)A~R*BhLxn^wgQ^hop{zoGf*i}$gK{)cSHy(CO z0hy|f096Vpck8C5)$7cCs%pAixsw;xgZNJ%S#pQTyAcJKyvYmmD<>tPSSz~CB}C(3 zS&6F|#>Z5c@w&2d;}*T@q#m9RF%TZ`0@}ZMi@GI4h0TxT$)a!TV#KR(O3nYO0l`v1 zIMHStM}`v(!)_0!in%i5$vb&@7ur8t&*e_ah68sY4yMVS`R1Lw(X}GV9k>f!xFho> zYVNp98QE~)E|d)i?n2pc%u8ZAW@N(|OT|8-W$!z1sPWvT)EF!5GK(eMr{c)}h!4o9 z0b-KG2gH$KhZ_53BA9^iK;dYO4!W;Xa;UMWZ-Qeq;xgeFX~J1#7|tfc8EPziME;q{ zmWt_6quf!48s#p*NI_6&@U)QqhPbvA#+^0!N>5TU*4Y)YOdC&vfLH zgzL=z%d+rKTj{kM;M%UtkT@g-luq(oe4|X-eLD?aVaORSU zA8@6Zf90N<0>oMajvZrea0|bz>~Hpl_aJjJcg|o}H#kYbu5NIWf?eIPc$ zA^^?^2Tg684>GeI?V0RTs*;e$Ce5e-%NG44$eA{0 z^e69T9I&*@h64j5!pU)DTcJ$|CucCNxx;NPIe-M=QgF(UrT^dCT*BNToMhuL!lhsw z_QV}H)bPHO+^ZMiB=_n?ILW*jdu<%BXQsxTaiNeu3^9!SVbY9D)u9H1Nx55`XM++AG3|<_^L^^TFJShvV#-2q(FI zCc;UspNVjy>t}-Yx=Q-oao$Pf&h$ZBBpDxwq*fusIA zCLAFg+X%!v85H52G~t*J$PJEoCxarqlO`PV0lC2uw?$AyDW1>PbESCP;D~oJD54aP z376Vn67OVCL@6E2ZT$(^56;1 z6ph%8umk2!vLuFZq9rlNF2qwMh5DIXT*3buga9#q2q(FICc@!1XKoATEH>R1j5OUA z78!P1*d)=-Ik6V!j=_l&YdQUH8m!Dxg^pFz>vmJ#C^Saz`JML?#~?+!aVJWOCVm8G z?NgJxcs7XUJEh6XzVFy{n3i@%rWzFh;h;E}J4x-+%cS<{ucY?rbn&%M5$-oq`}9px z`*azpeOg*T?Ne|$(Uh_FAIuKEdi0|D@~!j9Tuycvw%Lv$ocC(EoPeYof#z_T%^J+O z=&nP%nI^b31a9R08NovR3EZ#?u5gySF#P?DG}CM?G7M*vB!Gn5cQ}}AsfY@8g@iad znD?ue3uT#oLtX!UmRJ*xp;}EmV~H~~j+EhLr;16kQ-zV{sbZ0YJ1)D>33oM3Vc~GV z9ZiVqd9X)pyKHm)1^@a!S@#Fqo@sd}xwg@R%K;unpi-)zNhCZYe27VUK(g!A z&NnCjNM|@G1iMl=8th8zXJ&Y#X^8S5BWutq>;nU zbU%bEHYU6BM*sZ5&lBndyQMEeYtI-D`vxHY1sum+QQ)pyk2{H-#vjpwqbnz7|6D}= z9mgHQ6>I#ha_>OyV4d_Y2m7~b@8r(7@@(!5(&jEqT7zklWH4z363a-1y`1)6($sYG zDk$5&xT^J-)!jLF9^fn^6~ZN4U#e9)GJi$lA75$-wL}aiXFf$Zx=NL~bLjaQ-{Gx3 zp1A`bkejkB$~X*?SW4Vc&g!&Tt6!edQvi3IoQZG=(_f?|;o}#T`&8-GS%ehLdAQsL zQ<8_v4Nj7W%MDJFhszC4l84I;PLhYq4Nj7W%MDJHhYPH=sNWsi@O4a^Z6g)m=IeTg zj2#4Qb1vP_jXO~eHMq@@J945p9uW!`S8)p^F$Wg;Q52kYy*?>f@B{xH!inY%ga?EZ zA2}S+!g{dpFqBt(FDGtg;$VuNyU(VL`+Mjmt7wMo>_S6(Wva6Lq8SDpbJ9l$&W;?8 z$Y3^)?A*18ARMOw;b1PPT2`w)ccnV2!D)5QZSQTrKsQIRwpC!gdSOA4YBLJ|qxjRm zBj9@FwmHHTt&&gwqU77<_uX%x96Id19RqakK)C1wClj~j9iTR9Iwp|*B@va(4dH?9 zJU8J%oCd@NOd_1*axMrbxtt5anKy#0axQLgqRP2|r5#r$?^er0>4EwU- zn8nXLq-Dc_VP7^JII=0+pbF!ISz8CyX6ySgdo)=l;ibatnao*i8iyHa8iy@1?0dCI z=2=eV5R=ta({100Dm29A&NL3w!E9H>m$xtZay-I^ob9@Na_kRt^Y?y_Gjz4 zTHkn^pQ@Iio~pb`PfU|XJ(#_%fa{eDAfa#_2lfmU=v7pGDWS4nZ(c&6`n@`Vw2SI# z=Vys9QgIg$awj=X4BX>jCHYT=eSpKl>GhV>)PfzVl`Ha{PwCUs`@RFq z1Hygqb{F-ZH8VC<-teAQ@}76G7NSoPu34WITDKYLS8lm-Ik5G%h?U9d2$x|ah@U&o zuCf*2!ke7^>D?v<#kXa{LH-?{Dmxx;lXy9*q;_-JWObJ=pi>p^P{X-PAuig}zJryC za4Ez^dx8UHxtwHsCJ27i1XuD(0qU=dDv`TWvMThJtYZ58ndrj80Qi^zvjPeEkGjXj z#dRmE9zrb8;>Wf?_??PIW=JHfIn0x01S2atVZf1qNmh}V);=ZoogFZl8eB9hs&B(Z z(+EuVh0&zMv4bR4EI5+DaXmvR+|j4jgeW&_URYwhSMJ)!7~HreA9(Jw3^xKU6$)!V zB2E>~)tk~_vNY+eQ@tP2Z~-BA;!WS&jev0WK+>PQ4<>B$O0do4v_Y}FB-h{q65j}t z8%%_gJeYU^B{YA`suytLsCUr_suVs&<}OFh+*>X*sSsRUd`gINci{AL1F}i3IBT0b zS_5;vhDmK4TGNRflC&){t&PKxM&OoZ8cs?=?!*r!rz51nm6>-BGY3Sq{l;je;qkuX zIy1U(7f-k(FYo)#xDo7NSA^T#ql0$j#?8bmd8;cwzT$nU02~hH@Me{*!7O>od*rZj zz1rLrgt_~@^GOS?e@>$jq^G$9?hvly&)F@wZ-g`)=T>GZ;7;^L0PbYNLAyO%nMY?X zNc^*Wf34PIC)Ka#b`fC4;e0>{H}_oe#JqFw1@;zdrzUO^(T9sOQX!o9x#JWrgcIL> zh>KuEIMD$lVAxMd60--?`Ypn?=8xH&kvf)6#qZiPQWi9{Et7GTW>gJwsjjY zIPzb53Ni=o=n>s-=?*>ZwJ(C#z8RTJdu2Ukn5<=T$4HYqi%dZh}KKo|%(-@uU6A_{jr!3RKoU^{p77D?X<-@y+8d7xM-L@3X7Tf>2GL2KkHU-F@ zJ8BBBjzH1?vA<_I6FLYWT#Yv0skJ`7k+|;eQEkoCw?)I{gMGL6+2YnQeP*GE z;2-WrNKHpzH$qF2)7>(zWq0#NV5E5?SY-G{u*q-%XFCc`_EG`CPc|F~ezM^}@RJP( zf}dOx$erZpE_pRB_3V6uuyGtx{Mv&eADm`#$w9|h z&JAwBpvU~9(|8Z%g{Ee1aH94dYy>yBQAbMpcQ>pqVD7l4W^QnWNmH{!;+vYe!8IgJ z&3xjUnz_LZCr!=nh;M4<23N5`HGhuJ%L|x0E-u;)PTV%99xltFhH#RzdJ#@?RxiTQ zGgD+%FEkT$yYIv`6XaY@DRD;_l$F(saBZ`W2;^%yI?(HCadpq9-c=HFFjI@ImDDQH zZSEwsN_2yh)GE;pj)WBYMbsRIYH7PumQ|R@BH+yA%2P)G&RL#XHXIRaomDJw-9X~U2I2EB?U>NqlscRHP>KX;b)HO2T*o}aL$u27dD0}6`JfS_=?8ywMqf+92^D4gyFCvKZRR0EQn)r;Io&gw-t(OJD?W@aFu@| z1jlak2*I)YPCguGt(6T2!9Tb%nLJD0EwCO))^+M^n zRxYN1N4`v_pFQfm#4*6Nb%C36da1g!>3afB70v|L)dj9uo-Dp8Nn&D+93d9(xWFw{ zW~n#7^?>?4ela0m=V2z zz|bLoFe7>afoQbTMR@4?X$ig4R1y9=uD;4QE^zDuijF2($>hbthkzt0(#}t5cA?{! z$#)a(oc)04+@0%QTg`f9l=^z_6SUs2<8egem^s}{%4I3urqIhs62a(9A4rxUu#3R` zaH@)bMX4;>+P{9X0?fmhb^>_ImLy=3yhwsJ?TN!ktA$PYQ!@eF`ZO8bUIKUc;uZhW zt0&cC&rY&JK^dIa!88;u=0!+K!ntc2%IWK!Exoq4z*;4A(t8*-z)|j;PnJv1s<+E( zdcm(pYfawq9$O0;YWo51lb@$5H&#vwJXSwW|Eieba;ibB4N=V0kUKX=rU5dF|CH7W z;QV(8m!ZWY{!0n>)$d!U^-o{^7p>FIeFKpH0*=d2L%40x@oMM1BlJw&7HLb4ijXt8 zeTQ()d8B3>OP&0W`wskf2q(FW62eI?ql9p5FvXQo;>21vI7xMl+~CC3HR6oJZg7(P zcW!W!%EG(BN%G&h!AU9$?*=ESEW8_>q_XgCaH7h>gIMbZC#p_6`0w1{L~U~jAVIi& z+penJp2(yv9vp*aS*P!?%zlUN^YrB&0Bl_}8V$*0#_Q$v08ySp)Lms7;v2yKW@NvKKu%S<4uS_rfOh>YH0@u+(q9j z`in2_3qE~0mjTzaVF_H9AV*+#m1$I}mH- z!*NC`*>FZQj$Jfki#eDZ3ytt6A5_~~%WTo6wU&{lwbml(sbU+h$#+AI4%u+P9X+D| zoKr1!!}cEj-8It1@*EQG$VQ_*xUH4Rll07Vd}^#r`EbQm}y}+nf$2`!v~LQn)eIKa6d^^n#Z0UOiVhR&9XH9sNQ^(rxY} z!*JH8h9BW8M~KB?0+-SgdOljeI6{P%ge$y2=Wf&VAqICJ9%`JNyWHg8PyWYBxdKVK zb9_p@BpgY-Bu?&5x^Q=|dKG1c<~?2othIjvoM>w;>^piRTzD+OU+3kc{@9*B!&bMo zS61P~yv-SD3J(@Zw>ekv1U3SNi+z2uS}pTYfAu9lv(g0S>Y=3x$Yjt%o|wLAg-jsn z+&Mm_bH|Z*-<>9K1qWsDpP!vqd9QG`EfiJGIpo4il zzHVsJgam(!`C_wNTX8FwJ~(ZO^+$I@NWR;@eWdr)IeAWs$V{yTvC8Q^N3ovCea z{bX=#t5upWUp>#dIh5i-xI-UgQa_oRO}}(}y6=_eL=+?CiXx({lHi}Smm4t~*RW{57EcTKT& zE)i?lZEl?^Wsl1Jr5>G z(FnIc)LG5(My}wl@+b8%v!gx3foB=vZp9x_6P})=&bw92pQY*Jp5egK?mWckGMT#i zlKNobEv@qK()!^a+X#T;EbR#Q;Q24Br8$yK-&C}?{zvf-J;Om%0K#3b)KfXN;RU_i z+40Jqt0LeY%H7;-b+jY7Dkw4g*Q#$^c~<~;oU0dab2@+Yk>u)igA?Zi;&Qm~R1w|e z#SEBafy!>&iE{Nq=MLmfd`}rJg3*mTNv>WuI8mQMGb-wIH}5tvs0HW7oh09@8=NHHs~emo->Vy(DBmks{Em~`{O-<0 z`h$k!{M+XIkj%hn)oEu@-?2nlcG%K^q{_16(`2S^3RkRt)6nfI7XSDV&jyklG<8$+PS>ccKn4usq;4$H6r7%X2elu}L%X zU*wx}mUb8JqC{ER!32k?D;o;_sWl|7-h@6MZQl2xcULc%;1F(O=Avr#0a=xWd(X$z zo8(pbR9Wk|wkJ$uiYfe{M?bY|pr1cakY<f;Q~qt&R(6~ zUA?doWWzy8e}rpjHWH*9P9x0(z3)3t@IyFzAn8xu2NN7>Zg8=;O6uK53EBwFEbY|| zF3hEO?u`4+E}9`54hpBshGUfw%;A&`2Q@lm!$Hvu3ioFB<9_vgP}NuWwNy#AR4nhL zDXTE=q)9UGBqNFNK)sU|i6#Br?mGtOb(_P=lnnvqIE%f$0b+Z!>G5>Ar9akglbGZVi% zVyTnkrg*pbvAHwLxzNG<>gs0ysPlu=q!ne7sU&RQv46iwGcwhZ{!lBxtv9`-q$)Q! zQI>Wnis%L>DXGd0PLieF4NjD$9c&lf8h|C*@3abUEjZS)>u0qP{eWheRO_ej2ZVUlm& zLP)+jr;^}c&iVMfRxxm_+}%+plm^$l>j*|vz*-^Lx*fQLlR>q zs-&cdz_D^C5rVVzyNGbtJYq}5n7bAcgyTXia4_HBJ4DU!M?kMR?`{3D79!$RxR`c? zJ5?<~Jym&?nwTb!elUAm0fr7Pb;X3E+uHfW6N0?FZ*xf1MD8TJ3lUDdyU+-aVX2x3 zXO5_>R82QHN$x^7I8l~%a2LA4Npcsu!HIGgLcruLBCAXbjjp_RPlI5IpFR)KrE+=W zEu-L2?{jgUvn{}|PvM-;($cq#;1T+FE2F)ulOTy99BH0wX|Fj1G|vS|4B?!d3OU4h z!@g`d!$`%>l%yotaHDH+&EoTbBm3!vN35lib*lHJ^4a=_!oB~}RtxTfW8UE)3J&cm zqL&JAhy7kf!+{?`_EItSoh@g|h68J@Y&fvi%7z1Lt!y}E@iXOU*>GU3rEs6+c|5lH zgt7jwS3j1_j}S}T0yLGC<-!0-{0PoZ&AeCk%jCP^5R<*{AnF^>%uLTb9h^V6xq2x7 zMEzQk3Ic?7u4ia!b4SdwW+qWANjr+OOyA7-%zsJ;(@07R|FSWdTv8Q8OzIPfDN+$#>h`7H5%bA;mu*85-rciBKz*}r*)&UrY*2ZWR;9g&|PwJI+= zO z+%;^THyC?xkiPeawQ8>>BHB80wrGS~P_?X9d+thoRD;v{oZBM$n{&2kgp+KGrf?kx z_Vg9#RaAW`p|W0YUP7Syy*j?Mi|Q%oXT@1b#B8IH^mcBe0Z9XuAC|mN;qo=xvze~Q zz@CL6`tB5K$=7jpFo2}nocxcK)JR@5gXwo>hy@NNg|i>Ktc1lKzb{hV2vC~fI^nKO z?==Q@3tw9lqEJh&l`%>a^xx|9lc;VIfIsI2X7T^C!f-^1yo@5OC+VGON#?u5YR+ zAf}z)=4j{;f8TMZ3NDp0tFr|!cUhtD-1Vc{KzYXV+<{Z(86vdTe5vG?CYyI?tBX$w z(WP?W^m0RRZ<32%K)K1ClA9P4x|32o-Ma%xP8H{;^hR*}GFcbkl%a6Wr&@;mI-~z8 z?7gWOIAsv7^pqiL+MFYOrDhh^nN425sh%oUj0ou-JzO3ru9)RaisTb3nSKOy%o`ca3jwh zQ@_7DL9N^TNq@ha1wC(b(0~wbZ2Ne%d6Nbk4f}kC%)xV{H~lyP)v%$!7s6d8)v!Be znXfM)z3HO`RKq54v}GF$-9k9J5$Lm+G>dQXhIdQ53CBXW+~8g%&Em5OC{GO~LEPZ_ zlkV*!1=Nc+V{4hZ>;^}Yh=bnNc7tm`+NsABE+PPq z>oVpBH-xlPzxh`UQE;hkgcnFV^~VGhaE5jaZrq962%PEL4KBRdMJQaHoQZHHVs@(s zKH9Gx&lazqozUL%+!5cav-<34r6wI0!eR=p)L}EDL?- zDycCC_j^}KpobcTqt@CkhiVdQ?X1M`oUuP`Lx&^ZoP0>`J1gIuBiViD$TxrJeYcg| zcNa4<2!F^2nBYZ31dNtwPRwi32*xEpumdi9IAUZIP$8yvY_{UWYcsAAy;SCRBb5OKYlaFN@054~QSIHCe(3Wy4z zy1Av@B_&a18J{^m$_s6!SnSBVQI4AAS_Kb9CKTk^Cue)!qQ~J zfz>ElvKhx%Ds~3}%H7^s(?T8p80&vAeNwVCTb51Fd_W{{iT)KMsmsYpMgfUA%M`9$ zhi#$G8OHhVJ}8+29I;9fGZ*`QtCfZs3C4d)jZ}_bCf`k?PfhPu5_u?Gy*8)S#RD?w z*AG0mg>JZa%p$;FkRrgQ6XrkH#(}`CeFV<=lf2TeY(TaK&M3=mBWL**Mft&Lpbpz{W%Q?;Y8Q^2Adcy3*Vry>VIL+ zUiG&dzs2C(MT6)CBy|^Zq8E_VJLzmlN8z4q^=h!~#(ips&ZCmKoV?4KTx=~4rs&e* zuy>A7a^LWd)p zT2mQmnolh<;Rbe#RdW_7?Eh}%Om$2@ z@7_rWxJS<*J-J?X_yFEh4YdiT)XkT^}E+5DKEZyMQc&}eE~u{=Ox(% z`%d&=f^NQp!2J@v$zS59(ORyxTkHO6G2Gk}8?I!AYuQ?gl5Sk~w%u+~6eD`gVg8SAm2(#1Kw$b|J#0V1hG5 zO;0iHkt^^8r3sKb(TCX7z?9<-my-)zJb@)I?{emZ#$4J_MBtdCHxl*4xEdYuFCb3N zL^#n=-*jaX39}rjXyZs6^V?6KCEOi&Zk1l{(zW}NMcNPl`k4W0EtuZTk}FV59sjjq8gd;_`bVEc(}OAKPFr} z`FiIQPYCkzE3$>&+9GKZv6Cb}b0ntwxp5bU^gegsH{iiFd=13J{)&urUu7s(d>x+U++6e8A}b$>k$npW3u7EOQL}v;m_YQ_(tlAm%r~cdZ)idI?>pL2IhJ%f;6}US!w1~fbmE&s018vkroeFq{ zgTX|&;xA{`EB^Gm-uhTteNKK6)v!6y2;oAL)B4wR&mUY5n;S7J&fA>rJ9A?&GSxOHZ~@gIaLeC2652H+(Mpl7({-ZZgKgWmpOr-1 z(suPyXDcIVRDhEt@tGWn@tG8^%ZA;d@AfqC)12i}<=g6g$G6c2Eqzp7`%HfeE|z5C z#F6}Va;g}H}^-Z~p7ZLRh_Z`A@889PIbJL>4c|Vj> zCT{R9i9wtg!kMY<@sv9e$@^v^Dhor9eP)_)%)}@g4mQH`WT|W&SYgZbG1>ihDohNK zL5!MNe3P*et}T1l9}5~5kf|zMFn8r)W&ZJ8Z~eLHJC#tEt-g2xl@LHjs7T=6Y<$Mx zik&KzyY?|QLLAAqh-Mp&Y;&_*r?Kx$lI=T2hPOEx662T2@ehMpiNKw``0SPoO)3Og z6^ks<%ZAy5HTvj5(!AFg``|_(nqF3gNFqq$EpJ&V)yg}R6;g=dUIkmpG^6hF7XC|isRUv~J zvns3sIf^3s=r%X{l9+uhS=bwpR1zcqW1mvvFh`8p-F5t7{Y?xX2Br z!CmCGITunWe=xbwCfRUs-^qvL>Ke(0Ga{+jnGy+gk~4kRfD6cs3Q$R{Z&gICZwR4B zxbQtEPIv$v0pUdJ2*ixz3__rABnTk@rNslJw75n~i^qbr0A#Ad1GKr6y)vODRRrLu zXvDTcgy14|BR~l(`P@zXIHH4Tz(sB_4Y){MuTXJI{@fXoSmXvXqJke(+>$?-h9nlb z!HlTj2SIoA0=oF>R>PRzt4sqHbQe!`NfFvBWEYy(EB$)s6Hf^8vX$kQ%&rp4$0!0B zR+iZ>6PFX@PX1ds*09gIUc(LJtn1YznQqQVn%?eo(^EK^4mEH&ncO)CQmD%b{C7jT(_p zKQ?h;V(Ct|v>CMrdWJLhT{9~TA*HzsZ-Vef@EY0#=?}8uAh|;}9190Ehf_8jBzMS$ zgCm;myJFv-2|oU0ZoT1@+05@s&P)ExWC1Yj5Mu!_;WLwcYDRtABr$!HlrcL2yb*!h z9>^6UUmrEU<{Fj0lP5m>inq2oYcNFMjHmz-jT%S(N6t)+G@}C8r^%uM>Jzw@C+3E_ zyk5Wxv3RX+1%u1$dA*-1;3cU`;G7TX0B*SGDR-F!bO47Nfet2nScru)4BKmn1>AS3 z&0Q?Sfa|uT@!VPa$ z*@7#1%KH%w*J~}{j&Mbv`0z`FrJb{h;mV{~5(7vm-0_wPp$G+#;PqO)#1L!lmT&al zY+UrsVJ#dPF-P(cv**@v8%HlH*knPI9~o&Yd~1 z@#LMnM668C_bM9>;#F`kMaQdvXhgSp&F`M@r@i(?Fk8n{$+cI=5d)IycU+DbkmSDO zJj*zkqCLxCi^jo}93F$*i8g(MI@z4eU5{_mhn(Rtq^X%9jfI<ycV!($Lma(GNr!W|8vUod^TPDAMXG`j3N+;^qcyv^^*jps<++GwIs zl2@!5ga9N>5O91-1V5fcLkI1DcVyiTjM!I5#J)}=_6bZljKPlBCu5)6QabogldB}K z&1vNDs&}%7UYY-oR;2oTLpQMJ(xH;raQ|b1Kt!FPQ0Ji^tW29T`jht?0rb1nawlWW z&?%-P07=hG@;~+|ojZ<16P#=~SSqOvrnNHvb2JWT@e9Mbr)qi~OvnS04F^Xwox4!2 zGC^k^5IHwhx-3PsN(Ao0OT~RKS>T0+94Z0PU4ixXhKwZ8wp5K)@ZX zgwRVb9ISmTQ;H#lY-O?-Me_({B;9vL7FD>)pLu3lpC$__d_Cn;C7#Zmh*Jer5*$pk z8g_tG!wyKOhK+D$HEfMk!w!h3h7B?82uB8yKJnp~h$EVlGZ9X_oXP132uE2XPki|0 zojVX~5l*z631%FGqpXRvs~8uMZP-rix2L^#e*m~f0Jq}qTx;%zrSqPD2XIXR zE_TFZYcLx$6F!))0^IJ&6SX%=-ANpl_lWZIRpBeM6~KKt=%DiIYx@JiPrg^W_=Ur@ z12~=(zRlm{zu%(Dr};^L`=XZqCIcYQi|FD(vm0|AbazQ;Ez`fcH-N<901ct1I+lR9s@_Z%+ZZWO>U z^2XkF>V$p5;XY;GZ@%w&udRBeMH6M{_)dE8uJ_76z}+~2<4NJ$d=mftQSIwiuvX?B z;x`w3n@<6_md{MJ?z>VAh2ID>0gfky59U1n`+*V;w-5k$QaD@!|NRy8qDSUcmv&z3tN2$zrRE*sr^>eg$CJY6ZZH4+QMDc2{jv(^ z?gux*L4afANAI`LUl1>=9B1DT?`zTy*P~za9%2F9odFo06h3$7`R})=7duziXLR-+ z`~%$mVgZDIm|4Q7F5mHl+P2!Bn0i~i_Y4KNYXHZS!Uyv@|NT*ydcSQQV$n5(A7Zxw zu0!T13vPCj@I&lA!11K;!Hgn-an7e+)D=rK%HCMG(4G$9oX{c+`>--IyTCQbkYCR! z{>;n)aGClpR{J(srPNHDLn{;PC0eY_1#pSsa8P4R(}%-BI}=Gd%IW)WCtNk-C@cs6p@NHfV;Mid5 z&qu32k<=Bz%JNGtaI*`iQwyCGzVGU|z=gRKe&024f$P?2s{ZSEqXW1xp7xo^k!CSc z_9=}uB9Betnb{cNDjgc4UfcGUlDOhAy-OzHrtf9|$Ciqu!Fgn{qjtJj(Z@IwjN+_kb z>@NIN>E;6WUEdwbtnY=--McPuZ};!4U;kA2-1T;WleF*pyTIMa_px3#hj3;2BNw<* zITtFyQo;qlco(>=S4Zh5mkD=UjBtUIGUHR>cA<~( zeK+0(uIsUv^yO8B8#*Srz)70BsQ{O6W>@vlXLABy)?1pS;JhzpMl`?5Z_6QgJRs&oWt%Z7}@$br@ zTF+=FTMJ(*YXOc8rlh5^$pwyvrirM^3x^nXf5=|$9d%N%ZN3)Uc55#t2*2;P0C#Jj zXrk`Rp{i9Xeyp|oq@QSoYdgS6p1W^d;E0^5-V-lp9(I8nLi`9-#QPDjoqEjKzqM+c zpV6Amo1r(~<-OYxtjzPkUGJGUwYU2{u3cL_LBG{pxPJF5z_F#$kobb~h_`26b%B#~ zs$2)S4^Nd>=hnI$$UnEZ8oyNdnRy%F*kDTH?yd`5&qHUG^Wr73e*msd#VuOS)mow7?oaDL7=mJ+?jvpa2z}@Uw-_j9g zUl4AsrHvq+PydtetIy}Ts%`n8u{N=VaE0q}fOA4i@B!s@fg`etB0*Nk?*cdQ)Ir}% zmxYV9G?~%)48L1e?V9_ZRwri_Wphs9OQkTtIiV%YT@e?!22oeE0^+@s#a!URTne{E zW53r-j+pkP;$zxrA1>!}BK9lmRB2pYxM)-s;23lV(yeNTcn{ZeE^tjtPt)hWD_p;; z-~zWX?L>WQTj4swivTyOS!HYP$_c0*17a=qM__YDE+T!F_zQ?OEO0(2vo%$3+Oh`CdXsCyE$#Jy zJ2tRq?nmj5+!ikQIg3P5sNK=;sEb3}eGA^(t8JPuTsNn+0#bVZtX@T%tqH$gTe`r7 z{|Ulxgw_D}b^lh@%FIzf_-)=9;Ml;{I=moo`iAhqOf9`#$i8Fsl#`N*GIrp7Y4gXl zlSc({XTv=UFgz(}sn~EY@ZWDyukPC88-7JNcd-^g_=n5owkijXR!ZD^;&)%gfFS+O z=B^gNt?hr!H@M`Rn_roC%~$su;oQ{$xPry5`kwu%)8;`9ulg>Ehr|54j1AMOOTHNx zXx+E0UOigSHn#_}F>u$uXLj}a+Dd^|Ip%8>R|>j-Y`9kd?rtmF!!>o7pbN-`YX)#1 z*I5?Getq=jI$t$VhJ7J?sk8<-MsCb7LYvr6I9z-7{pS0^dzF<%If}$o{iD4$ua$7P zP5`&2bY-Pe|I3>))VitVy)1n0F#m38%nM46cP?xSrTbm`IZF7c@*Z%<$mi5?%3x7h zz4prN%f8=yU;5Fb>Z%6$150v$ri{-nd@w%*xDRV&RDaGoAdqfM$hUv7aJWGL$CJYE zyCMAdNA3DMlUg}f?|`=Jv{J69@IwsK{aUBVsE(faZeY~d6Uz5~;c%Y-cZoC8s9D!N zsr^-DqIM&n@VT1`a6Bn|?#A=qAGM%a5p_rXp@E-{eXA|)FDNR&-glT?$fFDAZa)A0 z7S;NxX4>fl;Yai$3xNOO+}fF1?Ha=2Fd>eC?izYlyWdy%5xs(aKfK>u-$2Q?LO6Gr zf4AoS32L1WduU546!!g-B*iln_wIW-)D5WXqjShdTstJSqGTJHmgzMJ+9TOIs@{l-C~2Qx*XK!*@UYq1CA> z{8Vwvzf%ic)vCWN9PT2|6i~wF?pFX{SSx9|(;?=-=F=>_UONGOwfgpsfaRt=DmGWtCp3(!kz7Yx<27GRRgjm& zz7ZY+xbGV4YSAaBX#J~xp*)$phZv`f4VM$()?^%|o?U%Wn|vW#pmKiUvI?eZvZW$v z?(ze7lHo8_bNGwTtNkX;^0nxEO1m*$xIMEFa98Z&T6JsY!pgWO_iHbldPnq9DFSek z2eSmg{XXHQ@<+Kx1N|$FRa%S|ZVGr7;3RWb+68VG$z3*cmJK%$^RE6U->bdNBa(<} z!@c0bouqAE$px+v2}{c>Djd}2uBr>1B<}nGSMa5D>g^^K1J&MIrnLD@xbRR5;PO0( zQcElw66o}CdF9e7;rs4ofXg^PN=<5AK5%jAVx`s-!r|%xT-#4?EBp7S*B)!LOM7Fd z@WE^ZaQ*K6rfg_dN?WzFf?hwL@EhS3fNR;~vNCZ{v{v=U=k&Z)g~K%mILT+`doFOh z=1tSq)D^C9VOFoc?NPPI@eJCG`tNM6J4*P<#H`+5KFX|qJLB6x+{~WJaPfy&TNuoj z-^`?D9k(-(WmH$?Tvg%RbpW^uZSE^A;#+CCmY3IepAwXaY9G;VS-p~u=cU;!rQ5XV!@{k#V_o2;v~R9` zzgYOnbW4%`b#UXrs(ZrW+)|{!+8U>2j~5PyDbj4I%-Q&+K4gIK`)-EI+!fk%%Qxhl zaPHhPvX4&vQcEf=9B!@)calz(F9Gh!#Wxk-o_`V#LaoHO=}GO)m$ z!1B&DwQHhE`rC5mI)Izd|D+PPdvsuFk;8#6Itk*=p1WKyXN=sntW@CLzlHC+MBt9W zh2I5P+HLOg^WSe#X}+8uQ&ar)is|hZp7Dbq?(C)FmflXouuq5z!?p*r7|)JHHOjU> za70x8oz2}hE=xu0J6+rIvhbC;2jH4F&!!%kmf(A1OdkF5O~MTw`vA@wO*u>D2NyWn z)%L?kasL+uj4NuImkBMXPM z0&0F!OTGB@pg`5}bCvq93Ev1efxDmX#;Qe%-ANq$+HcB*CBntph?FLasG%i_A{>`P7s9nP09&v&DyYJK5g1y4wGPuBX|FxE{#C_p# zkGjA$KVD1g{iW08r9Nt5!X;@WCtxa8o{*qGVp!)0eAhRsF-v!sEoS zR=|?YBb5PZX8YRaUZM>dCVcL&RzR7CLzHoAU-J!lwt!w>h#UV*oD#<|cDhZY*VB8g3yh_uv2;T^9r3oYrW*wKo zTue*>M@5+e?3G#H1#aOd+q4Pd{RoX+;QneqN81!5eC}Rxfs-_M%>XXr^jzwo$;AV& zX`d-?trmW&yasUJUt6p6n(bXSC*nY6#T^SRfoy;5>wnLxG)W3+M)1i{%x zs?tuZWIqc!#B4ZUGKlbBG$*wJhKQ;aV8dA@D*!fgraitz;^C?T3?nnG=&M}&M9{vo zxx?1L3~o%8Y)ZZ#g~MTMU#gic)0rP`_1>?Zf8@MWE>jkwEUtn>_Y4Tr6Pd353X4qF2=IGW7(gs5ajo4eQ9_nYs}R7$5# ztg8n0{=QC`e?ZU?ZNp(DgngftQ9E6FKTvwl*UCqYgfEqdbRxF7!%7HjY-1kZs0r(4 zYs0<6z8~IydVj6#?YSFm0q{Sh-*7?+j1VpweafR)lq7fI zSPLMfAB4}{gp^Ro-x2N<3C_^T0QY`tpCz2FoG1Kg8zPtk~DYoEdc(9pSF!vK5H-h5OZtmoMXXy<-|SVbGL+N%A(TzvsU>` zyu!820to-`*{3B{tzwTr*;iI89mWXX2rB`OCxx%fHT?Hml%z9ry#)~d;q6b;sS}3% znppOwcFNkmf{erV1%zFs89J$A5fE0z!iLk?_rrUY6Ce2A`Ahh|+X^tBZY-(3xUFvB z&wf*tU-t=LnL7cl9xVc$0kl-EC3PKoM7Y!4=u1YzhzidKTRg`X-|66CoGE!4l( zlnP9*Tt|5_hj4XrA7jUSCwX_)^(rj?&K^v+k|6((+NX;|)jqZ1jskZ)Df|#S!GFI+ zkx<@%uuxu`JL~|Sn9ipjUNSZ2;G2hhKaLf?@7yYogxM56m{@^iRm}y;wQ~ga6*R46F{B}$DZGI29<4NI5C5iw3s45PXq_}vM z1ly_e=)$>s#3ho7RQ^$fRsOM;N=6sBFqgu)bL-x|kJJjtA>Oc$1y3f;OsDp4x+QVO zkt)jENy0Y*Hj6LupriWc+c^WvKAWdB*(=CzZqJ=t1(F%1Iw%)s2^VXhi0o3qf+vqo zzO4BA|CBf=sgH8=N8xi<5V%{o_&qg$!=8a_j~-Ogwh~nI-k!U{09S1FMJ4~hQ=4PU z9aM&=70#Vo!4taga*E$~#euu8vu{xDws^R}vVZoE{eCz(Nw=0c~s>s5v zFc46-5cVA$mH-~qfJk0d*a;#TB8wscLuLp#B1m#T#(0M01&0WRW*-JP86*$_Dw3cf zCfxzTVu*&rng9|87zkTnRF=WR1g7e}zTI8-)%#^N?+2WG{hj;Oy|wo1s$1m1|sQiq-+7gX&&^?8RAo`77)g4ym;r*iM6*#y(C?tXhdF`sucY~ zhW_n3Ngt>DHO_1sxmTLDA&-wLue$^rxe*?-cO78}3q*`!r?v8pS%eRa3krl|yI%uKhDTOT^r9e_6vb~nV8?);uK zEL1+KEVuD)>6(V_A*Yo$l~qV?^ls<2?kWZZq_qe>ocByzaRdgskq`qa|M0E$=1!zXNZ6o)=&|;$Oh_tWY z;mkkaUC1w^>A3^S2Qi%a2jr>}BWc}dm9JI)i-K8xX%q>5ab@`UirwzeEy`P_T`HdY z?1Wl#^(WLGA@3lVtsZ^lI`fnA8Nn{|Psqa{dPn^aYPHcJ;`P}<^wEz?U61D1qJz?u zHWG^aZq+cnAcdTw{Rx?1^+fK&0Dc-2YM{@mET zb8j2^)`A2zm%R8!l_!#l$0yee1rs{L(G7D+u=*_)Ep6mXS>+qI+Ste?u<3P``sua3 zja;L$E;RUS6byYg?Z-H_bvRdKXs^>x>v)W>AY zUzKld3Pp0z5dzdQd)vtIox|(Z?;P%9BNrg=Ub2x3&?ba_NY43b0$m@Q=~{g?i?lwh zyr~R8ash5Cc8P{~Q(33Jsn{hN+VO{9v`AI?#C#JFPBirW3%%(}>-6xceT!UCMERKc zL=p}8yc=QDRDLdN?P{q0HI7}Pp#XLBDCAvEY$BOCptfuAihA@!KjkyRcqA9#eup#v zfLwqM@8irr=R0MR&D~BEmT%ZhvL`D4!i6s!|E_*}`d)*X;d;5twf&s(es>C@hyGtZ zaTPf+R{2_`63NuKdXmBkm&2!imO;K$f2#KylDmJo3+Zt<`jvKR7f73d%ImHX`u6I6 zdkF1V9k1n8zf85d%ICZ0NDiF+=z4cIDf#Vn$K8pWnmEmSLqd)Bu*|Y4Yf9Ig^?m@# z>6`THUeL$Z59>MlHSY(&UYXaQdmEyAJN_V=bjIN?L4Ay^5X-X zIxKZ?>dMq8#0FT8Ha@`YPlgHbuI$QuJ=z2M3aFRqnG#98M9o@g%UPE3uD`k=w^p%7)woBfy`oUs5>Ef}1nom~)PL4ou4>|iq zIowZfWS|@#0!GAmL#`%WgeQR!5sm{RVqM0{;pt$+zY=O{;(;x~GZ@_AlJOwPj|?Nv;*u<2 zaEx;>MeGy?$H#ZY>_rTIJwF4pAwv$TOU~vGvJE*|5Zg4unx@#bj*By0{#*k>5bALP6j7JGvU zTRI73DnLdmP16q4rA*jj(1gzWj>EyKL9Cs<2JCRadeF1H2=drQ@G}OS9D!idc?;Y`ZUh$b z$cTAf)nddvd1-;+ge0o8c1%)IX>eK;IS(fT5o}&rZV6SG$9cql+2bV|*_O%SRURXV zZSKdijG6@=BS;c{??v!kk8RYsL&1nRaG0ksEq(q4xe+ratbL2Kl*zWh-Uy29{$N{# z2S5SE_HD8)U5c}JjOc{>e7GDYU|a0-oXsE9d^kHPs0p*-;n6uYql`+);9P41TN;GPw!ob2EWU@=RdAdJ)%*vH-6O_{ zS2LV#7!gCo*~XU-5l#bGY-}7hY>O})FhK3w242gI7&R|S@|#2@E2S-RcqgG5GY{~lMp#igUi_4a`JTKr8JlTL*OhoonV2kq(Y`sBqngfi8Z1WN; zW?O`R2e!p{!KR= zRBp~T1|^Z*P7cGpLumBjZ2lnFWDmrXF8s)kyo6hSkP-9lA!bAjRX0P@;=K72y9Mqg zFChFNk0d!;vMS(L+ZeDID!B0m1vZSaW1LT8=Q+%J1MX@4fi2pGpMg;UIomKI4(leH zg-SFs!eCoQh>;97zU+xcOg1wj!kj&aEXL)YEjPkpgDo1#U@(7B0ll!;xfcUlgwqX} iRj~*!mBY(DM$oc6TMmEjF@o6Ta`>Fbi0PF1@BaZm8ZO!Z literal 0 HcmV?d00001 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker/miku.pmd b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBaker/miku.pmd new file mode 100644 index 0000000000000000000000000000000000000000..21ef5e48dfedc3631c5e07d66642df6bdf7cdede GIT binary patch literal 474665 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%0AOAK{27-Q0L%;U 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 WT>CaORBQisUI+f^M84(E2>%zlVh*1G literal 0 HcmV?d00001 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Form1.Designer.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Form1.Designer.cs new file mode 100644 index 000000000..451251e8d --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Form1.Designer.cs @@ -0,0 +1,166 @@ +namespace MMDIKBakerGUI +{ + partial class Form1 + { + /// + /// å¿…è¦ãªãƒ‡ã‚¶ã‚¤ãƒŠãƒ¼å¤‰æ•°ã§ã™ã€‚ + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 使用中ã®ãƒªã‚½ãƒ¼ã‚¹ã‚’ã™ã¹ã¦ã‚¯ãƒªãƒ¼ãƒ³ã‚¢ãƒƒãƒ—ã—ã¾ã™ã€‚ + /// + /// マãƒãƒ¼ã‚¸ リソースãŒç ´æ£„ã•ã‚Œã‚‹å ´åˆ trueã€ç ´æ£„ã•れãªã„å ´åˆã¯ false ã§ã™ã€‚ + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows フォーム デザイナーã§ç”Ÿæˆã•れãŸã‚³ãƒ¼ãƒ‰ + + /// + /// デザイナー サãƒãƒ¼ãƒˆã«å¿…è¦ãªãƒ¡ã‚½ãƒƒãƒ‰ã§ã™ã€‚ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã®å†…容を + /// コード エディターã§å¤‰æ›´ã—ãªã„ã§ãã ã•ã„。 + /// + private void InitializeComponent() + { + this.pmdFileName = new System.Windows.Forms.TextBox(); + this.vmdFileName = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.pmdRef = new System.Windows.Forms.Button(); + this.vmdRef = new System.Windows.Forms.Button(); + this.startBake = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + this.label3 = new System.Windows.Forms.Label(); + this.saveVmdName = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // pmdFileName + // + this.pmdFileName.Location = new System.Drawing.Point(14, 24); + this.pmdFileName.Name = "pmdFileName"; + this.pmdFileName.Size = new System.Drawing.Size(270, 19); + this.pmdFileName.TabIndex = 0; + // + // vmdFileName + // + this.vmdFileName.Location = new System.Drawing.Point(14, 61); + this.vmdFileName.Name = "vmdFileName"; + this.vmdFileName.Size = new System.Drawing.Size(270, 19); + this.vmdFileName.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(29, 12); + this.label1.TabIndex = 2; + this.label1.Text = "PMD"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(12, 46); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(30, 12); + this.label2.TabIndex = 3; + this.label2.Text = "VMD"; + // + // pmdRef + // + this.pmdRef.Location = new System.Drawing.Point(290, 22); + this.pmdRef.Name = "pmdRef"; + this.pmdRef.Size = new System.Drawing.Size(42, 23); + this.pmdRef.TabIndex = 4; + this.pmdRef.Text = "å‚ç…§"; + this.pmdRef.UseVisualStyleBackColor = true; + this.pmdRef.Click += new System.EventHandler(this.pmdRef_Click); + // + // vmdRef + // + this.vmdRef.Location = new System.Drawing.Point(290, 59); + this.vmdRef.Name = "vmdRef"; + this.vmdRef.Size = new System.Drawing.Size(42, 23); + this.vmdRef.TabIndex = 5; + this.vmdRef.Text = "å‚ç…§"; + this.vmdRef.UseVisualStyleBackColor = true; + this.vmdRef.Click += new System.EventHandler(this.vmdRef_Click); + // + // startBake + // + this.startBake.Location = new System.Drawing.Point(257, 142); + this.startBake.Name = "startBake"; + this.startBake.Size = new System.Drawing.Size(75, 23); + this.startBake.TabIndex = 6; + this.startBake.Text = "Bake !!"; + this.startBake.UseVisualStyleBackColor = true; + this.startBake.Click += new System.EventHandler(this.startBake_Click); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(290, 96); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(42, 23); + this.button1.TabIndex = 9; + this.button1.Text = "å‚ç…§"; + this.button1.UseVisualStyleBackColor = true; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(12, 83); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(59, 12); + this.label3.TabIndex = 8; + this.label3.Text = "Save VMD"; + // + // saveVmdName + // + this.saveVmdName.Location = new System.Drawing.Point(14, 98); + this.saveVmdName.Name = "saveVmdName"; + this.saveVmdName.Size = new System.Drawing.Size(270, 19); + this.saveVmdName.TabIndex = 7; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(344, 177); + this.Controls.Add(this.button1); + this.Controls.Add(this.label3); + this.Controls.Add(this.saveVmdName); + this.Controls.Add(this.startBake); + this.Controls.Add(this.vmdRef); + this.Controls.Add(this.pmdRef); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.vmdFileName); + this.Controls.Add(this.pmdFileName); + this.Name = "Form1"; + this.Text = "MMDIKBakerGUI"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox pmdFileName; + private System.Windows.Forms.TextBox vmdFileName; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button pmdRef; + private System.Windows.Forms.Button vmdRef; + private System.Windows.Forms.Button startBake; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox saveVmdName; + } +} + diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Form1.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Form1.cs new file mode 100644 index 000000000..37dae1444 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Form1.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System.IO; +using MikuMikuDance.Model; +using MikuMikuDance.Model.Ver1; +using MikuMikuDance.Motion; +using MikuMikuDance.Motion.Motion2; +using MMDIKBakerLibrary; + +namespace MMDIKBakerGUI +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + + private void startBake_Click(object sender, EventArgs e) + { + // 入力ãƒã‚§ãƒƒã‚¯ + if (!File.Exists(pmdFileName.Text)) + { + MessageBox.Show( + "PMDファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ï¼:\n" + pmdFileName.Text, + "PMD読ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + return; + } + + if (!File.Exists(vmdFileName.Text)) + { + MessageBox.Show( + "VMDファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ï¼:\n" + vmdFileName.Text, + "VMD読ã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + return; + } + + // saveVMDã®ä¸Šæ›¸ãç¢ºèª + if (File.Exists(saveVmdName.Text)) + { + var result = MessageBox.Show( + "VMDファイルãŒå­˜åœ¨ã—ã¾ã™ã€‚\n" + saveVmdName.Text + "\n上書ãã—ã¦ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ", + "上書ã確èª", + MessageBoxButtons.YesNoCancel, + MessageBoxIcon.Question); + + if(result != System.Windows.Forms.DialogResult.Yes) + return; + + // bakeã§ã‚¨ãƒ©ãƒ¼å‡ºã‚‹ã£ã½ã„ã®ã§å‰Šé™¤ã—ã¦ãŠã + File.Delete(saveVmdName.Text); + } + + // Bake! + try + { + MMDModel1 model = (MMDModel1)ModelManager.Read(pmdFileName.Text, MikuMikuDance.Model.CoordinateType.RightHandedCoordinate); + MMDMotion2 motion = (MMDMotion2)MotionManager.Read(vmdFileName.Text, MikuMikuDance.Motion.CoordinateType.RightHandedCoordinate); + motion = IKBaker.bake(motion, model); + MotionManager.Write(saveVmdName.Text, motion); + + MessageBox.Show( + "Bake完了", + "Baked!!"); + } + catch + { + MessageBox.Show( + "Bake中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ", + "未知ã®ã‚¨ãƒ©ãƒ¼", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + return; + } + } + + private void pmdRef_Click(object sender, EventArgs e) + { + var dialog = new OpenFileDialog(); + dialog.Filter = "PMDファイル|*.pmd"; + if (dialog.ShowDialog() == DialogResult.OK) + { + pmdFileName.Text = dialog.FileName; + } + } + + private void vmdRef_Click(object sender, EventArgs e) + { + var dialog = new OpenFileDialog(); + dialog.Filter = "VMDファイル|*.vmd"; + if (dialog.ShowDialog() == DialogResult.OK) + { + vmdFileName.Text = dialog.FileName; + + var f = new FileInfo(vmdFileName.Text); + saveVmdName.Text = Path.Combine(f.DirectoryName, f.Name.Replace(f.Extension, "_baked") + f.Extension); + } + } + + private void saveRef_Click(object sender, EventArgs e) + { + var dialog = new SaveFileDialog(); + dialog.Filter = "VMDファイル|*.vmd"; + if (dialog.ShowDialog() == DialogResult.OK) + { + saveVmdName.Text = dialog.FileName; + } + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Form1.resx b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Form1.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Program.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Program.cs new file mode 100644 index 000000000..bd2f23d65 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace MMDIKBakerGUI +{ + static class Program + { + /// + /// アプリケーションã®ãƒ¡ã‚¤ãƒ³ エントリ ãƒã‚¤ãƒ³ãƒˆã§ã™ã€‚ + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/AssemblyInfo.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..6fb8ab57e --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// アセンブリã«é–¢ã™ã‚‹ä¸€èˆ¬æƒ…å ±ã¯ä»¥ä¸‹ã®å±žæ€§ã‚»ãƒƒãƒˆã‚’ã¨ãŠã—ã¦åˆ¶å¾¡ã•れã¾ã™ã€‚ +// アセンブリã«é–¢é€£ä»˜ã‘られã¦ã„る情報を変更ã™ã‚‹ã«ã¯ã€ +// ã“れらã®å±žæ€§å€¤ã‚’変更ã—ã¦ãã ã•ã„。 +[assembly: AssemblyTitle("MMDIKBakerGUI")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MMDIKBakerGUI")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible ã‚’ false ã«è¨­å®šã™ã‚‹ã¨ã€ãã®åž‹ã¯ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内㧠COM コンãƒãƒ¼ãƒãƒ³ãƒˆã‹ã‚‰ +// å‚ç…§ä¸å¯èƒ½ã«ãªã‚Šã¾ã™ã€‚COM ã‹ã‚‰ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内ã®åž‹ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹å ´åˆã¯ã€ +// ãã®åž‹ã® ComVisible 属性を true ã«è¨­å®šã—ã¦ãã ã•ã„。 +[assembly: ComVisible(false)] + +// 次㮠GUID ã¯ã€ã“ã®ãƒ—ロジェクト㌠COM ã«å…¬é–‹ã•れる場åˆã®ã€typelib ã® ID ã§ã™ +[assembly: Guid("0339f748-b7cb-4486-bae7-b330d0ac3512")] + +// アセンブリã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã¯ã€ä»¥ä¸‹ã® 4 ã¤ã®å€¤ã§æ§‹æˆã•れã¦ã„ã¾ã™: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// ã™ã¹ã¦ã®å€¤ã‚’指定ã™ã‚‹ã‹ã€ä¸‹ã®ã‚ˆã†ã« '*' を使ã£ã¦ãƒ“ルドãŠã‚ˆã³ãƒªãƒ“ジョン番å·ã‚’ +// 既定値ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Resources.Designer.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Resources.Designer.cs new file mode 100644 index 000000000..e9c28be0d --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// ã“ã®ã‚³ãƒ¼ãƒ‰ã¯ãƒ„ールã«ã‚ˆã£ã¦ç”Ÿæˆã•れã¾ã—ãŸã€‚ +// ランタイム ãƒãƒ¼ã‚¸ãƒ§ãƒ³:4.0.30319.269 +// +// ã“ã®ãƒ•ァイルã¸ã®å¤‰æ›´ã¯ã€ä»¥ä¸‹ã®çжæ³ä¸‹ã§ä¸æ­£ãªå‹•作ã®åŽŸå› ã«ãªã£ãŸã‚Šã€ +// コードãŒå†ç”Ÿæˆã•れるã¨ãã«æå¤±ã—ãŸã‚Šã—ã¾ã™ +// +//------------------------------------------------------------------------------ + +namespace MMDIKBakerGUI.Properties +{ + + + /// + /// ローカライズã•ã‚ŒãŸæ–‡å­—列ãªã©ã‚’検索ã™ã‚‹ãŸã‚ã®ã€å޳坆ã«åž‹æŒ‡å®šã•れãŸãƒªã‚½ãƒ¼ã‚¹ クラスã§ã™ã€‚ + /// + // ã“ã®ã‚¯ãƒ©ã‚¹ã¯ StronglyTypedResourceBuilder クラス㌠ResGen + // ã¾ãŸã¯ Visual Studio ã®ã‚ˆã†ãªãƒ„ールを使用ã—ã¦è‡ªå‹•生æˆã•れã¾ã—ãŸã€‚ + // メンãƒãƒ¼ã‚’追加ã¾ãŸã¯å‰Šé™¤ã™ã‚‹ã«ã¯ã€.ResX ファイルを編集ã—ã¦ã€/str オプションã¨å…±ã« + // ResGen を実行ã—ç›´ã™ã‹ã€ã¾ãŸã¯ VS プロジェクトをビルドã—ç›´ã—ã¾ã™ã€‚ + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// ã“ã®ã‚¯ãƒ©ã‚¹ã«ä½¿ç”¨ã•れるã€ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã•れ㟠ResourceManager ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’è¿”ã—ã¾ã™ã€‚ + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MMDIKBakerGUI.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 厳密ã«åž‹æŒ‡å®šã•れãŸã“ã®ãƒªã‚½ãƒ¼ã‚¹ クラスを使用ã—ã¦ã€ã™ã¹ã¦ã®æ¤œç´¢ãƒªã‚½ãƒ¼ã‚¹ã«å¯¾ã—〠+ /// ç¾åœ¨ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã® CurrentUICulture プロパティをオーãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã—ã¾ã™ã€‚ + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Resources.resx b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Resources.resx new file mode 100644 index 000000000..af7dbebba --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Settings.Designer.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Settings.Designer.cs new file mode 100644 index 000000000..4d1f1c874 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.269 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MMDIKBakerGUI.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Settings.settings b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Settings.settings new file mode 100644 index 000000000..39645652a --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/bin/Debug/MMDBoneBakerLibrary.dll b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/bin/Debug/MMDBoneBakerLibrary.dll new file mode 100644 index 000000000..3ee67f5cb --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/bin/Debug/MMDBoneBakerLibrary.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9baae5d3530cedf887aba16481d6a6dae8a9efc7551c325842f3cad364262271 +size 42496 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/bin/Debug/MMDIKBakerGUI.exe b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/bin/Debug/MMDIKBakerGUI.exe new file mode 100644 index 0000000000000000000000000000000000000000..2a1967ad41f1f3bda2ddc43d8e21147d1e3613af GIT binary patch literal 11776 zcmeHNdvILUdH>GUYIn7IU`e)RAdTy;=R4o|&N<(CtVXWBk1B{LfcMi+iJrlipB_nnJDG*JuKBq- zdaCM;HP49QH`a`uG;B3*nG=?lRa06nXF6(9SFJ)$HFD~}frOeh(|WA7HnP@JJvvA< zEGlSh^7T=_ws%Pp)gny9negG~SU-r0_XJ+HPQ^!Y?M6!4&tG~7FK~Vo>baF@k^DdR z^;kCx)j;n7PM^U4N)Igk%o5drALt`mS&ILzv|2P><_v?sqNGgB(Wf2o=~fWPWLrJE z!O2I3NioZ|QsAU*Cy)r@U5~fq>48IHmYy+@k!__}ysT>@-jb(>2(2i8diq_SZBqyi z*nqY+5mkV{2({hUMwA!jWqupi7*|*Yp-4SdY^+vJAr)BsiP#{TBEgP2asjiRD1sU* zq79sAr;2!h?(qGu*o{Cxk0u1XB+Nl_F{2o%eiHeST*4^a;wM9MNemtzt&&Np0Tlz4 zRaA2_x|D5DPH}zBbh*zSP7RVO4A|RCSlB zV$gz?qACU!QpI?auZr8-WUg}cGSghsTveu*L94SwugtZoxu(oM2A7p8wRUrn)vjW8 zWw91!P)n?=76z@oCAG+0tLN3i;BvnfS>#YjE!<0L3;S+qnQq3dYfE%9(A?hKRMr9p zFZOlIB9rrUH<`_Db6Bc;5`+OkTLomUad93St^t>o8Nj%8eTe}KoM!-oD|`cFkx~N~ zC>p>F41gWw2Jnbf1w5eMi&;`;1B)xCM)M@bWJ{JQX3+XUiDCv8nrw`(@^rTleYXdsr`HCJL|f&kX^O6uU-fg` zZ%=Z+@x+g=lW253KFTR>w|Pk^!giJ;Tva*3T~v zn}=9Ghhw5{K(l^5=gOtgsM~@z{E;MpmO^I^OVJrRYKBhtba)h z7S`QS#My`gMFLA((L7JKnPpv&)r3P)d?Pg__J!T@TL6>wHjJ>|XPYhszn)#(QdSj91cW=)l04)3JL&9W~*OYrS47)lt%XdnYu*AMEasc^R0Hxl7V+ zQ0p32dwG$Ma$iQV_!NzS9e$fIv|&#VglN;k_IPdL%1Z5__I4#YfP&E04t*5_6L_@N z(@oeF@g4*YL1S9TGGNi0aGw$#WHa`F*n4H2vz*l}P`!ad@RK0aM3|P)Qww2a0|nb# zNSS4(D91#Gyv~;&wjm8hhoIAeiT zE%?RYQu?-}FGzYW_-628S{@37E~ZN)eIdx{{h`j#YPva;4F&0oA=dV=q)&rJ=qDkr z>(`R53opkuZgV&de_j>t4M!*+UW*pp6Xte(JnOFIF*KS@i&< zTdUaSp{lg(FL$i*m=idguA~<9yE_6GQJi*C6~-Z=34(qCTrITJ&@8y4$XSK4aS?LA z53Pb4L=)(0N#kM#(%U2*6wOEvOPY}MT1j;&%^-h0y(ij1>y#MiL1mamRW|N5`X%ZU zbi3qE(|=JTM%k+MEc?Q;X~Eof$(^R#MJu?cE@9be`crTL`pDzH3NA>uV>7|BZ-EQb z_a%3W)Doc|N$yN|wXzv)QL*13IuqWkYy-E=<1SZrf$Ndnm%~YA6p=V9IoFnIIwHCI zmo2Hf8nS}R(Uig*&l5h<3Az64N^E9uLiDS8XkpdW)a(tGf8BYKm)-6oMvNq0zkj=mpgqz{okMd#>)z-iFm z1dh?i9umPkIY*6^2B=zD2ij42jD+Y#x=Kuodw^V5d4}qd{t7J@cU3+F`efx_pvG5a z*`HSaHMNNkE1yEn|CAb(Alt*Xoufs;=crRegD=qzu{HQA^@^$B>oWaA;HQG`kS6{< z_&%Km{UtptZVP>k^xdIK!8z;1G=S@u29z2clqe<*3awC!W@o$wj)u{az4Gcg3@5mB#9i>JjJ zrLAhcvRvkA1JX#H${~!2PUU3PCZ$ukvucadM*Yf5B1S7{1f#xH(hal|>09XHiWo)= zryC`nph=`pQ9ba>B(hJ^E=mAT(F359^a!X;;ff)tIYo`iz3Ar^l2$7t;ufk_{uY#x zcf~cJIa(^(#8%NGz9GH^t1B=%1H^ItEzt*hrLq?^ryRm~tpcuK{Bv}u22~ITLKK*F z<3F-_PYb@hD)^7UD!@-UhUM!#?6&hTi_Xeom?|aD9|xH!$9^R-H=T4r9i97DGW z8xlt@#lZN|k-Qzu5hIs2Z?I#m)|Sf2-zRxl=s@y1J>~cX`pw+9F;TEI2RkV0&F8UC zl4-w&KF!wWGH3HNhMhN2W+-PkhL$mI)cbuQjp6dI z&zz=wHoeEl==-&-PE#f6VJ!*08K#}?XEXH`90#VM$U%LabMwb`G|OQ}Qc{Y&++AdA zQ~Kd-T567^9Mht~DHz;qVcSwHbi5y}ob*(BjH}pVSPQE0xcR%oVh4?AIc);1x4ca% zc;8ifvGw7`yMFaHq(ixJvzXb#XhL_6`#tU}WXzY_C21c^>*E^sxI;NKDVNfvjsX`V z|2u-7p|tD_j1;o<9Jb8_e`}dSu}9I!3`T?Od)wBt$;`}{;bin)2U|V3R;OMM9?Q`NFbMw2(NP*K#xG3ov@qg_Lu?px?~TSjNQ31w>;O_WxPUnp~iiyYHV9_&w+D z=3_%SN5>pW=+=~hBL!h#9yV+vS=!#c1tUGDz;C^G#5iBT!}vVmylOo;_rjQFp>OwK z#_BhirA_dP3>ex(&a@pPg^8pm3lkGsnRPA(O*{h;2E0R(*FK(Tu*WKGAOJZA59%3h zTBhu|RvdH-ayf{SM#gYTdTGd=%4`8#m2)gJLy3Z&$4DC1X3Rn{hzwZT4cxj>)5tj( zY0mLs(~TmMk&`ijKp?qdVoXa8VN6a-w71}xa}xfIz@7Ip{IJGDwvN6kXqkjFlhOOM z)MUSz@u&9{S}u)tla@~Va~9R@kygt9<(to%WK}6GqYvPOm*bP8O+}3TI%g2)Dk2CP zh$PZTPaQ1qXOEn*u8*KCo#q%($m*V-Ms;f(5!vH7FGoVZ`-Tn>42M5%sG@oz)YMpZ@?JJ=$OPShoqeo1NNK!ul`2}EwX{C*v=ICQHc^$3N(hHT2VT{XVOlt8`94jtVqYODCCV$H6 zbn$uSF$gR9v)OG+G1-UpNG_Edc|XSHfSHZ?)13C|SbNbmX_m~*YBxye)_yaGS!0z8{ldkvbLHF~ zc0&TE-C2cN9Om{|X4XUes3_N+A~Tpa(DptH`;YRVHBXRmU^2y0a&=C48yRn#kxQMl z%pB%!ni6BZV<#<)w>bk#wkI^0<4Q_Gg4`5w>o}5Sbe>=b<(h}cjyH-&O4d9^m#9&%W=pxC17Jy6%h}OAndOQAb z{IU4Y2AJbrup9()Jl6OitUH-9RsUDvtmWL&92PtVNrV=9~j}aSq0cc95i5@#s zfBT`wvU?xBWOV$?+MoY`!cX6L^zia6@7_@nY^dj-=#&bT1ehgwm*ZU(R28wZVGWY& z@V4Qg)Ub|88%}5fe3*HVHb@t-U=eeRaJmz$udWiLUgu=EA|#aXH+LVux&H0Q&PwPF zhoy8z($6!pa#;{L8)k21rly9O`q?|&&;6AuHOxN1nHvf)vo1hFslySmuCA_@0`;?B zt*fh_eY}45i6B(~W4Wk{P({P+-$3wejZA(I$=7SDNokmUL;im;OckQ8VfK49AyTB0 znh+~%n0*m)1(kvchLHblFkD$x2rA!hn0-%?@Glq^b#*<0y8JDfA3|bdrkSy0Sk%qj z1a{Ymq&UI2@uja|WUwg@c^B6>yYitiOlbc9)SnjI+S8RGR?T13xvpWI5(vTR(jTX5 z!@@hBUL|PXh>@~P+Z=adepD=^4KwCOUs&KpT5RNv39K7MAb|jxk;{#@CYV;ZQ{JS< z@M{oPw}?$TU623lP(}88WrLvFvhyq=6q`>?xS=cV-_=(hSJln&PDHgfL2Kh(T|36N zZQ0(D+?GmqY}vAXYe!Pkw{;}Dy5i}$mg>5cbJhq7b-I`NM7p51*#5z>;--0{x1a9j zJL`=&LX2Y#?sj))g2w6=7jyFdHKWPZxS3U`MTxpabqlCod3Z7;tw#d4ka$+}<>Z*M z^oXV9v62o>r*wJx!J>o}PUb}}|L=GBmf&%`C;ITNB|4ZGNc>Cpf27qPzI@=!Pvg$L zFFZKG_w4(29v#3D1lu|JP2!ukj47;$_{yWaee@7c&NHLf;bPxsAI)ad9oRf}6c{~P zwsTW~t1|b|xt=IV;*#O0nY`}k^!BYs<))xq7R#rTFp0MGGj*T+oK`(%-pBu&85cg@ zZ(4)Xx;$peI|f~kr8Dw(1Nw9wsXg;b|30${|Fsl1dlrBF!oM-j;#2at_tc{oz)voK zbK%(%4Q|pMHTQve=mgQ5JZQWppCbBqe^3E?Q`rJ~7h*EOaD*Tae^vVgXGxGEW@0`|iIjSkDkqP(RwHD~dZd)OF!@Vctt0mY1FH$@zZVF3a@7*Eal+MUQ6i`y1~a%X?scxeuQI z&aU0l*^D~n{aD+A0NkF_`Pmf|1z&eJA{~5J*`C3&xb9xYxQw2UA59?EUM$ItoZqe+a+!TKMwp!GJ(VN2M z7u-0mWo+GRlvJ{50c(8IH8C%9`|?e6F36>|MP#(1OE#N CX%o@_ literal 0 HcmV?d00001 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/bin/Debug/MMDIKBakerGUI.vshost.exe b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerGUI/bin/Debug/MMDIKBakerGUI.vshost.exe new file mode 100644 index 0000000000000000000000000000000000000000..bb84a51ac4f20534146c09f2fd9c928d15a903b2 GIT binary patch literal 11600 zcmeG?2~<)?tG75|5OPOMcC{DsnWb(K|p-9Gz zCYX{WA(Jm;dIfQqiJ};SrLL}G(n&hl8zFy;j>apOj_;bS1<^27Oc^0Hz(7W(Czb%1 z@VUW90w!d%4!)s8@lWO`4L-o%@Fz33`3PxI|9bMyD%lrO3DBh`b_0^65V}%-gn|b^ zWm*RtcF<41tL^XP%x>1H-pWw-?KO@iBWB8={z?S^v{7pXzI!Jo%+8WXB|Jbhzz%$;+6FHiiU_~N3I z3EN^9UtHuj{7z%|8vGH<%)(m1Ea7^jMXH#Y>ya2$DiaMPF|c+I&NvSYVbqF9*~#r#ILj8dWjm251tb7C6J%*T7omHQ z|3QZ`M<(G55b{zd>0OBcT-q z$5D_+!Bh&aq+kUFn<&Vjy~Gre83lc5nD5M>aGT=)?fZgOM>nV`Kqv zI0bDf=!~2J||60WgZ0+&DGHhBHk2136`;HfS!lVrq~L;Qp?LLw4#2#K5zlOj)1BCy1d77#r{JpDO<77O@Xp{xhn!4xZ$h!p@= zFfDSIN{Pg1K}r~3)_Zst+KZ6#Bz!U1wTDViV=OmGAajRFq+hp^({qI>UpIiLVv=~h zxay+kDH5kh_;K;yXzG;G*Tj7I0^&~_{e-b1Ng|izo-6pOSGO>vq9h3^M-Ep;2n2i? z;VA;Ob9u6_h6EBx&>#pUI*0gkg>gyTxL$JaT8kGU;HGf+ao-Tzcp`=5x@Rq2jC5KA zDL81CbnCa%R49SU_|be|v6omoM|<(PaYE7-c~ay>L?^|?aX&MN4jh;n*m;M|z$BDt zLV?wpRH>I1yLLe*EkY6~5>Aj35>FW2!};IZ6RZg`l4U+2WpPr3Jg{aVFJ1yBKdala z!{Q|bH-_8;-f}`H`;N<(`ErFZ0s_H?nELq^^AiFst^h{IAPxchk}HJW2r40D)L?1| zN5+-NKyKu|BH5O9=>_$oO%{WM1RNkt$|LX>+U#yGW4SL{W#Dq<^-?pWTs_=s z+sMi))7<${{lWc@(;pS&e4xt(nf|K_4fiC?yA3+_%vvY*l!4@4iv}=BM|c$3*(8Ejv=a+B_=Ss*JEQXuIqpixQ3a_4(W> zyEKm#xtQrM)b=Fwn2Ghv>;fV#EMt&fQn_Nx)Omd`sf+@qw7IY%8d=~wU}z94&^xT# z?O1hMy$gBFV<=2Rx4X%UFBOAX2ZDn_3e*V(5c0klQtL7p%59=S80yz;986D8eMaINL%0wc8G%|*e$MEHmK74Q% z!Aa2qJ`Z*(ODar2$dFuS7_I+z60R6Fg7-`wLHR_mTT!wUQ^u&61Y`_zfv7uESG-PI zL=b$z5K9F^02Rvd;_$Xby>8#V-GB3vXN;}hekVw2b}%EC!sUQGG$K1h+L_tfM2e!P zOCtHUjw8EKEOAUULMMT4SGq-(nO(Kd^R74+p{XEA@0kR39#JP2L9k*3WE=-K98<(} zqe}k)-;w}E#jg-2r+wZ^?F0lS_7$G&N8TMKx*>Foia|&WS+)ZhjyMosg(Ghi3MD_V zlt8Ha0ra7)2BA8})Ao*tk&JOg@{U+nBp*Xj>4k4odB9b z6pKVuFB2+W3WHWIV5QK`MKb6of?7waV3?3D4|tM6FFxSozD0@ZgTuNz{_IdRDFbAO z)M2bA&`X3r0!GVV7PvbAj0da~>bA%RB0vJogpW-A5a@S}5mS7nfE2jYc(OeJxZnXV z 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 + foreach (KeyValuePair> boneSet in beforeMotion.BoneFrames) + { + if (!boneManager.IsUnderIK(boneSet.Key)) + { + result.BoneFrames.Add(boneSet.Key, boneSet.Value); + } + else + { + result.BoneFrames.Add(boneSet.Key, new List()); + } + } + return result; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/BezireCurve.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/BezireCurve.cs new file mode 100644 index 000000000..81f94c021 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/BezireCurve.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MMDIKBakerLibrary.Misc +{ + struct BezierCurve + { + internal const float Epsilon = 1.0e-3f; + + /// + /// ベジェ曲線ã«ç”¨ã„る点1 + /// + public Vector2 v1; + /// + /// ベジェ曲線ã«ç”¨ã„る点2 + /// + public Vector2 v2; + + + /// + /// 進行度åˆã‹ã‚‰ç§»è¡Œåº¦åˆã‚’å–å¾— + /// + /// é€²è¡Œåº¦åˆ + /// ç§»è¡Œåº¦åˆ + public float Evaluate(float Progress) + { + //ニュートン法ã«ã‚ˆã‚‹è¿‘ä¼¼ + float t = MathHelper.Clamp(Progress, 0f, 1f); + float dt; + do + { + dt = -(fx(t) - Progress) / dfx(t); + + if (float.IsNaN(dt)) + break; + t += MathHelper.Clamp(dt, -1f, 1f);//大幅ã«ç§»å‹•ã—ã¦åˆ¥ã®è§£ã«åˆ°é”ã™ã‚‹ã®ã‚’防止ã™ã‚‹ç”¨ + } while (Math.Abs(dt) > Epsilon); + return MathHelper.Clamp(fy(t), 0f, 1f);//念ã®ãŸã‚ã€0-1ã®é–“ã«åŽã¾ã‚‹ã‚ˆã†ã«ã—㟠+ } + //fy(t)を計算ã™ã‚‹é–¢æ•° + private float fy(float t) + { + //fy(t)=(1-t)^3*0+3*(1-t)^2*t*v1.y+3*(1-t)*t^2*v2.y+t^3*1 + return 3 * (1 - t) * (1 - t) * t * v1.Y + 3 * (1 - t) * t * t * v2.Y + t * t * t; + } + //fx(t)を計算ã™ã‚‹é–¢æ•° + float fx(float t) + { + //fx(t)=(1-t)^3*0+3*(1-t)^2*t*v1.x+3*(1-t)*t^2*v2.x+t^3*1 + return 3 * (1 - t) * (1 - t) * t * v1.X + 3 * (1 - t) * t * t * v2.X + t * t * t; + } + //dfx/dtを計算ã™ã‚‹é–¢æ•° + float dfx(float t) + { + //dfx(t)/dt=-6(1-t)*t*v1.x+3(1-t)^2*v1.x-3t^2*v2.x+6(1-t)*t*v2.x+3t^2 + return -6 * (1 - t) * t * v1.X + 3 * (1 - t) * (1 - t) * v1.X + - 3 * t * t * v2.X + 6 * (1 - t) * t * v2.X + 3 * t * t; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/CCDSolver.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/CCDSolver.cs new file mode 100644 index 000000000..372e4d7e9 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/CCDSolver.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MMDIKBakerLibrary.Model; + +namespace MMDIKBakerLibrary.Misc +{ + /// + /// CCD-IKソルãƒãƒ¼ + /// + /// Cyclic-Coordinate-Descent(CCD)法ã«ã‚ˆã‚‹IK計算クラス + class CCDSolver : IIKSolver + { + const double errToleranceSq = 1.0e-8f; + + /// + /// IKã®ã‚½ãƒ«ãƒ– + /// + /// 対象IK + /// ボーンマãƒãƒ¼ã‚¸ãƒ£ + /// 呼ã³å‡ºã—å´ã§UpdateGlobalã‚’ã‚‚ã†ä¸€åº¦å‘¼ã¶å ´åˆã¯true + public bool Solve(MMDIK ik, MMDBoneManager BoneManager) + { +#if SlimDX + Vector4 localTargetPos = Vector4.Zero; + Vector4 localEffectorPos = Vector4.Zero; +#else + Vector3 localTargetPos = Vector3.Zero; + Vector3 localEffectorPos = Vector3.Zero; +#endif + //エフェクタã¨ãªã‚‹ãƒœãƒ¼ãƒ³ã‚’å–å¾— + MMDBone effector = ik.IKTargetBone; + //IK対象ã®ãƒœãƒ¼ãƒ³ã®Globalã‚’æ›´æ–°(別ã®IK影響下ã®ãƒœãƒ¼ãƒ³ã‹ã‚‰IKãƒã‚§ã‚¤ãƒ³ãŒå‡ºã¦ã„ã‚‹å ´åˆãŒã‚ã‚‹ã®ã§) + Matrix local; + for (int i = ik.IKChildBones.Count - 1; i >= 0; --i) + {//順番ã«è¦ªå­é–¢ä¿‚ã«ãªã£ã¦ã„る。(Processorã§ãƒã‚§ãƒƒã‚¯ã‹ã‘ã¦ã‚ã‚‹ + //GlobalTransformを仮更新 + int parentBone = ik.IKChildBones[i].SkeletonHierarchy; + ik.IKChildBones[i].LocalTransform.CreateMatrix(out local); + Matrix.Multiply(ref local, ref BoneManager[parentBone].GlobalTransform, out ik.IKChildBones[i].GlobalTransform); + } + effector.LocalTransform.CreateMatrix(out local); + Matrix.Multiply(ref local, ref BoneManager[effector.SkeletonHierarchy].GlobalTransform, out effector.GlobalTransform); + + //ターゲットä½ç½®ã®å–å¾— + Vector3 targetPos; + Matrix.GetTranslation(ref ik.IKBone.GlobalTransform, out targetPos); + + //最大ループ回数分ループ + for (int it = 0; it < ik.Iteration; ++it) + { + for (int nodeIndex = 0; nodeIndex < ik.IKChildBones.Count; ++nodeIndex) + {//å­ãƒŽãƒ¼ãƒ‰ã‚’å­ã‹ã‚‰é †ç•ªã«â€¦â€¦ + MMDBone node = ik.IKChildBones[nodeIndex]; + //エフェクタã®ä½ç½® + Vector3 effectorPos; + Matrix.GetTranslation(ref effector.GlobalTransform, out effectorPos); + // 注目ノードã®ä½ç½®ã®å–å¾— + Vector3 jointPos; + Matrix.GetTranslation(ref node.GlobalTransform, out jointPos); + + // ワールド座標系ã‹ã‚‰æ³¨ç›®ãƒŽãƒ¼ãƒ‰ã®å±€æ‰€åº§æ¨™ç³»ã¸ã®å¤‰æ› + Matrix invCoord; + Matrix.Invert(ref node.GlobalTransform, out invCoord); + // å„ベクトルã®åº§æ¨™å¤‰æ›ã‚’行ã„ã€æ¤œç´¢ä¸­ã®ãƒœãƒ¼ãƒ³i基準ã®åº§æ¨™ç³»ã«ã™ã‚‹ + // (1) 注目ノード→エフェクタä½ç½®ã¸ã®ãƒ™ã‚¯ãƒˆãƒ«(a)(注目ノード) + Vector3.Transform(ref effectorPos, ref invCoord, out localEffectorPos); + // (2) 基準関節i→目標ä½ç½®ã¸ã®ãƒ™ã‚¯ãƒˆãƒ«(b)(ボーンi基準座標系) + Vector3.Transform(ref targetPos, ref invCoord, out localTargetPos); +#if SlimDX + //念ã®ãŸã‚…… + // (1) 基準関節→エフェクタä½ç½®ã¸ã®æ–¹å‘ベクトル + Vector3 basis2Effector = Vector3.Normalize(new Vector3(localEffectorPos.X, localEffectorPos.Y, localEffectorPos.Z)); + // (2) 基準関節→目標ä½ç½®ã¸ã®æ–¹å‘ベクトル + Vector3 basis2Target = Vector3.Normalize(new Vector3(localTargetPos.X, localTargetPos.Y, localTargetPos.Z)); +#else + // (1) 基準関節→エフェクタä½ç½®ã¸ã®æ–¹å‘ベクトル + Vector3 basis2Effector = Vector3.Normalize(localEffectorPos); + // (2) 基準関節→目標ä½ç½®ã¸ã®æ–¹å‘ベクトル + Vector3 basis2Target = Vector3.Normalize(localTargetPos); +#endif + + // 回転角 + float rotationDotProduct = (float)Vector3.Dot(basis2Effector, basis2Target); + float rotationAngle = (float)Math.Acos(rotationDotProduct); + + //回転é‡åˆ¶é™ã‚’ã‹ã‘ã‚‹ + if (rotationAngle > MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1)) + rotationAngle = MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1); + if (rotationAngle < -MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1)) + rotationAngle = -MathHelper.Pi * ik.ControlWeight * (nodeIndex + 1); + + // 回転軸 + Vector3 rotationAxis = Vector3.Cross(basis2Effector, basis2Target); + BoneManager.IKLimitter.Adjust(node.Name, ref rotationAxis); + rotationAxis.Normalize(); + + if (!float.IsNaN(rotationAngle) && rotationAngle > 1.0e-3f && !rotationAxis.NaN) + { + // 関節回転é‡ã®è£œæ­£ + Quaternion subRot = Quaternion.CreateFromAxisAngle(rotationAxis, (decimal)rotationAngle); + Quaternion.Multiply(ref subRot, ref node.LocalTransform.Rotation, out node.LocalTransform.Rotation); + BoneManager.IKLimitter.Adjust(node); + //関係ノードã®ã‚°ãƒ­ãƒ¼ãƒãƒ«åº§æ¨™æ›´æ–° + for (int i = nodeIndex; i >= 0; --i) + {//順番ã«è¦ªå­é–¢ä¿‚ã«ãªã£ã¦ã„る。(Processorã§ãƒã‚§ãƒƒã‚¯ã‹ã‘ã¦ã‚ã‚‹ + //GlobalTransformを仮更新 + int parentBone = ik.IKChildBones[i].SkeletonHierarchy; + ik.IKChildBones[i].LocalTransform.CreateMatrix(out local); + Matrix.Multiply(ref local, ref BoneManager[parentBone].GlobalTransform, out ik.IKChildBones[i].GlobalTransform); + } + effector.LocalTransform.CreateMatrix(out local); + Matrix.Multiply(ref local, ref BoneManager[effector.SkeletonHierarchy].GlobalTransform, out effector.GlobalTransform); + } + } + } + return true;//UpdateGlobalã‚’ã‚‚ã†ä¸€åº¦å‘¼ã¶ + //IKãƒã‚§ã‚¤ãƒ³ã«ã¶ã‚‰ä¸‹ãŒã£ã¦ã‚‹IK影響外ã®ãƒœãƒ¼ãƒ³ã‚’æ›´æ–°ã™ã‚‹ãŸã‚。 + } + + + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/DefaultIKLimitter.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/DefaultIKLimitter.cs new file mode 100644 index 000000000..5c98530f1 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/DefaultIKLimitter.cs @@ -0,0 +1,273 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MMDIKBakerLibrary.Misc +{ + /// + /// 回転制é™ã‚¯ãƒ©ã‚¹ + /// + public class RotationLimit + { + /// + /// 最大回転 + /// + /// X回転ã€Y回転ã€Zå›žè»¢åˆ¶é™ + public float[] MaxRot { get; protected set; } + /// + /// 最å°å›žè»¢ + /// + /// X回転ã€Y回転ã€Zå›žè»¢åˆ¶é™ + public float[] MinRot { get; protected set; } + /// + /// 角度ã®å射調整機能使用フラグ + /// + /// IKã®CCDソルブã¯è¶³ã®IKãŒï¼œãŒï¼žã«ãªã‚‹æ„Ÿã˜ã®è§£ã‚’出ã—ã¦ãã‚‹ã®ã§ã€åå°„ã—ã¦ã‚„ã‚‹ã¨ä¸Šæ‰‹ãã„ãã£ã½ã„ + public bool[] Mirror { get; private set; } + /// + /// 角度ã®å射調整ã®å発係数 + /// + public float[] Restitution { get; private set; } + /// + /// 角速度ã®"粘性"係数。IKã®ã‚½ãƒ«ãƒ–ã®éŽç¨‹ã§è§£ãŒ"飛ã¶"ã®ã‚’防ããŸã‚ã«è¨­å®š + /// + public float[] Stickness { get; private set; } + + + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public RotationLimit() + { + MaxRot = new float[3]; + MinRot = new float[3]; + Mirror = new bool[3]; + Restitution = new float[3]; + for (int i = 0; i < 3; i++) + { + MaxRot[i] = MathHelper.Pi; + MinRot[i] = -MathHelper.Pi; + Mirror[i] = false; + Restitution[i] = 0.5f; + } + + + } + + + /// + /// 指定ã—ãŸè§’度をアジャストã™ã‚‹ + /// + /// 回転角 + /// 回転軸 + /// アジャスト済ã¿è§’度 + public float Adjust(float value, int index) + { + if (MinRot[index] > MaxRot[index]) + {//角度ãŒé€†ãªã‚‰å…¥ã‚Œæ›¿ãˆã¦ãŠã + float temp = MinRot[index]; + MinRot[index] = MaxRot[index]; + MaxRot[index] = temp; + } + if (MaxRot[index] < value) + { + if (Mirror[index]) + return MaxRot[index] * (1 + Restitution[index]) - value * Restitution[index]; + else + return MaxRot[index]; + } + else if (MinRot[index] > value) + { + if (Mirror[index]) + return MinRot[index] * (1 + Restitution[index]) - value * Restitution[index]; + else + return MinRot[index]; + } + else + return value; + + } + } + /// + /// IK計算時ã®å›žè»¢è»¸åˆ¶é™ã‚¯ãƒ©ã‚¹ + /// + class RotationAxisLimit + { + /// + /// 回転制é™ã‚’行ã†è»¸(X,Y,Z) + /// + public bool[] Limits { get; private set; } + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public RotationAxisLimit() + { + Limits = new bool[3] { false, false, false }; + } + /// + /// 回転軸制é™ã®é©ç”¨ + /// + /// + public void Adjust(ref Vector3 rotationAxis) + { + if (Limits[0]) + { + rotationAxis.X = 0; + } + if (Limits[1]) + { + rotationAxis.Y = 0; + } + if (Limits[2]) + { + rotationAxis.Z = 0; + } + } + } + /// + /// 標準IKLimitter + /// + class DefaltIKLimitter : IIKLimitter + { + /// + /// ç·åˆç¨¼åƒè»¸åˆ¶é™ä¸€è¦§ + /// + /// ボーンåマッãƒãƒ³ã‚°ç”¨ã®æ­£è¦è¡¨ç¾ã‚ªãƒ–ジェクトã¨è¨±å¯å›žè»¢è»¸(親ボーン基準) + Dictionary TotalRotationLimits { get; set; } + + /// + /// IK補正回転軸制é™ä¸€è¦§ + /// + /// IK計算をã™ã‚‹éš›ã®å›žè»¢è»¸ã®åˆ¶é™ + Dictionary RotationAxisLimits { get; set; } + + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public DefaltIKLimitter() + { + //ç·åˆç¨¼åƒåˆ¶é™ + TotalRotationLimits = new Dictionary(); + RotationLimit limit; + limit = new RotationLimit(); + limit.MaxRot[0] = MathHelper.Pi; + limit.MinRot[0] = MathHelper.ToRadians(3f);//3度ãらã„制é™ã‚’設ã‘ã¦ã‚„ã‚‹ã¨ä¸Šæ‰‹ãã„ã。 + limit.MinRot[1] = 0; + limit.MaxRot[1] = 0; + limit.MinRot[2] = 0; + limit.MaxRot[2] = 0; + limit.Mirror[0] = true; + limit.Restitution[0] = 0.99f; + TotalRotationLimits.Add("å·¦ã²ã–", limit); + limit = new RotationLimit(); + limit.MaxRot[0] = MathHelper.Pi; + limit.MinRot[0] = MathHelper.ToRadians(3f);//3度ãらã„制é™ã‚’設ã‘ã¦ã‚„ã‚‹ã¨ä¸Šæ‰‹ãã„ã。 + limit.MinRot[1] = 0; + limit.MaxRot[1] = 0; + limit.MinRot[2] = 0; + limit.MaxRot[2] = 0; + limit.Mirror[0] = true; + limit.Restitution[0] = 0.99f; + TotalRotationLimits.Add("å³ã²ã–", limit); + + RotationAxisLimits = new Dictionary(); + RotationAxisLimit axisLimit; + axisLimit = new RotationAxisLimit(); + axisLimit.Limits[0] = false; + axisLimit.Limits[1] = true; + axisLimit.Limits[2] = false; + RotationAxisLimits.Add("左足", axisLimit); + axisLimit = new RotationAxisLimit(); + axisLimit.Limits[0] = false; + axisLimit.Limits[1] = true; + axisLimit.Limits[2] = false; + RotationAxisLimits.Add("å³è¶³", axisLimit); + + //IKã®ã‚½ãƒ«ãƒ–åŠã³ãれã®èª¿æ•´è¨ˆç®—ã«é–¢ã™ã‚‹ãƒ¡ãƒ¢ + //上記数値調整計算åŠã³å„種数値設定ã¯MMDã®å…ƒã‚³ãƒ¼ãƒ‰æŽ¨å®š(リãƒãƒ¼ã‚¹ã‚¨ãƒ³ã‚¸ãƒ‹ã‚¢ãƒªãƒ³ã‚°ã€é€†ã‚³ãƒ³ãƒ‘イラã¨ã‹ã¯ã—ã¦ãªã„ã‹ã‚‰Rエンジニアã£ã¦è¨€ã†ã®ã‹åˆ†ã‹ã‚‰ãªã„ã‘ã©)ã™ã‚‹éŽç¨‹ã§è½ã¡ç€ã„ã¦ã„る今ã®ã¨ã“ã‚ã®è§£ã§ã™ã€‚ + //ã»ã‚“ã¨ã®è§£æ³•ã¯æ¨‹å£ã•ã‚“ãŒçŸ¥ã£ã¦ã‚‹ã‚“ã ã‚ã†ã‘ã©ï½— + //解法ã¯ä»Šã®ã¨ã“ã‚IK-CCD法ãŒMMDã«ã¨ã£ã¦æœ€é©ã ã¨è€ƒãˆã¦ã¾ã™ã€‚ + //ç†ç”±ã¨ã—㦠+ //・ã²ã–ã®ãƒœãƒ¼ãƒ³ã«IKソルブ時ã®è§’度制é™ãŒå…¥ã£ã¦ã„ã‚‹ã£ã½ã„ã®ã§ã€ã‚½ãƒ«ãƒ–ã«ãƒœãƒ¼ãƒ³ã®è§’度を扱ã†å¿…è¦ãŒã‚ã‚‹ã“㨠+ //・高速解法ãŒå¿…è¦ã§ã‚ã‚‹ã“ã¨(MMDãŒéžå¸¸ã«è»½ã„ã“ã¨ã¨ã€ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã®å­˜åœ¨ã¨ãã®å›žæ•°ã‚’考ãˆã‚‹ã¨ã€è»½ã„アルゴリズムを使ã£ã¦ãªã„ã¨ã¤ã˜ã¤ã¾ãŒåˆã‚ãªã„) + //ãŒä¸Šã’られã¾ã™ + //ãã“ã§ã€CCD,Particleã‹ã®äºŒã¤ã§ã€è§’åº¦ã‚’ä½¿ã„æ˜“ã‹ã£ãŸCCDã‚’é¸ã³ã¾ã—ãŸã€‚ + //ã²ã–ã®è§’度調整ã¯CCDã®ã‚¯ã‚»ã‚’抑ãˆã‚‹ç†ç”±ã‚‚ã‚ã£ã¦å·¥å¤«ã—ã¦ã‚りã¾ã™ã€‚ + //CCDã®ã‚¯ã‚»ã¨ã—ã¦ã€æ­£ã—ã„è§£ãŒï¼œã ã¨ã—ãŸã‚‰ã€ï¼žã¨ã„ã†è§£ã‚’出ã—ã¦ãã‚‹ã“ã¨ãŒå¤šã„ã¨ã„ã†å•題ãŒã‚りã¾ã™ã€‚(><ã¯è¶³ã§ã™ï½—) + //ãã®ãŸã‚ã«"å発係数"ãªã‚‹è¬Žãªãƒ‘ラメータを付ã‘ã¦ã¾ã™ï½— + //ã¾ãŸã€è§£ãŒã»ã¨ã‚“ã©ã¾ã£ã™ããªè§£ã‚’出ã™éš›ã«ã€|ãªæ„Ÿã˜ã®è§£ã§å›ºå®šã•れã¦ã—ã¾ã†å•題ãŒã‚ã‚‹ãŸã‚ã€3度ãらã„下é™ã‚’入れã¦ã„ã¾ã™(ã©ã†ã‚‚ã€MMDã®æ–¹ã‚‚入れã¦ã‚‹ã£ã½ã„ã‘ã©ã€ã‚ˆã分ã‹ã‚‰ãªã„……) + //ã“れã¯ç¾åœ¨ã®æŽ¨å®šçµæžœã§ã™ã€‚ã‚‚ã£ã¨å†ç¾æ€§ãŒé«˜ã„è§£ãŒã‚れã°ã€æ”¹é€ ã—ã¦ã€ãœã²æ•™ãˆã¦ãã ã•ã„ + + //2012/01/19追記分 + //IKè¨ˆç®—ã®æœ¬å®¶MMDã¨ã®å¾®å¦™ãªã‚ºãƒ¬ã‚’発見。 + //場所ã¯ä»˜å±žãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³(true my heart)ã®è…°æŒ¯ã‚Šã®ã‚ã¨ï¼¼(^o^)ï¼ãªå‹•作ã«ç§»è¡Œã™ã‚‹è…°æŒ¯ã‚Šã®ã¨ã“ã‚ + //è¶³ã®å‹•ããŒå¾®å¦™ã«æœ¬å®¶ã¨ã‚ºãƒ¬ã¦ã„ã‚‹ã“ã¨ã‚’発見 + //原因を調査ã—ãŸã¨ã“ã‚ã€å³è¶³ã€å·¦è¶³ã®Y軸回転ã®å‹•ããŒIKã®è¨ˆç®—ã«ã‚ˆã‚Šè£œæ­£ã•れã¦ã—ã¾ã†ã®ãŒåŽŸå› ã¨åˆ¤æ˜Ž + //ãã®ãŸã‚ã€æ–°ãŸã«axisLimit機能を追加ã—ã€å³è¶³ã€å·¦è¶³ãŒIK計算ã§Y軸回転を補正ã•れãªã„よã†ã«ã—ãŸã€‚ + //ã“れã«ã‚ˆã‚Šä»–ã®ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ã«å½±éŸ¿ãŒå‡ºãªã„ã‹ã¯ç¾åœ¨èª¿æŸ»ä¸­ + } + + + + #region IIKLimitter メンãƒãƒ¼ + /// + /// 制é™ã®é©ç”¨ + /// + /// 対象ã¨ãªã‚‹ãƒœãƒ¼ãƒ³ + public void Adjust(Model.MMDBone bone) + { + if (!TotalRotationLimits.ContainsKey(bone.Name)) + return; + float YRot, XRot, ZRot; + int FactoringType = 0; + //if (MMDMath.FactoringQuaternionZXY(rot, out ZRot, out XRot, out YRot)) + //ã¾ãšã¯XYZã§åˆ†è§£ + if (!MathHelper.FactoringQuaternionXYZ(bone.LocalTransform.Rotation, out XRot, out YRot, out ZRot)) + {//ジンãƒãƒ«ãƒ­ãƒƒã‚¯å¯¾ç­– + //YZXã§åˆ†è§£ + if (!MathHelper.FactoringQuaternionYZX(bone.LocalTransform.Rotation, out YRot, out ZRot, out XRot)) + { + //ZXYã§åˆ†è§£ + MathHelper.FactoringQuaternionZXY(bone.LocalTransform.Rotation, out ZRot, out XRot, out YRot); + FactoringType = 2; + } + else + FactoringType = 1; + } + else + FactoringType = 0; + + RotationLimit lim = TotalRotationLimits[bone.Name]; + XRot = lim.Adjust(XRot, 0); + YRot = lim.Adjust(YRot, 1); + ZRot = lim.Adjust(ZRot, 2); + if (FactoringType == 0) + bone.LocalTransform.Rotation = Quaternion.CreateFromRotationMatrix( + Matrix.CreateRotationX(XRot) * + Matrix.CreateRotationY(YRot) * + Matrix.CreateRotationZ(ZRot)); + else if (FactoringType == 1) + bone.LocalTransform.Rotation = Quaternion.CreateFromRotationMatrix( + Matrix.CreateRotationY(YRot) * + Matrix.CreateRotationZ(ZRot) * + Matrix.CreateRotationX(XRot)); + else + bone.LocalTransform.Rotation = Quaternion.CreateFromYawPitchRoll(YRot, XRot, ZRot); + + } + /// + /// 回転軸制é™ã®é©ç”¨ + /// + /// ボーンå + /// 回転軸 + public void Adjust(string boneName, ref Vector3 rotationAxis) + { + RotationAxisLimit limit; + if (RotationAxisLimits.TryGetValue(boneName, out limit)) + { + limit.Adjust(ref rotationAxis); + } + } + #endregion + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/IIKLimitter.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/IIKLimitter.cs new file mode 100644 index 000000000..7af448aaa --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/IIKLimitter.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MMDIKBakerLibrary.Model; + +namespace MMDIKBakerLibrary.Misc +{ + interface IIKLimitter + { + /// + /// 制é™ã®é©ç”¨ + /// + /// 対象ã¨ãªã‚‹ãƒœãƒ¼ãƒ³ + void Adjust(MMDBone bone); + + /// + /// 回転軸制é™ã®é©ç”¨ + /// + /// 対象ã¨ãªã‚‹ãƒœãƒ¼ãƒ³å + /// 回転軸 + void Adjust(string boneName, ref Vector3 rotationAxis); + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/IIKSolver.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/IIKSolver.cs new file mode 100644 index 000000000..e09c6a681 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/IIKSolver.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MMDIKBakerLibrary.Model; + +namespace MMDIKBakerLibrary.Misc +{ + interface IIKSolver + { + /// + /// IKã®ã‚½ãƒ«ãƒ– + /// + /// 対象IK + /// ボーンマãƒãƒ¼ã‚¸ãƒ£ + /// 呼ã³å‡ºã—å´ã§UpdateGlobalã‚’ã‚‚ã†ä¸€åº¦å‘¼ã¶å ´åˆã¯true + bool Solve(MMDIK ik, MMDBoneManager BoneManager); + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/MathHelper.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/MathHelper.cs new file mode 100644 index 000000000..7a6a6244d --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/MathHelper.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MMDIKBakerLibrary.Misc +{ + static class MathHelper + { + public static float Pi { get { return (float)Math.PI; } } + public static float PiOver2 { get { return Pi / 2; } } + public static decimal Clamp(decimal value, decimal min, decimal max) + { + return Math.Max(min, Math.Min(value, max)); + } + public static float Clamp(float value, float min, float max) + { + return Math.Max(min, Math.Min(value, max)); + } + + + public static decimal Lerp(decimal value1, decimal value2, decimal amount) + { + if (value1 == value2) + { + return value1; + } + return value1 + (value2 - value1) * Clamp(amount, 0m, 1m); + } + public static float Lerp(float value1, float value2, float amount) + { + if (value1 == value2) + { + return value1; + } + return value1 + (value2 - value1) * Clamp(amount, 0, 1); + } + public static BezierCurve[] CreateIdentityCurve() + { + BezierCurve[] result = new BezierCurve[4]; + for (int i = 0; i < result.Length; i++) + { + result[i].v1 = new Vector2 { X = 0.25f, Y = 0.25f }; + result[i].v2 = new Vector2 { X = 0.75f, Y = 0.75f }; + } + return result; + } + + public static int GetMaxArgIndex(params decimal[] argument) + { + decimal value = decimal.MinValue; + int index = -1; + for (int i = 0; i < argument.Length; ++i) + { + if (argument[i] > value) + { + index = i; + value = argument[i]; + } + } + return index; + } + + public static Vector3 Round(Vector3 vector, int decimals) + { + return new Vector3(Math.Round(vector.X, decimals),Math.Round(vector.Y, decimals),Math.Round(vector.Z, decimals)); + } + + public static Quaternion Round(Quaternion rotation, int decimals) + { + return new Quaternion(Math.Round(rotation.X, decimals), Math.Round(rotation.Y, decimals), Math.Round(rotation.Z, decimals), Math.Round(rotation.W, decimals)); + } + + internal static Matrix Round(Matrix matrix, int decimals) + { + return new Matrix() + { + M11 = Math.Round(matrix.M11, decimals), + M12 = Math.Round(matrix.M12, decimals), + M13 = Math.Round(matrix.M13, decimals), + M14 = Math.Round(matrix.M14, decimals), + M21 = Math.Round(matrix.M21, decimals), + M22 = Math.Round(matrix.M22, decimals), + M23 = Math.Round(matrix.M23, decimals), + M24 = Math.Round(matrix.M24, decimals), + M31 = Math.Round(matrix.M31, decimals), + M32 = Math.Round(matrix.M32, decimals), + M33 = Math.Round(matrix.M33, decimals), + M34 = Math.Round(matrix.M34, decimals), + M41 = Math.Round(matrix.M41, decimals), + M42 = Math.Round(matrix.M42, decimals), + M43 = Math.Round(matrix.M43, decimals), + M44 = Math.Round(matrix.M44, decimals) + }; + } + + + + + public static float ToRadians(float degrees) + { + return degrees * 0.01745329f; + } + /// + /// クォータニオンをYaw(Y回転), Pitch(X回転), Roll(Z回転)ã«åˆ†è§£ã™ã‚‹é–¢æ•° + /// + /// 分解ã™ã‚‹ã‚¯ã‚©ãƒ¼ã‚¿ãƒ‹ã‚ªãƒ³ + /// Z軸回転 + /// X軸回転(-PI/2~PI/2) + /// Y軸回転 + /// ジンãƒãƒ«ãƒ­ãƒƒã‚¯ãŒç™ºç”Ÿã—ãŸæ™‚ã¯false。ジンãƒãƒ«ãƒ­ãƒƒã‚¯ã¯X軸回転ã§ç™ºç”Ÿ + public static bool FactoringQuaternionZXY(Quaternion input, out float ZRot, out float XRot, out float YRot) + { + //ã‚¯ã‚©ãƒ¼ã‚¿ãƒ‹ã‚ªãƒ³ã®æ­£è¦åŒ– + Quaternion inputQ = new Quaternion(input.X, input.Y, input.Z, input.W); + inputQ.Normalize(); + //マトリクスを生æˆã™ã‚‹ + Matrix rot; + Matrix.CreateFromQuaternion(ref inputQ, out rot); + //ヨー(X軸周りã®å›žè»¢)ã‚’å–å¾— + if ((double)rot.M32 > 1 - 1.0e-4 || (double)rot.M32 < -1 + 1.0e-4) + {//ジンãƒãƒ«ãƒ­ãƒƒã‚¯åˆ¤å®š + XRot = (rot.M32 < 0 ? MathHelper.PiOver2 : -MathHelper.PiOver2); + ZRot = 0; YRot = (float)Math.Atan2(-(double)rot.M13, (double) rot.M11); + return false; + } + XRot = -(float)Math.Asin((double)rot.M32); + //ロールをå–å¾— + ZRot = (float)Math.Asin((double)rot.M12 / Math.Cos(XRot)); + if (float.IsNaN(ZRot)) + {//æ¼ã‚Œå¯¾ç­– + XRot = (rot.M32 < 0 ? MathHelper.PiOver2 : -MathHelper.PiOver2); + ZRot = 0; YRot = (float)Math.Atan2(-(double)rot.M13, (double)rot.M11); + return false; + } + if (rot.M22 < 0) + ZRot = MathHelper.Pi - ZRot; + //ピッãƒã‚’å–å¾— + YRot = (float)Math.Atan2((double)rot.M31, (double)rot.M33); + return true; + } + + + /// + /// クォータニオンをX,Y,Z回転ã«åˆ†è§£ã™ã‚‹é–¢æ•° + /// + /// 分解ã™ã‚‹ã‚¯ã‚©ãƒ¼ã‚¿ãƒ‹ã‚ªãƒ³ + /// X軸回転 + /// Y軸回転(-PI/2~PI/2) + /// Z軸回転 + /// + public static bool FactoringQuaternionXYZ(Quaternion input, out float XRot, out float YRot, out float ZRot) + { + //ã‚¯ã‚©ãƒ¼ã‚¿ãƒ‹ã‚ªãƒ³ã®æ­£è¦åŒ– + Quaternion inputQ = new Quaternion(input.X, input.Y, input.Z, input.W); + inputQ.Normalize(); + //マトリクスを生æˆã™ã‚‹ + Matrix rot; + Matrix.CreateFromQuaternion(ref inputQ, out rot); + //Y軸回りã®å›žè»¢ã‚’å–å¾— + if ((double)rot.M13 > 1 - 1.0e-4 || (double)rot.M13 < -1 + 1.0e-4) + {//ジンãƒãƒ«ãƒ­ãƒƒã‚¯åˆ¤å®š + XRot = 0; + YRot = (rot.M13 < 0 ? MathHelper.PiOver2 : -MathHelper.PiOver2); + ZRot = -(float)Math.Atan2(-(double)rot.M21, (double)rot.M22); + return false; + } + YRot = -(float)Math.Asin((double)rot.M13); + //X軸回りã®å›žè»¢ã‚’å–å¾— + XRot = (float)Math.Asin((double)rot.M23 / Math.Cos(YRot)); + if (float.IsNaN(XRot)) + {//ジンãƒãƒ«ãƒ­ãƒƒã‚¯åˆ¤å®š(æ¼ã‚Œå¯¾ç­–) + XRot = 0; + YRot = (rot.M13 < 0 ? MathHelper.PiOver2 : -MathHelper.PiOver2); + ZRot = -(float)Math.Atan2(-(double)rot.M21, (double)rot.M22); + return false; + } + if (rot.M33 < 0) + XRot = MathHelper.Pi - XRot; + //Z軸回りã®å›žè»¢ã‚’å–å¾— + ZRot = (float)Math.Atan2((double)rot.M12, (double)rot.M11); + return true; + } + /// + /// クォータニオンをY,Z,X回転ã«åˆ†è§£ã™ã‚‹é–¢æ•° + /// + /// 分解ã™ã‚‹ã‚¯ã‚©ãƒ¼ã‚¿ãƒ‹ã‚ªãƒ³ + /// Y軸回転 + /// Z軸回転(-PI/2~PI/2) + /// X軸回転 + /// + public static bool FactoringQuaternionYZX(Quaternion input, out float YRot, out float ZRot, out float XRot) + { + //ã‚¯ã‚©ãƒ¼ã‚¿ãƒ‹ã‚ªãƒ³ã®æ­£è¦åŒ– + Quaternion inputQ = new Quaternion(input.X, input.Y, input.Z, input.W); + inputQ.Normalize(); + //マトリクスを生æˆã™ã‚‹ + Matrix rot; + Matrix.CreateFromQuaternion(ref inputQ, out rot); + //Z軸回りã®å›žè»¢ã‚’å–å¾— + if ((double)rot.M21 > 1 - 1.0e-4 || (double)rot.M21 < -1 + 1.0e-4) + {//ジンãƒãƒ«ãƒ­ãƒƒã‚¯åˆ¤å®š + YRot = 0; + ZRot = (rot.M21 < 0 ? MathHelper.PiOver2 : -MathHelper.PiOver2); + XRot = -(float)Math.Atan2(-(double)rot.M32, (double)rot.M33); + return false; + } + ZRot = -(float)Math.Asin((double)rot.M21); + //Y軸回りã®å›žè»¢ã‚’å–å¾— + YRot = (float)Math.Asin((double)rot.M31 / Math.Cos(ZRot)); + if (float.IsNaN(YRot)) + {//ジンãƒãƒ«ãƒ­ãƒƒã‚¯åˆ¤å®š(æ¼ã‚Œå¯¾ç­–) + YRot = 0; + ZRot = (rot.M21 < 0 ? MathHelper.PiOver2 : -MathHelper.PiOver2); + XRot = -(float)Math.Atan2(-(double)rot.M32, (double)rot.M33); + return false; + } + if (rot.M11 < 0) + YRot = MathHelper.Pi - YRot; + //X軸回りã®å›žè»¢ã‚’å–å¾— + XRot = (float)Math.Atan2((double)rot.M23, (double)rot.M22); + return true; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Matrix.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Matrix.cs new file mode 100644 index 000000000..34d4e9d5e --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Matrix.cs @@ -0,0 +1,393 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MMDIKBakerLibrary.Misc +{ + struct Matrix + { + public decimal M11; + public decimal M12; + public decimal M13; + public decimal M14; + public decimal M21; + public decimal M22; + public decimal M23; + public decimal M24; + public decimal M31; + public decimal M32; + public decimal M33; + public decimal M34; + public decimal M41; + public decimal M42; + public decimal M43; + public decimal M44; + + + public static Matrix Identity + { + get + { + return new Matrix { M11 = 1, M12 = 0, M13 = 0, M14 = 0, M21 = 0, M22 = 1, M23 = 0, M24 = 0, M31 = 0, M32 = 0, M33 = 1, M34 = 0, M41 = 0, M42 = 0, M43 = 0, M44 = 1 }; + } + } + public Vector3 Translation + { + get + { + Vector3 result; + result.X = this.M41; + result.Y = this.M42; + result.Z = this.M43; + result.NaN = false; + return result; + } + + } + + + public static void CreateTranslation(decimal x, decimal y, decimal z, out Matrix result) + { + result.M11 = 1; + result.M12 = 0; + result.M13 = 0; + result.M14 = 0; + result.M21 = 0; + result.M22 = 1; + result.M23 = 0; + result.M24 = 0; + result.M31 = 0; + result.M32 = 0; + result.M33 = 1; + result.M34 = 0; + result.M41 = x; + result.M42 = y; + result.M43 = z; + result.M44 = 1; + } + + public static void Invert(ref Matrix matrix, out Matrix result) + { + decimal temp1 = matrix.M33 * matrix.M44 - matrix.M34 * matrix.M43; + decimal temp2 = matrix.M32 * matrix.M44 - matrix.M34 * matrix.M42; + decimal temp3 = matrix.M32 * matrix.M43 - matrix.M33 * matrix.M42; + decimal temp4 = matrix.M31 * matrix.M44 - matrix.M34 * matrix.M41; + decimal temp5 = matrix.M31 * matrix.M43 - matrix.M33 * matrix.M41; + decimal temp6 = matrix.M31 * matrix.M42 - matrix.M32 * matrix.M41; + decimal temp7 = matrix.M22 * temp1 - matrix.M23 * temp2 + matrix.M24 * temp3; + decimal temp8 = -(matrix.M21 * temp1 - matrix.M23 * temp4 + matrix.M24 * temp5); + decimal temp9 = matrix.M21 * temp2 - matrix.M22 * temp4 + matrix.M24 * temp6; + decimal temp10 = -(matrix.M21 * temp3 - matrix.M22 * temp5 + matrix.M23 * temp6); + decimal temp11 = matrix.M23 * matrix.M44 - matrix.M24 * matrix.M43; + decimal temp12 = matrix.M22 * matrix.M44 - matrix.M24 * matrix.M42; + decimal temp13 = matrix.M22 * matrix.M43 - matrix.M23 * matrix.M42; + decimal temp14 = matrix.M21 * matrix.M44 - matrix.M24 * matrix.M41; + decimal temp15 = matrix.M21 * matrix.M43 - matrix.M23 * matrix.M41; + decimal temp16 = matrix.M21 * matrix.M42 - matrix.M22 * matrix.M41; + decimal temp17 = matrix.M23 * matrix.M34 - matrix.M24 * matrix.M33; + decimal temp18 = matrix.M22 * matrix.M34 - matrix.M24 * matrix.M32; + decimal temp19 = matrix.M22 * matrix.M33 - matrix.M23 * matrix.M32; + decimal temp20 = matrix.M21 * matrix.M34 - matrix.M24 * matrix.M31; + decimal temp21 = matrix.M21 * matrix.M33 - matrix.M23 * matrix.M31; + decimal temp22 = matrix.M21 * matrix.M32 - matrix.M22 * matrix.M31; + decimal det = 1m / (matrix.M11 * temp7 + matrix.M12 * temp8 + matrix.M13 * temp9 + matrix.M14 * temp10); + result.M11 = temp7 * det; + result.M21 = temp8 * det; + result.M31 = temp9 * det; + result.M41 = temp10 * det; + result.M12 = -(matrix.M12 * temp1 - matrix.M13 * temp2 + matrix.M14 * temp3) * det; + result.M22 = (matrix.M11 * temp1 - matrix.M13 * temp4 + matrix.M14 * temp5) * det; + result.M32 = -(matrix.M11 * temp2 - matrix.M12 * temp4 + matrix.M14 * temp6) * det; + result.M42 = (matrix.M11 * temp3 - matrix.M12 * temp5 + matrix.M13 * temp6) * det; + result.M13 = (matrix.M12 * temp11 - matrix.M13 * temp12 + matrix.M14 * temp13) * det; + result.M23 = -(matrix.M11 * temp11 - matrix.M13 * temp14 + matrix.M14 * temp15) * det; + result.M33 = (matrix.M11 * temp12 - matrix.M12 * temp14 + matrix.M14 * temp16) * det; + result.M43 = -(matrix.M11 * temp13 - matrix.M12 * temp15 + matrix.M13 * temp16) * det; + result.M14 = -(matrix.M12 * temp17 - matrix.M13 * temp18 + matrix.M14 * temp19) * det; + result.M24 = (matrix.M11 * temp17 - matrix.M13 * temp20 + matrix.M14 * temp21) * det; + result.M34 = -(matrix.M11 * temp18 - matrix.M12 * temp20 + matrix.M14 * temp22) * det; + result.M44 = (matrix.M11 * temp19 - matrix.M12 * temp21 + matrix.M13 * temp22) * det; + } + + public static void Multiply(ref Matrix matrix1, ref Matrix matrix2, out Matrix result) + { + result.M11 = matrix1.M11 * matrix2.M11 + matrix1.M12 * matrix2.M21 + matrix1.M13 * matrix2.M31 + matrix1.M14 * matrix2.M41; + result.M12 = matrix1.M11 * matrix2.M12 + matrix1.M12 * matrix2.M22 + matrix1.M13 * matrix2.M32 + matrix1.M14 * matrix2.M42; + result.M13 = matrix1.M11 * matrix2.M13 + matrix1.M12 * matrix2.M23 + matrix1.M13 * matrix2.M33 + matrix1.M14 * matrix2.M43; + result.M14 = matrix1.M11 * matrix2.M14 + matrix1.M12 * matrix2.M24 + matrix1.M13 * matrix2.M34 + matrix1.M14 * matrix2.M44; + result.M21 = matrix1.M21 * matrix2.M11 + matrix1.M22 * matrix2.M21 + matrix1.M23 * matrix2.M31 + matrix1.M24 * matrix2.M41; + result.M22 = matrix1.M21 * matrix2.M12 + matrix1.M22 * matrix2.M22 + matrix1.M23 * matrix2.M32 + matrix1.M24 * matrix2.M42; + result.M23 = matrix1.M21 * matrix2.M13 + matrix1.M22 * matrix2.M23 + matrix1.M23 * matrix2.M33 + matrix1.M24 * matrix2.M43; + result.M24 = matrix1.M21 * matrix2.M14 + matrix1.M22 * matrix2.M24 + matrix1.M23 * matrix2.M34 + matrix1.M24 * matrix2.M44; + result.M31 = matrix1.M31 * matrix2.M11 + matrix1.M32 * matrix2.M21 + matrix1.M33 * matrix2.M31 + matrix1.M34 * matrix2.M41; + result.M32 = matrix1.M31 * matrix2.M12 + matrix1.M32 * matrix2.M22 + matrix1.M33 * matrix2.M32 + matrix1.M34 * matrix2.M42; + result.M33 = matrix1.M31 * matrix2.M13 + matrix1.M32 * matrix2.M23 + matrix1.M33 * matrix2.M33 + matrix1.M34 * matrix2.M43; + result.M34 = matrix1.M31 * matrix2.M14 + matrix1.M32 * matrix2.M24 + matrix1.M33 * matrix2.M34 + matrix1.M34 * matrix2.M44; + result.M41 = matrix1.M41 * matrix2.M11 + matrix1.M42 * matrix2.M21 + matrix1.M43 * matrix2.M31 + matrix1.M44 * matrix2.M41; + result.M42 = matrix1.M41 * matrix2.M12 + matrix1.M42 * matrix2.M22 + matrix1.M43 * matrix2.M32 + matrix1.M44 * matrix2.M42; + result.M43 = matrix1.M41 * matrix2.M13 + matrix1.M42 * matrix2.M23 + matrix1.M43 * matrix2.M33 + matrix1.M44 * matrix2.M43; + result.M44 = matrix1.M41 * matrix2.M14 + matrix1.M42 * matrix2.M24 + matrix1.M43 * matrix2.M34 + matrix1.M44 * matrix2.M44; + } + public static Matrix operator *(Matrix matrix1, Matrix matrix2) + { + Matrix result; + Matrix.Multiply(ref matrix1, ref matrix2, out result); + return result; + } + public static void CreateScale(ref Vector3 scale, out Matrix result) + { + result.M11 = scale.X; + result.M12 = 0; + result.M13 = 0; + result.M14 = 0; + result.M21 = 0; + result.M22 = scale.Y; + result.M23 = 0; + result.M24 = 0; + result.M31 = 0; + result.M32 = 0; + result.M33 = scale.Z; + result.M34 = 0; + result.M41 = 0; + result.M42 = 0; + result.M43 = 0; + result.M44 = 1; + } + public static void CreateFromQuaternion(Quaternion quaternion, out Matrix result) + { + quaternion.Normalize(); + decimal xx = quaternion.X * quaternion.X; + decimal yy = quaternion.Y * quaternion.Y; + decimal zz = quaternion.Z * quaternion.Z; + decimal xy = quaternion.X * quaternion.Y; + decimal yz = quaternion.Y * quaternion.Z; + decimal zx = quaternion.Z * quaternion.X; + decimal xw = quaternion.X * quaternion.W; + decimal yw = quaternion.Y * quaternion.W; + decimal zw = quaternion.Z * quaternion.W; + result.M11 = 1 - 2 * (yy + zz); + result.M12 = 2 * (xy + zw); + result.M13 = 2 * (zx - yw); + result.M14 = 0; + result.M21 = 2 * (xy - zw); + result.M22 = 1 - 2 * (zz + xx); + result.M23 = 2 * (yz + xw); + result.M24 = 0; + result.M31 = 2 * (zx + yw); + result.M32 = 2 * (yz - xw); + result.M33 = 1 - 2 * (yy + xx); + result.M34 = 0; + result.M41 = 0; + result.M42 = 0; + result.M43 = 0; + result.M44 = 1; + } + public static void CreateTranslation(ref Vector3 position, out Matrix result) + { + result.M11 = 1; + result.M12 = 0; + result.M13 = 0; + result.M14 = 0; + result.M21 = 0; + result.M22 = 1; + result.M23 = 0; + result.M24 = 0; + result.M31 = 0; + result.M32 = 0; + result.M33 = 1; + result.M34 = 0; + result.M41 = position.X; + result.M42 = position.Y; + result.M43 = position.Z; + result.M44 = 1; + } + + public void Decompose(out Vector3 scale, out Quaternion rotation, out Vector3 translation) + { + //移動行列ã®åˆ‡ã‚Šå‡ºã— + translation = new Vector3(M41, M42, M43); + //スケールã®åˆ‡ã‚Šå‡ºã—ã¨å›žè»¢è¡Œåˆ—ã®ä½œæˆ + scale = new Vector3(); + Matrix rotMatrix = new Matrix(); + Vector3 temp; + temp = new Vector3(M11, M12, M13); + scale.X = temp.Length(); + if (scale.X > 0) + { + rotMatrix.M11 = M11 / scale.X; + rotMatrix.M12 = M12 / scale.X; + rotMatrix.M13 = M13 / scale.X; + } + temp = new Vector3(M21, M22, M23); + scale.Y = temp.Length(); + if (scale.X > 0) + { + rotMatrix.M21 = M21 / scale.Y; + rotMatrix.M22 = M22 / scale.Y; + rotMatrix.M23 = M23 / scale.Y; + } + temp = new Vector3(M31, M32, M33); + scale.Z = temp.Length(); + if (scale.X > 0) + { + rotMatrix.M31 = M31 / scale.Z; + rotMatrix.M32 = M32 / scale.Z; + rotMatrix.M33 = M33 / scale.Z; + } + if (scale.Length() == 0) + { + throw new ArgumentException("scaleæˆåˆ†ãŒä¸æ˜Ž"); + } + //回転行列をクォータニオンã«å¤‰æ›ã™ã‚‹ + rotation = new Quaternion(); + decimal w = (decimal)Math.Sqrt((double)Math.Max(rotMatrix.M11 + rotMatrix.M22 + rotMatrix.M33 + 1, 0)) / 2; + decimal tempX = (decimal)Math.Sqrt((double)Math.Max(rotMatrix.M11 - rotMatrix.M22 - rotMatrix.M33 + 1, 0)) / 2; + decimal tempY = (decimal)Math.Sqrt((double)Math.Max(-rotMatrix.M11 + rotMatrix.M22 - rotMatrix.M33 + 1, 0)) / 2; + decimal tempZ = (decimal)Math.Sqrt((double)Math.Max(-rotMatrix.M11 - rotMatrix.M22 + rotMatrix.M33 + 1, 0)) / 2; + int MaxIndex = MathHelper.GetMaxArgIndex(tempX, tempY, tempZ, w); + switch (MaxIndex) + { + case 0://x + rotation.X = tempX; + rotation.Y = (rotMatrix.M12 + rotMatrix.M21) / (4 * Math.Abs(tempX)); + rotation.Z = (rotMatrix.M31 + rotMatrix.M13) / (4 * Math.Abs(tempX)); + rotation.W = (rotMatrix.M23 - rotMatrix.M32) / (4 * Math.Abs(tempX)); + break; + case 1: + rotation.X = (rotMatrix.M12 + rotMatrix.M21) / (4 * Math.Abs(tempY)); + rotation.Y = tempY; + rotation.Z = (rotMatrix.M23 + rotMatrix.M32) / (4 * Math.Abs(tempY)); + rotation.W = (rotMatrix.M31 - rotMatrix.M13) / (4 * Math.Abs(tempY)); + break; + case 2: + rotation.X = (rotMatrix.M31 + rotMatrix.M13) / (4 * Math.Abs(tempZ)); + rotation.Y = (rotMatrix.M23 + rotMatrix.M32) / (4 * Math.Abs(tempZ)); + rotation.Z = tempZ; + rotation.W = (rotMatrix.M12 - rotMatrix.M21) / (4 * Math.Abs(tempZ)); + break; + default://w + rotation.X = (rotMatrix.M23 - rotMatrix.M32) / (4 * Math.Abs(w)); + rotation.Y = (rotMatrix.M31 - rotMatrix.M13) / (4 * Math.Abs(w)); + rotation.Z = (rotMatrix.M12 - rotMatrix.M21) / (4 * Math.Abs(w)); + rotation.W = w; + break; + } + } + public static void Compose(Vector3 scale,Quaternion rotation, Vector3 translation, out Matrix result) + { + Matrix scaleMat, rotateMat, translationMat; + Matrix.CreateScale(ref scale, out scaleMat); + Matrix.CreateFromQuaternion(rotation, out rotateMat); + Matrix.CreateTranslation(ref translation, out translationMat); + Matrix temp; + Multiply(ref scaleMat, ref rotateMat, out temp); + Multiply(ref temp, ref translationMat, out result); + } + + + internal static void GetTranslation(ref Matrix matrix, out Vector3 trans) + { + trans = matrix.Translation; + } + + public static Matrix CreateRotationX(float radians) + { + Matrix result; + decimal single1 = (decimal)Math.Cos((double)radians); + decimal single2 = (decimal)Math.Sin((double)radians); + result.M11 = 1; + result.M12 = 0; + result.M13 = 0; + result.M14 = 0; + result.M21 = 0; + result.M22 = single1; + result.M23 = single2; + result.M24 = 0; + result.M31 = 0; + result.M32 = -single2; + result.M33 = single1; + result.M34 = 0; + result.M41 = 0; + result.M42 = 0; + result.M43 = 0; + result.M44 = 1; + return result; + } + public static Matrix CreateRotationY(float radians) + { + Matrix result; + decimal single1 = (decimal)Math.Cos((double)radians); + decimal single2 = (decimal)Math.Sin((double)radians); + result.M11 = single1; + result.M12 = 0; + result.M13 = -single2; + result.M14 = 0; + result.M21 = 0; + result.M22 = 1; + result.M23 = 0; + result.M24 = 0; + result.M31 = single2; + result.M32 = 0; + result.M33 = single1; + result.M34 = 0; + result.M41 = 0; + result.M42 = 0; + result.M43 = 0; + result.M44 = 1; + return result; + } + public static Matrix CreateRotationZ(float radians) + { + Matrix result; + decimal single1 = (decimal)Math.Cos((double)radians); + decimal single2 = (decimal)Math.Sin((double)radians); + result.M11 = single1; + result.M12 = single2; + result.M13 = 0; + result.M14 = 0; + result.M21 = -single2; + result.M22 = single1; + result.M23 = 0; + result.M24 = 0; + result.M31 = 0; + result.M32 = 0; + result.M33 = 1; + result.M34 = 0; + result.M41 = 0; + result.M42 = 0; + result.M43 = 0; + result.M44 = 1; + return result; + } + public static void CreateFromQuaternion(ref Quaternion quaternion, out Matrix result) + { + decimal xx = quaternion.X * quaternion.X; + decimal yy = quaternion.Y * quaternion.Y; + decimal zz = quaternion.Z * quaternion.Z; + decimal xy = quaternion.X * quaternion.Y; + decimal zw = quaternion.Z * quaternion.W; + decimal zx = quaternion.Z * quaternion.X; + decimal yw = quaternion.Y * quaternion.W; + decimal yz = quaternion.Y * quaternion.Z; + decimal xw = quaternion.X * quaternion.W; + result.M11 = 1 - 2 * (yy + zz); + result.M12 = 2 * (xy + zw); + result.M13 = 2 * (zx - yw); + result.M14 = 0; + result.M21 = 2 * (xy - zw); + result.M22 = 1 - 2 * (zz + xx); + result.M23 = 2 * (yz + xw); + result.M24 = 0; + result.M31 = 2 * (zx + yw); + result.M32 = 2 * (yz - xw); + result.M33 = 1 - 2 * (yy + xx); + result.M34 = 0; + result.M41 = 0; + result.M42 = 0; + result.M43 = 0; + result.M44 = 1; + } + + + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Quaternion.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Quaternion.cs new file mode 100644 index 000000000..b004e92c4 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Quaternion.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MMDIKBakerLibrary.Misc +{ + struct Quaternion + { + public decimal X; + public decimal Y; + public decimal Z; + public decimal W; + + public static Quaternion Identity { get { return new Quaternion(0, 0, 0, 1); } } + + public Quaternion(decimal x, decimal y, decimal z, decimal w) + { + X = x; Y = y; Z = z; W = w; + } + public static void Slerp(ref Quaternion quaternion1, ref Quaternion quaternion2, decimal amount, out Quaternion result) + { + decimal rate2; + decimal rate1; + decimal dot = quaternion1.X * quaternion2.X + quaternion1.Y * quaternion2.Y + quaternion1.Z * quaternion2.Z + quaternion1.W * quaternion2.W; + bool flag = false; + if (dot < 0) + { + flag = true; + dot = -dot; + } + if (dot > 0.999999m) + { + rate1 = 1 - amount; + rate2 = (flag ? -amount : amount); + } + else + { + decimal ph = (decimal)Math.Acos((double)dot); + rate1 = (decimal)Math.Sin((double)((1 - amount) * ph)) * (decimal)(1.0f/(float)Math.Sin((double)ph)); + rate2 = (decimal)Math.Sin((double)(amount * ph)) * (decimal)(1.0f/(float)Math.Sin((double)ph)); + if (flag) + { + rate2 = -rate2; + } + } + result.X = rate1 * quaternion1.X + rate2 * quaternion2.X; + result.Y = rate1 * quaternion1.Y + rate2 * quaternion2.Y; + result.Z = rate1 * quaternion1.Z + rate2 * quaternion2.Z; + result.W = rate1 * quaternion1.W + rate2 * quaternion2.W; + } + public static Quaternion CreateFromAxisAngle(Vector3 axis, decimal angle) + { + decimal temp = (decimal)Math.Sin((double)angle * 0.5); + Quaternion result; + result.X = axis.X * temp; + result.Y = axis.Y * temp; + result.Z = axis.Z * temp; + result.W = (decimal)Math.Cos((double)angle * 0.5); + return result; + } + + + + public void Normalize() + { + decimal temp = 1 / (decimal)Math.Sqrt((double)(this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W)); + this.X = this.X * temp; + this.Y = this.Y * temp; + this.Z = this.Z * temp; + this.W = this.W * temp; + } + + public static void Multiply(ref Quaternion quaternion1, ref Quaternion quaternion2, out Quaternion result) + { + result.X = quaternion1.X * quaternion2.W + quaternion2.X * quaternion1.W + quaternion1.Y * quaternion2.Z - quaternion1.Z * quaternion2.Y; + result.Y = quaternion1.Y * quaternion2.W + quaternion2.Y * quaternion1.W + quaternion1.Z * quaternion2.X - quaternion1.X * quaternion2.Z; + result.Z = quaternion1.Z * quaternion2.W + quaternion2.Z * quaternion1.W + quaternion1.X * quaternion2.Y - quaternion1.Y * quaternion2.X; + result.W = quaternion1.W * quaternion2.W - (quaternion1.X * quaternion2.X + quaternion1.Y * quaternion2.Y + quaternion1.Z * quaternion2.Z); + } + public static Quaternion CreateFromRotationMatrix(Matrix matrix) + { + decimal diag = matrix.M11 + matrix.M22 + matrix.M33; + Quaternion result = new Quaternion(); + if (diag > 0) + { + decimal temp1 = (decimal)Math.Sqrt((double)diag + 1); + result.W = temp1 * 0.5m; + temp1 = 0.5m / temp1; + result.X = (matrix.M23 - matrix.M32) * temp1; + result.Y = (matrix.M31 - matrix.M13) * temp1; + result.Z = (matrix.M12 - matrix.M21) * temp1; + } + else + { + if (matrix.M11 >= matrix.M22 && matrix.M11 >= matrix.M33) + { + decimal temp2 = (decimal)Math.Sqrt((double)(1m + matrix.M11 - matrix.M22 - matrix.M33)); + decimal temp3 = 0.5m / temp2; + result.X = 0.5m * temp2; + result.Y = (matrix.M12 + matrix.M21) * temp3; + result.Z = (matrix.M13 + matrix.M31) * temp3; + result.W = (matrix.M23 - matrix.M32) * temp3; + } + } + return result; + } + public static Quaternion CreateFromYawPitchRoll(float yaw, float pitch, float roll) + { + decimal sin_roll = (decimal)Math.Sin((double)roll * 0.5); + decimal cos_roll = (decimal)Math.Cos((double)roll * 0.5); + decimal sin_pitch = (decimal)Math.Sin((double)pitch * 0.5); + decimal cos_pitch = (decimal)Math.Cos((double)pitch * 0.5); + decimal sin_yaw = (decimal)Math.Sin((double)yaw * 0.5); + decimal cos_yaw = (decimal)Math.Cos((double)yaw * 0.5); + Quaternion result; + result.X = cos_yaw * sin_pitch * cos_roll + sin_yaw * cos_pitch * sin_roll; + result.Y = sin_yaw * cos_pitch * cos_roll - cos_yaw * sin_pitch * sin_roll; + result.Z = cos_yaw * cos_pitch * sin_roll - sin_yaw * sin_pitch * cos_roll; + result.W = cos_yaw * cos_pitch * cos_roll + sin_yaw * sin_pitch * sin_roll; + return result; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/SQTTransform.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/SQTTransform.cs new file mode 100644 index 000000000..25dfb058c --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/SQTTransform.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MMDIKBakerLibrary.Misc +{ + /// + /// 拡大ã€å›žè»¢ã€ç§»å‹•ã®3ã¤ã‚’表ã™å¤‰æ› + /// + struct SQTTransform + { + #region フィールド + /// + /// 拡大 + /// + public Vector3 Scales; + + /// + /// 回転 + /// + public Quaternion Rotation; + + /// + /// 平行移動 + /// + public Vector3 Translation; + + #endregion + + /// + /// SQTTransformã‚’ç”Ÿæˆ + /// + /// スケールベクトル + /// 回転クォータニオン + /// 移動ベクトル + public SQTTransform(Vector3 scales, Quaternion rotation, Vector3 translation) + { + Scales = scales; + Rotation = rotation; + Translation = translation; + } + + /// + /// SQTTransformã‚’ç”Ÿæˆ + /// + /// スケールベクトル + /// 回転クォータニオン + /// 移動ベクトル + /// SQTTransform + public static void Create(ref Vector3 scales, ref Quaternion rotation, ref Vector3 translation, out SQTTransform result) + { + result = new SQTTransform() { Scales = scales, Rotation = rotation, Translation = translation }; + } + /// + /// 指定ã•れãŸè¡Œåˆ—ã‹ã‚‰ç”Ÿæˆã™ã‚‹ + /// + /// + /// + public static SQTTransform FromMatrix(Matrix matrix) + { + // 行列ã®åˆ†è§£ + Quaternion rotation; + Vector3 translation; + Vector3 scale; + matrix.Decompose(out scale, out rotation, out translation); + + + return new SQTTransform(scale, rotation, translation); + } + + /// + /// SQTTransformã®ä¹—ç®— + /// + public static void Multiply(ref SQTTransform value1, ref SQTTransform value2, out SQTTransform result) + { + result = new SQTTransform(); + // 平行移動ã®ç®—出 + // 拡大→回転 + Vector3 temp = new Vector3(); + Vector3 newTranslation; + temp.X = value1.Translation.X * value2.Scales.X; + temp.Y = value1.Translation.Y * value2.Scales.Y; + temp.Z = value1.Translation.Z * value2.Scales.Z; + Vector3.Transform(ref temp, ref value2.Rotation, out newTranslation); + + newTranslation.X += value2.Translation.X; + newTranslation.Y += value2.Translation.Y; + newTranslation.Z += value2.Translation.Z; + + // 回転部分ã®çµåˆ(å›žè»¢ã¨æ‹¡å¤§ã¯ç‹¬ç«‹ã ã£ãŸã¯ãšâ€¦â€¦) + Quaternion.Multiply(ref value1.Rotation, ref value2.Rotation, + out result.Rotation); + //拡大部分ã®çµåˆ + result.Scales.X = value1.Scales.X * value2.Scales.X; + result.Scales.Y = value1.Scales.Y * value2.Scales.Y; + result.Scales.Z = value1.Scales.Z * value2.Scales.Z; + result.Translation = newTranslation; + } + internal Matrix CreateMatrix() + { + Matrix result; + CreateMatrix(out result); + return result; + } + /// + /// マトリックスã®ç”Ÿæˆ + /// + /// マトリックス + public void CreateMatrix(out Matrix result) + { + Matrix scales; + Matrix move; + Matrix rot; + Matrix temp; + + Matrix.CreateScale(ref Scales, out scales); + Matrix.CreateTranslation(ref Translation, out move); + Matrix.CreateFromQuaternion(Rotation, out rot); + Matrix.Multiply(ref scales, ref rot, out temp); + Matrix.Multiply(ref temp, ref move, out result); + + } + +#if false + /// + /// æ’ç­‰SQTTransformã‚’è¿”ã—ã¾ã™ + /// + public static SQTTransform Identity { get { return new SQTTransform(new Vector3(1, 1, 1), Quaternion.Identity, Vector3.Zero); } } + #region åˆæœŸåŒ– + + + + + + #endregion + + + + /// + /// å§¿å‹¢ã®ç·šå½¢è£œé–“ + /// + /// å§¿å‹¢1 + /// å§¿å‹¢2 + /// 補完係数(0-1) + /// 線形補間ã•れãŸå§¿å‹¢ + /// Quaternionã¯çƒçŠ¶ç·šå½¢è£œé–“ã‚’ä½¿ç”¨ + internal static void Lerp(ref SQTTransform pose1, ref SQTTransform pose2, float amount, out SQTTransform result) + { + Vector3.Lerp(ref pose1.Scales, ref pose2.Scales, amount, out result.Scales); + Vector3.Lerp(ref pose1.Translation, ref pose2.Translation, amount, out result.Translation); + Quaternion.Slerp(ref pose1.Rotation, ref pose2.Rotation, amount, out result.Rotation); + } + +#endif + + + + + } +} \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Vector2.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Vector2.cs new file mode 100644 index 000000000..72f4c7569 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Vector2.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MMDIKBakerLibrary.Misc +{ + struct Vector2 + { + public float X; + public float Y; + public Vector2(float x, float y) + { + X = x; + Y = y; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Vector3.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Vector3.cs new file mode 100644 index 000000000..0206d51d9 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Misc/Vector3.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MMDIKBakerLibrary.Misc +{ + struct Vector3 + { + public decimal X; + public decimal Y; + public decimal Z; + public bool NaN; + public static Vector3 Zero { get { return new Vector3(); } } + public static Vector3 One { get { return new Vector3(1, 1, 1); } } + + public Vector3(decimal x, decimal y, decimal z) + { + X = x; + Y = y; + Z = z; + NaN = false; + } + + public static void Lerp(ref Vector3 value1, ref Vector3 value2, decimal amount, out Vector3 result) + { + result.X = value1.X + (value2.X - value1.X) * amount; + result.Y = value1.Y + (value2.Y - value1.Y) * amount; + result.Z = value1.Z + (value2.Z - value1.Z) * amount; + result.NaN = false; + } + + public decimal Length() + { + return (decimal)Math.Sqrt((double)(X * X + Y * Y + Z * Z)); + } + + public static void Transform(ref Vector3 value, ref Quaternion rotation, out Vector3 result) + { + decimal xx = rotation.X * rotation.X * 2m; + decimal xy = rotation.X * rotation.Y * 2m; + decimal xz = rotation.X * rotation.Z * 2m; + decimal xw = rotation.W * rotation.X * 2m; + decimal yy = rotation.Y * rotation.Y * 2m; + decimal yz = rotation.Y * rotation.Z * 2m; + decimal yw = rotation.W * rotation.Y * 2m; + decimal zz = rotation.Z * rotation.Z * 2m; + decimal zw = rotation.W * rotation.Z * 2m; + result.X = value.X * (1 - yy - zz) + value.Y * (xy - zw) + value.Z * (xz + yw); + result.Y = value.X * (xy + zw) + value.Y * (1 - xx - zz) + value.Z * (yz - xw); + result.Z = value.X * (xz - yw) + value.Y * (yz + xw) + value.Z * (1 - xx - yy); + result.NaN = false; + } + + + + public static Vector3 Normalize(Vector3 value) + { + decimal len2 = value.X * value.X + value.Y * value.Y + value.Z * value.Z; + Vector3 result; + if (len2 == 0) + { + result.X = 0; + result.Y = 0; + result.Z = 0; + result.NaN = true; + return result; + } + else + { + result.X = value.X / (decimal)Math.Sqrt((double)len2); + result.Y = value.Y / (decimal)Math.Sqrt((double)len2); + result.Z = value.Z / (decimal)Math.Sqrt((double)len2); + result.NaN = false; + return result; + } + } + + public static decimal Dot(Vector3 vector1, Vector3 vector2) + { + return vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z; + } + + public static Vector3 Cross(Vector3 vector1, Vector3 vector2) + { + Vector3 result; + result.X = vector1.Y * vector2.Z - vector1.Z * vector2.Y; + result.Y = vector1.Z * vector2.X - vector1.X * vector2.Z; + result.Z = vector1.X * vector2.Y - vector1.Y * vector2.X; + result.NaN = false; + return result; + } + + + + public static void Transform(ref Vector3 position, ref Matrix matrix, out Vector3 result) + { + result.X = position.X * matrix.M11 + position.Y * matrix.M21 + position.Z * matrix.M31 + matrix.M41; + result.Y = position.X * matrix.M12 + position.Y * matrix.M22 + position.Z * matrix.M32 + matrix.M42; + result.Z = position.X * matrix.M13 + position.Y * matrix.M23 + position.Z * matrix.M33 + matrix.M43; + result.NaN = false; + } + + + + public void Normalize() + { + decimal len2 = X * X + Y * Y + Z * Z; + if (len2 == 0) + { + NaN = true; + } + else + { + X /= (decimal)Math.Sqrt((double)len2); + Y /= (decimal)Math.Sqrt((double)len2); + Z /= (decimal)Math.Sqrt((double)len2); + } + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/MMDBone.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/MMDBone.cs new file mode 100644 index 000000000..bdea19e18 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/MMDBone.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MMDIKBakerLibrary.Misc; + +namespace MMDIKBakerLibrary.Model +{ + class MMDBone + { + /// + /// ボーンã®åå‰ + /// + public readonly string Name; + + /// + /// ボーンã®ãƒã‚¤ãƒ³ãƒ‰ãƒãƒ¼ã‚ºè¡Œåˆ— + /// + public readonly SQTTransform BindPose; + /// + /// ボーンã®ãƒã‚¤ãƒ³ãƒ‰ãƒãƒ¼ã‚ºé€†è¡Œåˆ— + /// + /// 変更ã—ãªã„ã“ã¨â€¦â€¦ + public Matrix InverseBindPose; + /// + /// ボーンã®è¦ªã®ãƒœãƒ¼ãƒ³ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹æƒ…å ± + /// + /// 親ãŒç„¡ã„å ´åˆã¯-1 + public readonly int SkeletonHierarchy; + + /// + /// ボーンã®ãƒ­ãƒ¼ã‚«ãƒ«å¤‰æ›è¡Œåˆ— + /// + /// アニメーションå†ç”Ÿæ™‚ã«ã¯ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã«ã‚ˆã‚Šä¸Šæ›¸ãã•れる + public SQTTransform LocalTransform; + + /// + /// ボーンã®ã‚°ãƒ­ãƒ¼ãƒãƒ«å¤‰æ›è¡Œåˆ— + /// + /// 毎フレームã”ã¨ã«LocalTransformã‹ã‚‰è¨ˆç®—ã•れã€ä¸Šæ›¸ãã•れる + public Matrix GlobalTransform; + /// + /// コンストラクタ + /// + /// åå‰ + /// ãƒã‚¤ãƒ³ãƒ‰ãƒãƒ¼ã‚º + /// 逆ãƒã‚¤ãƒ³ãƒ‰ãƒãƒ¼ã‚º + /// è¦ªãƒœãƒ¼ãƒ³ç•ªå· + public MMDBone(string name, SQTTransform bindPose, Matrix inverseBindPose, int skeletonHierarchy) + { + Name = name; + BindPose = bindPose; + InverseBindPose = inverseBindPose; + SkeletonHierarchy = skeletonHierarchy; + LocalTransform = bindPose; + GlobalTransform = Matrix.Identity; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/MMDBoneManager.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/MMDBoneManager.cs new file mode 100644 index 000000000..5029936f6 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/MMDBoneManager.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MMDIKBakerLibrary.Motion; +using MMDIKBakerLibrary.Misc; + +namespace MMDIKBakerLibrary.Model +{ + class MMDBoneManager + { + public IIKSolver IKSolver = new CCDSolver(); + public IIKLimitter IKLimitter = new DefaltIKLimitter(); + private List bones; + private List iks; + private Dictionary ik_dict = new Dictionary(); + Dictionary boneDic; + /// + /// ボーンå–å¾— + /// + /// ãƒœãƒ¼ãƒ³ç•ªå· + /// ボーンオブジェクト + public MMDBone this[int index] { get { return bones[index]; } } + /// + /// ボーンå–å¾— + /// + /// ボーンå + /// ボーンオブジェクト + public MMDBone this[string key] { get { return bones[boneDic[key]]; } } + /// + /// ボーン数 + /// + public int Count { get { return bones.Count; } } + + public MMDBoneManager(List bones, List iks) + { + this.bones = bones; + this.iks = iks; + boneDic = new Dictionary(); + for (int i = 0; i < bones.Count; i++) + { + boneDic.Add(bones[i].Name, i); + } + foreach (MMDBone bone in bones) + { + ik_dict[bone.Name] = false; + } + foreach (MMDIK ik in iks) + { + foreach (MMDBone ikchild in ik.IKChildBones) + { + ik_dict[ikchild.Name] = true; + } + } + } + + public bool IsUnderIK(string boneName) + { + bool result; + if (!ik_dict.TryGetValue(boneName, out result)) + { + return false; + } + return result; + } + /// + /// グローãƒãƒ«ãƒˆãƒ©ãƒ³ã‚¹ãƒ•ã‚©ãƒ¼ãƒ ã®æ›´æ–° + /// + public virtual void CalcGlobalTransform() + { + bones[0].LocalTransform.CreateMatrix(out bones[0].GlobalTransform); + for (int i = 1; i < bones.Count; ++i) + { + int parentBone = bones[i].SkeletonHierarchy; + Matrix local; + bones[i].LocalTransform.CreateMatrix(out local); + if (parentBone > bones.Count) + { + bones[i].GlobalTransform = local; + } + else + { + Matrix.Multiply(ref local, ref bones[parentBone].GlobalTransform, out bones[i].GlobalTransform); + } + } + } + /// + /// IK計算 + /// + public virtual void CalcIK() + { + bool UpdateFlag = false; + for (int i = 0; i < iks.Count; ++i) + { + if (IKSolver.Solve(iks[i], this)) + UpdateFlag = true; + } + if (UpdateFlag) + CalcGlobalTransform(); + } + public void bake(uint frameNo, MMDMotion afterMotion) + { + foreach (KeyValuePair it in ik_dict) + { + if (it.Value && afterMotion.BoneFrames.ContainsKey(it.Key)) + { + Matrix globalTrans = this[it.Key].GlobalTransform; + Matrix parentTrans, invParentTrans; + if (this[it.Key].SkeletonHierarchy >= bones.Count) + { + parentTrans = Matrix.Identity; + } + else + { + parentTrans = this[this[it.Key].SkeletonHierarchy].GlobalTransform; + } + Matrix.Invert(ref parentTrans, out invParentTrans); + Matrix LocalTrans; + Matrix.Multiply(ref globalTrans, ref invParentTrans, out LocalTrans); + Matrix BindPose = this[it.Key].BindPose.CreateMatrix(); + Matrix invBindPose; + Matrix.Invert(ref BindPose, out invBindPose); + Matrix subPose; + Vector3 scale, Location; + Quaternion quaternion; + Matrix.Multiply(ref LocalTrans, ref invBindPose, out subPose); + subPose.Decompose(out scale, out quaternion, out Location); + MMDBoneKeyFrame keyframe = new MMDBoneKeyFrame(); + if (afterMotion.BoneFrames[it.Key].Count == 0 && frameNo > 0) + { + keyframe.FrameNo = 0; + keyframe.BoneName = it.Key; + keyframe.Curve = MathHelper.CreateIdentityCurve(); + keyframe.Location = Location; + keyframe.Quatanion = quaternion; + keyframe.Scales = scale; + afterMotion.BoneFrames[it.Key].Add(keyframe); + keyframe = new MMDBoneKeyFrame(); + } + keyframe.FrameNo = frameNo; + keyframe.BoneName = it.Key; + keyframe.Curve = MathHelper.CreateIdentityCurve(); + keyframe.Location = Location; + keyframe.Quatanion = quaternion; + keyframe.Scales = scale; + afterMotion.BoneFrames[it.Key].Add(keyframe); + } + } + + + + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/MMDIK.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/MMDIK.cs new file mode 100644 index 000000000..3b4485791 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/MMDIK.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MMDIKBakerLibrary.Model +{ + class MMDIK + { + /// + /// 目標ä½ç½®ã¨ãªã‚‹ãƒœãƒ¼ãƒ³ + /// + public MMDBone IKBone { get; internal set; } + /// + /// エフェクタã¨ãªã‚‹ãƒœãƒ¼ãƒ³ + /// + public MMDBone IKTargetBone { get; internal set; } + /// + /// å†å¸°æ¼”算回数 + /// + public readonly UInt16 Iteration; + /// + /// IKã®å½±éŸ¿åº¦ + /// + public readonly float ControlWeight; + /// + /// IK影響下ã®ãƒœãƒ¼ãƒ³ + /// + public List IKChildBones { get; internal set; } + + internal int IKBoneIndex; + internal int IKTargetBoneIndex; + internal List ikChildBoneIndex; + /// + /// コンストラクタ + /// + /// IKボーンã¨ãªã‚‹ãƒœãƒ¼ãƒ³ + /// エフェクタã¨ãªã‚‹ãƒœãƒ¼ãƒ³ + /// å†å¸°æ¼”算回数 + /// IKã®å½±éŸ¿åº¦ + /// IK影響下ã®ãƒœãƒ¼ãƒ³ + public MMDIK(int ikBoneIndex, int iktargetindex, UInt16 iteration, float controlWeight, List ikChildBones) + { + IKBoneIndex = ikBoneIndex; + IKTargetBoneIndex = iktargetindex; + Iteration = iteration; + ControlWeight = controlWeight; + ikChildBoneIndex = ikChildBones; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/ModelConverter.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/ModelConverter.cs new file mode 100644 index 000000000..226ed8408 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Model/ModelConverter.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MMDIKBakerLibrary.Misc; + +namespace MMDIKBakerLibrary.Model +{ + static class ModelConverter + { + public static MMDBoneManager BuildBoneManager(MikuMikuDance.Model.Ver1.MMDModel1 model) + { + List bones; + List iks; + bones = new List(); + iks = new List(); + Matrix[] absPoses = new Matrix[model.Bones.LongLength]; + //å„ボーンã®çµ¶å¯¾åº§æ¨™ã‚’計算 + for (long i = 0; i < model.Bones.LongLength; ++i) + { + Matrix.CreateTranslation((decimal)model.Bones[i].BoneHeadPos[0], + (decimal)model.Bones[i].BoneHeadPos[1], + (decimal)model.Bones[i].BoneHeadPos[2], + out absPoses[i]); + } + for (long i = 0; i < model.Bones.LongLength; ++i) + { + Matrix localMatrix; + if (model.Bones[i].ParentBoneIndex != 0xffff) + { + Matrix parentInv; + Matrix.Invert(ref absPoses[model.Bones[i].ParentBoneIndex], out parentInv); + Matrix.Multiply(ref parentInv, ref absPoses[i], out localMatrix); + } + else + { + localMatrix = absPoses[i]; + } + SQTTransform bindPose = SQTTransform.FromMatrix(localMatrix); + Matrix inverseBindPose; + Matrix.Invert(ref absPoses[i], out inverseBindPose); + bones.Add(new MMDBone(model.Bones[i].BoneName, bindPose, inverseBindPose, model.Bones[i].ParentBoneIndex)); + } + for (long i = 0; i < model.IKs.LongLength; ++i) + { + List ikChildBones = new List(); + foreach (var ikc in model.IKs[i].IKChildBoneIndex) + ikChildBones.Add(ikc); + iks.Add(new MMDIK(model.IKs[i].IKBoneIndex, model.IKs[i].IKTargetBoneIndex, model.IKs[i].Iterations, model.IKs[i].AngleLimit, ikChildBones)); + } + //ボーンインデックス→ボーンオブジェクト化 + IKSetup(iks, bones); + return new MMDBoneManager(bones, iks); + } + /// + /// ボーンインデックス→ボーンオブジェクト化 + /// + public static void IKSetup(List iks, List bones) + { + foreach (var ik in iks) + { + ik.IKBone = bones[ik.IKBoneIndex]; + ik.IKTargetBone = bones[ik.IKTargetBoneIndex]; + List ikchilds = new List(); + foreach (var ikci in ik.ikChildBoneIndex) + ikchilds.Add(bones[ikci]); + ik.IKChildBones = new List(ikchilds); + } + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/AnimationPlayer.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/AnimationPlayer.cs new file mode 100644 index 000000000..0fefea100 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/AnimationPlayer.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MMDIKBakerLibrary.Model; +using MMDIKBakerLibrary.Misc; + +namespace MMDIKBakerLibrary.Motion +{ + class AnimationPlayer + { + private MMDBoneManager boneManager; + private MMDMotionTrack motionTrack; + private Dictionary resultPoses = new Dictionary(); + private List underIKBones = new List(); + Dictionary BindPoses; + public AnimationPlayer(MMDBoneManager boneManager) + { + this.boneManager = boneManager; + BindPoses = new Dictionary(); + for (int i = 0; i < boneManager.Count; ++i) + { + BindPoses.Add(boneManager[i].Name, boneManager[i].BindPose); + } + } + + public void SetMotion(MMDMotion motionData) + { + this.motionTrack = new MMDMotionTrack(motionData); + } + + public bool Update() + { + resultPoses.Clear(); + bool result = motionTrack.Update(); + foreach (KeyValuePair subpose in motionTrack.SubPoses) + { + resultPoses[subpose.Key] = subpose.Value; + SQTTransform bindPose, sub = subpose.Value, local; + if (BindPoses.TryGetValue(subpose.Key, out bindPose)) + { + SQTTransform.Multiply(ref sub, ref bindPose, out local); + boneManager[subpose.Key].LocalTransform = local; + } + } + return result; + } + + + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDBoneKeyFrame.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDBoneKeyFrame.cs new file mode 100644 index 000000000..ec272d006 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDBoneKeyFrame.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Text; +using DWORD = System.UInt32; +using MMDIKBakerLibrary.Misc; + +namespace MMDIKBakerLibrary.Motion +{ + class MMDBoneKeyFrame + { + /// + /// ボーンå + /// + public string BoneName;//[15]; + /// + /// ãƒ•ãƒ¬ãƒ¼ãƒ ç•ªå· + /// + public DWORD FrameNo; + /// + /// スケールベクトル + /// + public Vector3 Scales; + /// + /// ä½ç½®ãƒ™ã‚¯ãƒˆãƒ« + /// + public Vector3 Location; + /// + /// クォータニオン + /// + public Quaternion Quatanion; + + /// + /// 補完用曲線 + /// + /// é †ã«X,Y,Z,回転 + public BezierCurve[] Curve; + + /// + /// 補完 + /// + /// フレーム1 + /// フレーム2 + /// 進行度åˆã„ + /// è£œå®Œçµæžœ + public static void Lerp(MMDBoneKeyFrame frame1, MMDBoneKeyFrame frame2, decimal Progress, out SQTTransform result) + { + decimal ProgX, ProgY, ProgZ, ProgR; + ProgX = (decimal)frame2.Curve[0].Evaluate((float)Progress); + ProgY = (decimal)frame2.Curve[1].Evaluate((float)Progress); + ProgZ = (decimal)frame2.Curve[2].Evaluate((float)Progress); + ProgR = (decimal)frame2.Curve[3].Evaluate((float)Progress); + decimal x, y, z; + Quaternion q; + Vector3 scales; + x = MathHelper.Lerp(frame1.Location.X, frame2.Location.X, ProgX); + y = MathHelper.Lerp(frame1.Location.Y, frame2.Location.Y, ProgY); + z = MathHelper.Lerp(frame1.Location.Z, frame2.Location.Z, ProgZ); + Quaternion.Slerp(ref frame1.Quatanion, ref frame2.Quatanion, ProgR, out q); + //MMDã¯ã‚¹ã‚±ãƒ¼ãƒ«ã®ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã‚’å«ã¾ãªã„ã®ã§ã€ã‚¹ã‚±ãƒ¼ãƒ«ã®ãƒ™ã‚¸ã‚§æ›²ç·šè¨ˆç®—ã¯è¡Œã‚ãªã„ + Vector3.Lerp(ref frame1.Scales, ref frame2.Scales, Progress, out scales); + Vector3 t = new Vector3(x, y, z); + SQTTransform.Create(ref scales, ref q, ref t, out result); + } + /// + /// ã“ã®ãƒ•レームã®SQTトランスフォームをå–å¾— + /// + /// SQLトランスフォーム + public void GetSQTTransform(out SQTTransform result) + { + SQTTransform.Create(ref Scales, ref Quatanion, ref Location, out result); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDFaceKeyFrame.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDFaceKeyFrame.cs new file mode 100644 index 000000000..bfa33e6b0 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDFaceKeyFrame.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MMDIKBakerLibrary.Misc; + +namespace MMDIKBakerLibrary.Motion +{ + class MMDFaceKeyFrame + { + /// + /// 表情å + /// + public string FaceName; + /// + /// ãƒ•ãƒ¬ãƒ¼ãƒ ç•ªå· + /// + public uint FrameNo; + /// + /// 表情é©å¿œå‰²åˆ + /// + public float Rate; + /// + /// 表情ã®è£œå®Œ + /// + /// フレーム1 + /// フレーム2 + /// 進行度åˆã„ + /// 表情é©ç”¨é‡ + public static float Lerp(MMDFaceKeyFrame frame1, MMDFaceKeyFrame frame2, float progress) + { + return MathHelper.Lerp(frame1.Rate, frame2.Rate, progress); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDMotion.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDMotion.cs new file mode 100644 index 000000000..f07166dc8 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDMotion.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MMDIKBakerLibrary.Motion +{ + class MMDMotion + { + /// + /// ボーンモーションデータ + /// + /// ボーンã”ã¨ã«æ™‚系列順 + public Dictionary> BoneFrames; + /// + /// フェイスモーションデータ + /// + /// 表情ã”ã¨ã«æ™‚系列順 + public Dictionary> FaceFrames; + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDMotionTrack.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDMotionTrack.cs new file mode 100644 index 000000000..be0e142f3 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MMDMotionTrack.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MMDIKBakerLibrary.Misc; + +namespace MMDIKBakerLibrary.Motion +{ + class MMDMotionTrack + { + /// + /// デフォルトモーションå†ç”ŸFPS + /// + public const decimal DefaultFPS = 30m; + decimal m_NowFrame = 0; + decimal m_MaxFrame = 0; + //モーションデータ + Dictionary> boneFrames; + //モーションデータã®èª­ã¿å‡ºã—ä½ç½® + Dictionary bonePos = new Dictionary(); + //トラックã‹ã‚‰æŠ½å‡ºã•れãŸãƒœãƒ¼ãƒ³ã®å·®åˆ†ä¸€è¦§ + Dictionary subPoses; + /// + /// モーションå†ç”Ÿç”¨FPS + /// + public decimal FramePerSecond { get; set; } + /// + /// ç¾åœ¨ã®ãƒœãƒ¼ãƒ³å·®åˆ†ä¸€è¦§ + /// + public Dictionary SubPoses { get { return subPoses; } } + + public MMDMotionTrack(MMDMotion motionData) + { + //ボーンã®é…列抜ã出㗠+ boneFrames = motionData.BoneFrames; + //モーションã®FPS=30 + FramePerSecond = DefaultFPS; + //å·®åˆ†ä¸€è¦§ã‚’ä½œæˆ + subPoses = new Dictionary(motionData.BoneFrames.Count); + //ç¾åœ¨ã®å†ç”Ÿä½ç½®ã‚’設定&最大フレーム数ã®ãƒã‚§ãƒƒã‚¯ + foreach (KeyValuePair> it in motionData.BoneFrames) + { + bonePos.Add(it.Key, 0); + foreach (MMDBoneKeyFrame it2 in it.Value) + { + if (it2.FrameNo > m_MaxFrame) + m_MaxFrame = it2.FrameNo; + } + } + } + + //終了ã—ãŸã‚‰falseを返㙠+ public bool Update() + { + bool result = !TimeUpdate(); + SubPoses.Clear(); + //ãƒœãƒ¼ãƒ³ã®æ›´æ–° + foreach (KeyValuePair> frameList in boneFrames) + { + //カーソルä½ç½®ã®æ›´æ–° + int CursorPos = bonePos[frameList.Key]; + for (; CursorPos < frameList.Value.Count && frameList.Value[CursorPos].FrameNo < m_NowFrame; ++CursorPos) ; + for (; CursorPos > 0 && frameList.Value[CursorPos - 1].FrameNo > m_NowFrame; --CursorPos) ; + bonePos[frameList.Key] = CursorPos; + if (CursorPos == frameList.Value.Count) + {//通常å†ç”Ÿæ™‚ã®æœ€çµ‚フレーム + SQTTransform subPose; + frameList.Value[CursorPos - 1].GetSQTTransform(out subPose); + SubPoses.Add(frameList.Key, subPose); + } + else + { + //時間経éŽå–å¾— + decimal Progress = (m_NowFrame - frameList.Value[CursorPos - 1].FrameNo) / (frameList.Value[CursorPos].FrameNo - frameList.Value[CursorPos - 1].FrameNo); + SQTTransform subPose; + MMDBoneKeyFrame pose1 = frameList.Value[CursorPos - 1], pose2 = frameList.Value[CursorPos]; + MMDBoneKeyFrame.Lerp(pose1, pose2, Progress, out subPose); + SubPoses.Add(frameList.Key, subPose); + } + } + return result; + } + private bool TimeUpdate() + { + decimal elapsedSeconds = 1m / 30m; + bool result = false; + m_NowFrame += elapsedSeconds * FramePerSecond; + if (m_NowFrame > m_MaxFrame) + { + result = true; + m_NowFrame = m_MaxFrame; + } + return result; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MotionConverter.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MotionConverter.cs new file mode 100644 index 000000000..fd53176fb --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MotionConverter.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MMDIKBakerLibrary.Misc; + +namespace MMDIKBakerLibrary.Motion +{ + static class MotionConverter + { + internal static MMDMotion Convert(MikuMikuDance.Motion.Motion2.MMDMotion2 input) + { + MMDMotion result = new MMDMotion(); + //ボーンモーションデータã®å¤‰æ› + MMDBoneKeyFrame[] BoneFrames = new MMDBoneKeyFrame[input.Motions.LongLength]; + for (long i = 0; i < input.Motions.LongLength; i++) + { + BoneFrames[i] = new MMDBoneKeyFrame(); + BoneFrames[i].BoneName = input.Motions[i].BoneName; + BoneFrames[i].FrameNo = input.Motions[i].FrameNo; + + BoneFrames[i].Curve = new BezierCurve[4]; + for (int j = 0; j < BoneFrames[i].Curve.Length; j++) + { + BezierCurve curve = new BezierCurve(); + curve.v1 = new Vector2((float)input.Motions[i].Interpolation[0][0][j] / 128f, (float)input.Motions[i].Interpolation[0][1][j] / 128f); + curve.v2 = new Vector2((float)input.Motions[i].Interpolation[0][2][j] / 128f, (float)input.Motions[i].Interpolation[0][3][j] / 128f); + BoneFrames[i].Curve[j] = curve; + } + BoneFrames[i].Scales = new Vector3(1, 1, 1); + BoneFrames[i].Location = new Vector3((decimal)input.Motions[i].Location[0], (decimal)input.Motions[i].Location[1], (decimal)input.Motions[i].Location[2]); + BoneFrames[i].Quatanion = new Quaternion((decimal)input.Motions[i].Quatanion[0], (decimal)input.Motions[i].Quatanion[1], (decimal)input.Motions[i].Quatanion[2], (decimal)input.Motions[i].Quatanion[3]); + BoneFrames[i].Quatanion.Normalize(); + } + result.BoneFrames = MotionHelper.SplitBoneMotion(BoneFrames); + //表情モーションã®å¤‰æ› + MMDFaceKeyFrame[] FaceFrames = new MMDFaceKeyFrame[input.FaceMotions.LongLength]; + for (long i = 0; i < input.FaceMotions.Length; i++) + { + FaceFrames[i] = new MMDFaceKeyFrame(); + FaceFrames[i].Rate = input.FaceMotions[i].Rate; + FaceFrames[i].FaceName = input.FaceMotions[i].FaceName; + FaceFrames[i].FrameNo = input.FaceMotions[i].FrameNo; + float temp = input.FaceMotions[i].FrameNo; + } + result.FaceFrames = MotionHelper.SplitFaceMotion(FaceFrames); + //カメラモーションã¯ç„¡è¦–(使ã‚ã‚“ã®ã§) + //ライトモーションã¯ç„¡è¦–(使ã‚ã‚“ã®ã§) + //変æ›ã—ãŸãƒ‡ãƒ¼ã‚¿ã‚’è¿”å´ + return result; + } + + public static MikuMikuDance.Motion.Motion2.MMDMotion2 Convert(MMDMotion input, string modelName) + { + MikuMikuDance.Motion.Motion2.MMDMotion2 result = new MikuMikuDance.Motion.Motion2.MMDMotion2(); + result.ModelName = modelName; + result.Coordinate = MikuMikuDance.Motion.CoordinateType.RightHandedCoordinate; + //ボーンモーションデータã®å¤‰æ› + MMDBoneKeyFrame[] BoneFrames= MotionHelper.ImplodeBoneMotion(input.BoneFrames); + MikuMikuDance.Motion.Motion2.MotionData[] BoneMotionData = new MikuMikuDance.Motion.Motion2.MotionData[BoneFrames.LongLength]; + for (long i = 0; i < BoneFrames.LongLength; i++) + { + BoneMotionData[i] = new MikuMikuDance.Motion.Motion2.MotionData(); + BoneMotionData[i].BoneName = BoneFrames[i].BoneName; + BoneMotionData[i].FrameNo = BoneFrames[i].FrameNo; + + for (int j = 0; j < BoneFrames[i].Curve.Length; j++) + { + BoneMotionData[i].Interpolation[0][0][j]=(byte)MathHelper.Clamp(BoneFrames[i].Curve[j].v1.X*128f,0,255); + BoneMotionData[i].Interpolation[0][1][j]=(byte)MathHelper.Clamp(BoneFrames[i].Curve[j].v1.Y*128f,0,255); + BoneMotionData[i].Interpolation[0][2][j]=(byte)MathHelper.Clamp(BoneFrames[i].Curve[j].v2.X*128f,0,255); + BoneMotionData[i].Interpolation[0][3][j]=(byte)MathHelper.Clamp(BoneFrames[i].Curve[j].v2.Y*128f,0,255); + } + + BoneMotionData[i].Location[0] = (float)BoneFrames[i].Location.X; + BoneMotionData[i].Location[1] = (float)BoneFrames[i].Location.Y; + BoneMotionData[i].Location[2] = (float)BoneFrames[i].Location.Z; + + BoneFrames[i].Quatanion.Normalize(); + BoneMotionData[i].Quatanion[0] = (float)BoneFrames[i].Quatanion.X; + BoneMotionData[i].Quatanion[1] = (float)BoneFrames[i].Quatanion.Y; + BoneMotionData[i].Quatanion[2] = (float)BoneFrames[i].Quatanion.Z; + BoneMotionData[i].Quatanion[3] = (float)BoneFrames[i].Quatanion.W; + } + result.Motions = BoneMotionData; + //表情モーションã®å¤‰æ› + MMDFaceKeyFrame[] FaceFrames = MotionHelper.ImplodeFaceMotion(input.FaceFrames); + MikuMikuDance.Motion.Motion2.FaceMotionData[] FaceMotionData = new MikuMikuDance.Motion.Motion2.FaceMotionData[FaceFrames.LongLength]; + for (long i = 0; i < FaceFrames.LongLength; i++) + { + FaceMotionData[i] = new MikuMikuDance.Motion.Motion2.FaceMotionData(); + FaceMotionData[i].Rate = FaceFrames[i].Rate; + FaceMotionData[i].FaceName = FaceFrames[i].FaceName; + FaceMotionData[i].FrameNo = FaceFrames[i].FrameNo; + } + result.FaceMotions = FaceMotionData; + //カメラモーションã¯ç„¡è¦–(使ã‚ã‚“ã®ã§) + result.CameraMotions = new MikuMikuDance.Motion.Motion2.CameraMotionData[0]; + //ライトモーションã¯ç„¡è¦–(使ã‚ã‚“ã®ã§) + result.LightMotions = new MikuMikuDance.Motion.Motion2.LightMotionData[0]; + + return result; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MotionHelper.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MotionHelper.cs new file mode 100644 index 000000000..97dccab6c --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Motion/MotionHelper.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MMDIKBakerLibrary.Motion +{ + static class MotionHelper + { + internal static Dictionary> SplitBoneMotion(MMDBoneKeyFrame[] keyframes) + { + Dictionary> result = new Dictionary>(); + foreach (var keyframe in keyframes) + { + if (!result.ContainsKey(keyframe.BoneName)) + result.Add(keyframe.BoneName, new List()); + result[keyframe.BoneName].Add(keyframe); + } + foreach (var boneframes in result) + { + boneframes.Value.Sort((x, y) => (int)((long)x.FrameNo - (long)y.FrameNo)); + } + return result; + } + + internal static Dictionary> SplitFaceMotion(MMDFaceKeyFrame[] keyframes) + { + Dictionary> result = new Dictionary>(); + foreach (var keyframe in keyframes) + { + if (!result.ContainsKey(keyframe.FaceName)) + result.Add(keyframe.FaceName, new List()); + result[keyframe.FaceName].Add(keyframe); + } + foreach (var boneframes in result) + { + boneframes.Value.Sort((x, y) => (int)((long)x.FrameNo - (long)y.FrameNo)); + } + return result; + } + + internal static MMDBoneKeyFrame[] ImplodeBoneMotion(Dictionary> keyframes) + { + List result = new List(); + Dictionary> iterators = new Dictionary>(); + foreach (KeyValuePair> keyframe in keyframes) + { + iterators.Add(keyframe.Key, keyframe.Value.GetEnumerator()); + iterators[keyframe.Key].MoveNext(); + } + List endKeys = new List(); + for (uint frame = 0; iterators.Count > 0; ++frame) + { + foreach (KeyValuePair> it in iterators) + { + if (it.Value.Current.FrameNo <= frame) + { + result.Add(it.Value.Current); + if (!it.Value.MoveNext()) + { + endKeys.Add(it.Key); + } + } + } + foreach (string key in endKeys) + { + iterators.Remove(key); + } + } + return result.ToArray(); + } + + internal static MMDFaceKeyFrame[] ImplodeFaceMotion(Dictionary> keyframes) + { + List result = new List(); + Dictionary> iterators = new Dictionary>(); + foreach (KeyValuePair> keyframe in keyframes) + { + iterators.Add(keyframe.Key, keyframe.Value.GetEnumerator()); + iterators[keyframe.Key].MoveNext(); + } + List endKeys = new List(); + for (uint frame = 0; iterators.Count > 0; ++frame) + { + foreach (KeyValuePair> it in iterators) + { + if (it.Value.Current.FrameNo <= frame) + { + result.Add(it.Value.Current); + if (!it.Value.MoveNext()) + { + endKeys.Add(it.Key); + } + } + } + foreach (string key in endKeys) + { + iterators.Remove(key); + } + } + return result.ToArray(); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Properties/AssemblyInfo.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..6c5b10e0f --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerLibrary/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// アセンブリã«é–¢ã™ã‚‹ä¸€èˆ¬æƒ…å ±ã¯ä»¥ä¸‹ã®å±žæ€§ã‚»ãƒƒãƒˆã‚’ã¨ãŠã—ã¦åˆ¶å¾¡ã•れã¾ã™ã€‚ +// アセンブリã«é–¢é€£ä»˜ã‘られã¦ã„る情報を変更ã™ã‚‹ã«ã¯ã€ +// ã“れらã®å±žæ€§å€¤ã‚’変更ã—ã¦ãã ã•ã„。 +[assembly: AssemblyTitle("MMDBoneBakerLibrary")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MMDBoneBakerLibrary")] +[assembly: AssemblyCopyright("Copyright © 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible ã‚’ false ã«è¨­å®šã™ã‚‹ã¨ã€ãã®åž‹ã¯ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内㧠COM コンãƒãƒ¼ãƒãƒ³ãƒˆã‹ã‚‰ +// å‚ç…§ä¸å¯èƒ½ã«ãªã‚Šã¾ã™ã€‚COM ã‹ã‚‰ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内ã®åž‹ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹å ´åˆã¯ã€ +// ãã®åž‹ã® ComVisible 属性を true ã«è¨­å®šã—ã¦ãã ã•ã„。 +[assembly: ComVisible(false)] + +// 次㮠GUID ã¯ã€ã“ã®ãƒ—ロジェクト㌠COM ã«å…¬é–‹ã•れる場åˆã®ã€typelib ã® ID ã§ã™ +[assembly: Guid("912f8a3c-d5c2-421d-8d85-7be2978d4dcf")] + +// アセンブリã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã¯ã€ä»¥ä¸‹ã® 4 ã¤ã®å€¤ã§æ§‹æˆã•れã¦ã„ã¾ã™: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// ã™ã¹ã¦ã®å€¤ã‚’指定ã™ã‚‹ã‹ã€ä¸‹ã®ã‚ˆã†ã« '*' を使ã£ã¦ãƒ“ルドãŠã‚ˆã³ãƒªãƒ“ジョン番å·ã‚’ +// 既定値ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MMDIKBakerTest")] \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/MatrixTest.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/MatrixTest.cs new file mode 100644 index 000000000..060521184 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/MatrixTest.cs @@ -0,0 +1,177 @@ +using MMDIKBakerLibrary.Misc; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +namespace MMDIKBakerTest +{ + + + /// + ///MatrixTest ã®ãƒ†ã‚¹ãƒˆ クラスã§ã™ã€‚ã™ã¹ã¦ã® + ///MatrixTest å˜ä½“テストをã“ã“ã«å«ã‚ã¾ã™ + /// + [TestClass()] + public class MatrixTest + { + + + private TestContext testContextInstance; + + /// + ///ç¾åœ¨ã®ãƒ†ã‚¹ãƒˆã®å®Ÿè¡Œã«ã¤ã„ã¦ã®æƒ…å ±ãŠã‚ˆã³æ©Ÿèƒ½ã‚’ + ///æä¾›ã™ã‚‹ãƒ†ã‚¹ãƒˆ コンテキストをå–å¾—ã¾ãŸã¯è¨­å®šã—ã¾ã™ã€‚ + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + + #region 追加ã®ãƒ†ã‚¹ãƒˆå±žæ€§ + // + //テストを作æˆã™ã‚‹ã¨ãã«ã€æ¬¡ã®è¿½åŠ å±žæ€§ã‚’ä½¿ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™: + // + //ã‚¯ãƒ©ã‚¹ã®æœ€åˆã®ãƒ†ã‚¹ãƒˆã‚’実行ã™ã‚‹å‰ã«ã‚³ãƒ¼ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€ClassInitialize を使用 + //[ClassInitialize()] + //public static void MyClassInitialize(TestContext testContext) + //{ + //} + // + //クラスã®ã™ã¹ã¦ã®ãƒ†ã‚¹ãƒˆã‚’実行ã—ãŸå¾Œã«ã‚³ãƒ¼ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€ClassCleanup を使用 + //[ClassCleanup()] + //public static void MyClassCleanup() + //{ + //} + // + //å„テストを実行ã™ã‚‹å‰ã«ã‚³ãƒ¼ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€TestInitialize を使用 + //[TestInitialize()] + //public void MyTestInitialize() + //{ + //} + // + //å„テストを実行ã—ãŸå¾Œã«ã‚³ãƒ¼ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€TestCleanup を使用 + //[TestCleanup()] + //public void MyTestCleanup() + //{ + //} + // + #endregion + + + /// + ///Decompose ã®ãƒ†ã‚¹ãƒˆ + /// + [TestMethod()] + public void DecomposeTest() + { + Vector3 scale; + Quaternion rotation; + Vector3 translation; + Matrix target = new Matrix(); + Vector3[] scaleTestPatterns = { Vector3.One, new Vector3(5, 1, 1), new Vector3(1, 5, 1), new Vector3(1, 1, 5), new Vector3(5, 5, 1), new Vector3(5, 1, 5), new Vector3(1, 5, 5), new Vector3(5, 5, 5) }; + Quaternion[] rotationTestPatterns = { Quaternion.Identity, Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 0.72m), Quaternion.CreateFromAxisAngle(new Vector3(0.5m, 0.5m, 0), 0.72m), Quaternion.CreateFromAxisAngle(new Vector3(0, 0.5m, 0.5m), 0.72m) }; + Vector3[] transrationTestPatterns = { Vector3.Zero, Vector3.One, new Vector3(5, 1, 1), new Vector3(1, 5, 1), new Vector3(1, 1, 5), new Vector3(5, 5, 1), new Vector3(5, 1, 5), new Vector3(1, 5, 5), new Vector3(5, 5, 5) }; + + foreach (Vector3 scaleTestPattern in scaleTestPatterns) + { + foreach (Quaternion rotationTestPattern in rotationTestPatterns) + { + foreach (Vector3 transrationTestPattern in transrationTestPatterns) + { + Matrix.Compose(scaleTestPattern, rotationTestPattern, transrationTestPattern, out target); + rotationTestPattern.Normalize(); + target.Decompose(out scale, out rotation, out translation); + Vector3 scaleExpected = MathHelper.Round(scaleTestPattern, 5); + scale = MathHelper.Round(scale, 5); + Quaternion rotationExpected = MathHelper.Round(rotationTestPattern, 5); + rotation = MathHelper.Round(rotation, 5); + Vector3 translationExpected = MathHelper.Round(transrationTestPattern, 5); + translation = MathHelper.Round(translation, 5); + Assert.AreEqual(scaleExpected.X, scale.X); + Assert.AreEqual(scaleExpected.Y, scale.Y); + Assert.AreEqual(scaleExpected.Z, scale.Z); + Assert.AreEqual((double)rotationExpected.X, (double)rotation.X); + Assert.AreEqual(rotationExpected.Y, rotation.Y); + Assert.AreEqual(rotationExpected.Z, rotation.Z); + Assert.AreEqual(rotationExpected.W, rotation.W); + Assert.AreEqual(translationExpected.X, translation.X); + Assert.AreEqual(translationExpected.Y, translation.Y); + Assert.AreEqual(translationExpected.Z, translation.Z); + } + } + } + } + + /// + ///Invert ã®ãƒ†ã‚¹ãƒˆ + /// + [TestMethod()] + public void InvertTest() + { + Matrix matrix; + Matrix result; // TODO: é©åˆ‡ãªå€¤ã«åˆæœŸåŒ–ã—ã¦ãã ã•ã„ + Vector3[] scaleTestPatterns = { Vector3.One, new Vector3(5, 1, 1), new Vector3(1, 5, 1), new Vector3(1, 1, 5), new Vector3(5, 5, 1), new Vector3(5, 1, 5), new Vector3(1, 5, 5), new Vector3(5, 5, 5) }; + Quaternion[] rotationTestPatterns = { Quaternion.Identity, Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 0.72m), Quaternion.CreateFromAxisAngle(new Vector3(0.5m, 0.5m, 0), 0.72m), Quaternion.CreateFromAxisAngle(new Vector3(0, 0.5m, 0.5m), 0.72m) }; + Vector3[] transrationTestPatterns = { Vector3.Zero, Vector3.One, new Vector3(5, 1, 1), new Vector3(1, 5, 1), new Vector3(1, 1, 5), new Vector3(5, 5, 1), new Vector3(5, 1, 5), new Vector3(1, 5, 5), new Vector3(5, 5, 5) }; + + foreach (Vector3 scaleTestPattern in scaleTestPatterns) + { + foreach (Quaternion rotationTestPattern in rotationTestPatterns) + { + foreach (Vector3 transrationTestPattern in transrationTestPatterns) + { + rotationTestPattern.Normalize(); + Matrix.Compose(scaleTestPattern, rotationTestPattern, transrationTestPattern, out matrix); + Matrix temp; + Matrix.Invert(ref matrix, out temp); + Matrix.Invert(ref temp, out result); + matrix = MathHelper.Round(matrix, 5); + result = MathHelper.Round(result, 5); + Assert.IsTrue(Math.Abs(matrix.M11 - result.M11) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M12 - result.M12) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M13 - result.M13) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M14 - result.M14) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M21 - result.M21) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M22 - result.M22) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M23 - result.M23) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M24 - result.M24) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M31 - result.M31) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M32 - result.M32) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M33 - result.M33) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M34 - result.M34) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M41 - result.M41) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M42 - result.M42) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M43 - result.M43) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M44 - result.M44) < 0.001m); + Matrix.Multiply(ref temp, ref matrix, out result); + matrix = Matrix.Identity; + result = MathHelper.Round(result, 5); + Assert.IsTrue(Math.Abs(matrix.M11 - result.M11) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M12 - result.M12) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M13 - result.M13) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M14 - result.M14) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M21 - result.M21) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M22 - result.M22) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M23 - result.M23) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M24 - result.M24) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M31 - result.M31) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M32 - result.M32) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M33 - result.M33) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M34 - result.M34) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M41 - result.M41) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M42 - result.M42) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M43 - result.M43) < 0.001m); + Assert.IsTrue(Math.Abs(matrix.M44 - result.M44) < 0.001m); + + } + } + } + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/Properties/AssemblyInfo.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..fe1e4dba6 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// アセンブリã«é–¢ã™ã‚‹ä¸€èˆ¬æƒ…å ±ã¯ä»¥ä¸‹ã®å±žæ€§ã‚»ãƒƒãƒˆã‚’通ã—ã¦åˆ¶å¾¡ã•れã¾ã™ã€‚ +// アセンブリã«é–¢é€£ä»˜ã‘られã¦ã„る情報を変更ã™ã‚‹ã«ã¯ã€ +// ã“れらã®å±žæ€§å€¤ã‚’変更ã—ã¦ãã ã•ã„。 +[assembly: AssemblyTitle("MMDIKBakerTest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MMDIKBakerTest")] +[assembly: AssemblyCopyright("Copyright © 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible ã‚’ false ã«è¨­å®šã™ã‚‹ã¨ã€ãã®åž‹ã¯ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内㧠COM コンãƒãƒ¼ãƒãƒ³ãƒˆã‹ã‚‰ +// å‚ç…§ã§ããªããªã‚Šã¾ã™ã€‚ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内㧠COM ã‹ã‚‰åž‹ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹å¿…è¦ãŒã‚ã‚‹å ´åˆã¯ã€ +// ãã®åž‹ã® ComVisible 属性を true ã«è¨­å®šã—ã¦ãã ã•ã„。 +[assembly: ComVisible(false)] + +// ã“ã®ãƒ—ロジェクト㌠COM ã«å…¬é–‹ã•れる場åˆã€æ¬¡ã® GUID ãŒã‚¿ã‚¤ãƒ— ライブラリ㮠ID ã«ãªã‚Šã¾ã™ã€‚ +[assembly: Guid("fb3f53b4-55bc-473b-8bb1-c40e079dd827")] + +// アセンブリã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã¯ã€ä»¥ä¸‹ã® 4 ã¤ã®å€¤ã§æ§‹æˆã•れã¦ã„ã¾ã™: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// ã™ã¹ã¦ã®å€¤ã‚’指定ã™ã‚‹ã‹ã€ä»¥ä¸‹ã®ã‚ˆã†ã« '*' を使用ã—ã¦ãƒ“ルド番å·ã¨ãƒªãƒ“ジョン番å·ã‚’ +// 既定値ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/QuaternionTest.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/QuaternionTest.cs new file mode 100644 index 000000000..4efa402bc --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/QuaternionTest.cs @@ -0,0 +1,135 @@ +using MMDIKBakerLibrary.Misc; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +namespace MMDIKBakerTest +{ + + + /// + ///QuaternionTest ã®ãƒ†ã‚¹ãƒˆ クラスã§ã™ã€‚ã™ã¹ã¦ã® + ///QuaternionTest å˜ä½“テストをã“ã“ã«å«ã‚ã¾ã™ + /// + [TestClass()] + public class QuaternionTest + { + + + private TestContext testContextInstance; + + /// + ///ç¾åœ¨ã®ãƒ†ã‚¹ãƒˆã®å®Ÿè¡Œã«ã¤ã„ã¦ã®æƒ…å ±ãŠã‚ˆã³æ©Ÿèƒ½ã‚’ + ///æä¾›ã™ã‚‹ãƒ†ã‚¹ãƒˆ コンテキストをå–å¾—ã¾ãŸã¯è¨­å®šã—ã¾ã™ã€‚ + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + + #region 追加ã®ãƒ†ã‚¹ãƒˆå±žæ€§ + // + //テストを作æˆã™ã‚‹ã¨ãã«ã€æ¬¡ã®è¿½åŠ å±žæ€§ã‚’ä½¿ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™: + // + //ã‚¯ãƒ©ã‚¹ã®æœ€åˆã®ãƒ†ã‚¹ãƒˆã‚’実行ã™ã‚‹å‰ã«ã‚³ãƒ¼ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€ClassInitialize を使用 + //[ClassInitialize()] + //public static void MyClassInitialize(TestContext testContext) + //{ + //} + // + //クラスã®ã™ã¹ã¦ã®ãƒ†ã‚¹ãƒˆã‚’実行ã—ãŸå¾Œã«ã‚³ãƒ¼ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€ClassCleanup を使用 + //[ClassCleanup()] + //public static void MyClassCleanup() + //{ + //} + // + //å„テストを実行ã™ã‚‹å‰ã«ã‚³ãƒ¼ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€TestInitialize を使用 + //[TestInitialize()] + //public void MyTestInitialize() + //{ + //} + // + //å„テストを実行ã—ãŸå¾Œã«ã‚³ãƒ¼ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€TestCleanup を使用 + //[TestCleanup()] + //public void MyTestCleanup() + //{ + //} + // + #endregion + + + /// + ///Slerp ã®ãƒ†ã‚¹ãƒˆ + /// + [TestMethod()] + public void SlerpTest() + { + Quaternion[] QuaternionPatterns = { /*Quaternion.Identity,*/ Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 0.72m), Quaternion.CreateFromAxisAngle(new Vector3(0.5m, 0.5m, 0), 0.72m), Quaternion.CreateFromAxisAngle(new Vector3(0, 0.5m, 0.5m), 0.72m) }; + decimal[] ratePatterns = { 0m, 0.2m, 0.25m, 0.6m, 0.8m, 1m }; + + foreach (Quaternion q1 in QuaternionPatterns) + { + foreach (Quaternion q2 in QuaternionPatterns) + { + foreach (decimal rate in ratePatterns) + { + Quaternion quaternion1 = q1, quaternion2 = q2; + Quaternion result; + quaternion1.Normalize(); + quaternion2.Normalize(); + Quaternion.Slerp(ref quaternion1, ref quaternion2, rate, out result); + Microsoft.Xna.Framework.Quaternion xnaq1 = new Microsoft.Xna.Framework.Quaternion((float)q1.X, (float)q1.Y, (float)q1.Z, (float)q1.W); + Microsoft.Xna.Framework.Quaternion xnaq2 = new Microsoft.Xna.Framework.Quaternion((float)q2.X, (float)q2.Y, (float)q2.Z, (float)q2.W); + Microsoft.Xna.Framework.Quaternion xnaactual; + Microsoft.Xna.Framework.Quaternion.Slerp(ref xnaq1, ref xnaq2, (float)rate, out xnaactual); + Quaternion actual = new Quaternion { X = (decimal)xnaactual.X, Y = (decimal)xnaactual.Y, Z = (decimal)xnaactual.Z, W = (decimal)xnaactual.W }; + actual.Normalize(); + result.Normalize(); + Assert.AreEqual(Math.Abs(actual.X- result.X)<0.01m, true); + Assert.AreEqual(Math.Abs(actual.Y - result.Y) < 0.01m, true); + Assert.AreEqual(Math.Abs(actual.Z- result.Z)<0.01m, true); + Assert.AreEqual(Math.Abs(actual.W- result.W) < 0.01m, true); + } + } + } + } + + /// + ///Multiply ã®ãƒ†ã‚¹ãƒˆ + /// + [TestMethod()] + public void MultiplyTest() + { + Quaternion[] QuaternionPatterns = { Quaternion.Identity, Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 0.72m), Quaternion.CreateFromAxisAngle(new Vector3(0.5m, 0.5m, 0), 0.72m), Quaternion.CreateFromAxisAngle(new Vector3(0, 0.5m, 0.5m), 0.72m) }; + foreach (Quaternion q1 in QuaternionPatterns) + { + foreach (Quaternion q2 in QuaternionPatterns) + { + Quaternion quaternion1 = q1, quaternion2 = q2; + Quaternion result; + quaternion1.Normalize(); + quaternion2.Normalize(); + Quaternion.Multiply(ref quaternion1, ref quaternion2, out result); + Microsoft.Xna.Framework.Quaternion xnaq1 = new Microsoft.Xna.Framework.Quaternion((float)q1.X, (float)q1.Y, (float)q1.Z, (float)q1.W); + Microsoft.Xna.Framework.Quaternion xnaq2 = new Microsoft.Xna.Framework.Quaternion((float)q2.X, (float)q2.Y, (float)q2.Z, (float)q2.W); + Microsoft.Xna.Framework.Quaternion xnaactual; + Microsoft.Xna.Framework.Quaternion.Multiply(ref xnaq1, ref xnaq2, out xnaactual); + Quaternion actual = new Quaternion { X = (decimal)xnaactual.X, Y = (decimal)xnaactual.Y, Z = (decimal)xnaactual.Z, W = (decimal)xnaactual.W }; + actual.Normalize(); + result.Normalize(); + Assert.IsTrue(Math.Abs(actual.X - result.X) < 0.01m); + Assert.IsTrue(Math.Abs(actual.Y - result.Y) < 0.01m); + Assert.IsTrue(Math.Abs(actual.Z - result.Z) < 0.01m); + Assert.IsTrue(Math.Abs(actual.W - result.W) < 0.01m); + } + } + + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/Vector3Test.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/Vector3Test.cs new file mode 100644 index 000000000..ae676f1de --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDIKBakerTest/Vector3Test.cs @@ -0,0 +1,95 @@ +using MMDIKBakerLibrary.Misc; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +namespace MMDIKBakerTest +{ + + + /// + ///Vector3Test ã®ãƒ†ã‚¹ãƒˆ クラスã§ã™ã€‚ã™ã¹ã¦ã® + ///Vector3Test å˜ä½“テストをã“ã“ã«å«ã‚ã¾ã™ + /// + [TestClass()] + public class Vector3Test + { + + + private TestContext testContextInstance; + + /// + ///ç¾åœ¨ã®ãƒ†ã‚¹ãƒˆã®å®Ÿè¡Œã«ã¤ã„ã¦ã®æƒ…å ±ãŠã‚ˆã³æ©Ÿèƒ½ã‚’ + ///æä¾›ã™ã‚‹ãƒ†ã‚¹ãƒˆ コンテキストをå–å¾—ã¾ãŸã¯è¨­å®šã—ã¾ã™ã€‚ + /// + public TestContext TestContext + { + get + { + return testContextInstance; + } + set + { + testContextInstance = value; + } + } + + #region 追加ã®ãƒ†ã‚¹ãƒˆå±žæ€§ + // + //テストを作æˆã™ã‚‹ã¨ãã«ã€æ¬¡ã®è¿½åŠ å±žæ€§ã‚’ä½¿ç”¨ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™: + // + //ã‚¯ãƒ©ã‚¹ã®æœ€åˆã®ãƒ†ã‚¹ãƒˆã‚’実行ã™ã‚‹å‰ã«ã‚³ãƒ¼ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€ClassInitialize を使用 + //[ClassInitialize()] + //public static void MyClassInitialize(TestContext testContext) + //{ + //} + // + //クラスã®ã™ã¹ã¦ã®ãƒ†ã‚¹ãƒˆã‚’実行ã—ãŸå¾Œã«ã‚³ãƒ¼ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€ClassCleanup を使用 + //[ClassCleanup()] + //public static void MyClassCleanup() + //{ + //} + // + //å„テストを実行ã™ã‚‹å‰ã«ã‚³ãƒ¼ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€TestInitialize を使用 + //[TestInitialize()] + //public void MyTestInitialize() + //{ + //} + // + //å„テストを実行ã—ãŸå¾Œã«ã‚³ãƒ¼ãƒ‰ã‚’実行ã™ã‚‹ã«ã¯ã€TestCleanup を使用 + //[TestCleanup()] + //public void MyTestCleanup() + //{ + //} + // + #endregion + + + /// + ///Transform ã®ãƒ†ã‚¹ãƒˆ + /// + [TestMethod()] + public void TransformTest() + { + Quaternion[] rotationTestPatterns = { Quaternion.Identity, Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 0.72m), Quaternion.CreateFromAxisAngle(new Vector3(0.5m, 0.5m, 0), 0.72m), Quaternion.CreateFromAxisAngle(new Vector3(0, 0.5m, 0.5m), 0.72m) }; + Vector3[] transrationTestPatterns = { Vector3.Zero, Vector3.One, new Vector3(5, 1, 1), new Vector3(1, 5, 1), new Vector3(1, 1, 5), new Vector3(5, 5, 1), new Vector3(5, 1, 5), new Vector3(1, 5, 5), new Vector3(5, 5, 5) }; + + foreach (var rot in rotationTestPatterns) + { + foreach (var vec in transrationTestPatterns) + { + Vector3 value = vec, result; + Quaternion rotation = rot; + Vector3.Transform(ref value, ref rotation, out result); + Microsoft.Xna.Framework.Vector3 value2 = new Microsoft.Xna.Framework.Vector3((float)vec.X, (float)vec.Y, (float)vec.Z), actual_xna; + Microsoft.Xna.Framework.Quaternion rotation2 = new Microsoft.Xna.Framework.Quaternion((float)rot.X, (float)rot.Y, (float)rot.Z, (float)rot.W); + Microsoft.Xna.Framework.Vector3.Transform(ref value2, ref rotation2, out actual_xna); + Vector3 acutual = new Vector3((decimal)actual_xna.X, (decimal)actual_xna.Y, (decimal)actual_xna.Z); + Assert.IsTrue(Math.Abs(result.X - acutual.X) < 0.001m); + Assert.IsTrue(Math.Abs(result.Y - acutual.Y) < 0.001m); + Assert.IsTrue(Math.Abs(result.Z - acutual.Z) < 0.001m); + + } + } + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/CoordinateType.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/CoordinateType.cs new file mode 100644 index 000000000..3c4630959 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/CoordinateType.cs @@ -0,0 +1,20 @@ + +namespace MikuMikuDance.Model +{ + /// + /// 座標系を表ã™åˆ—挙体 + /// + public enum CoordinateType + { + /// + /// 左手座標系 + /// + /// MMDã®æ¨™æº–座標系 + LeftHandedCoordinate = 1, + /// + /// 峿‰‹åº§æ¨™ç³» + /// + /// XNAã®æ¨™æº–座標系 + RightHandedCoordinate = -1, + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/MMDModel.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/MMDModel.cs new file mode 100644 index 000000000..086af4927 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/MMDModel.cs @@ -0,0 +1,46 @@ +using System.IO; + +namespace MikuMikuDance.Model +{ + /// + /// MMDモデルを表ã™ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェイス + /// + /// + /// ã“ã®ã‚¯ãƒ©ã‚¹ã‚’継承ã—ã€ã‚ªãƒªã‚¸ãƒŠãƒ«ã®ã‚ªãƒ–ジェクトを作æˆã™ã‚‹å ´åˆã¯å¼•æ•°ãªã—コンストラクタを用æ„ã™ã‚‹ã“㨠+ /// ã¾ãŸã€Read,Write関数をオーãƒãƒ¼ãƒ©ã‚¤ãƒ‰ã™ã‚‹ã“ã¨ã€‚ + /// + public interface MMDModel + { + /// + /// MMDモデルãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå· + /// + float Version { get; } + /// + /// Read関数 + /// + /// ã“ã®é–¢æ•°ã¯ModelManagerã‹ã‚‰å‘¼ã³å‡ºã•れる。呼ã³å‡ºã—時ã«ã¯ãƒžã‚¸ãƒƒã‚¯æ–‡å­—ã¨ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ãŒèª­ã¾ã‚ŒãŸçŠ¶æ…‹ã§æ¸¡ã•れる + /// マジック文字ã¨ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·èª­ã¿è¾¼ã¿æ¸ˆã¿ã®BinaryReader + /// åº§æ¨™ç³»å¤‰æ›æŒ‡å®š + /// スケール + void Read(BinaryReader reader, CoordinateType coordinate, float scale); + /// + /// Write関数 + /// + /// ã“ã®é–¢æ•°ã¯ModelManagerã‹ã‚‰å‘¼ã³å‡ºã•れる。呼ã³å‡ºã—時ã«ã¯ãƒžã‚¸ãƒƒã‚¯æ–‡å­—ã¨ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ãŒæ›¸ã‹ã‚ŒãŸçŠ¶æ…‹ã§æ¸¡ã•れる + /// マジック文字ã¨ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·æ›¸ãè¾¼ã¿æ¸ˆã¿ã®BinaryWriter + /// スケール + void Write(BinaryWriter writer, float scale); + /// + /// ä¿æŒã—ã¦ã„るデータã®åº§æ¨™ç³» + /// + CoordinateType Coordinate { get; } + +#if false + /// + /// スケーリング + /// + /// 拡大å€çއ + void Scale(float ScaleFactor); +#endif + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/ModelManager.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/ModelManager.cs new file mode 100644 index 000000000..51bc8df10 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/ModelManager.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.IO; +using MikuMikuDance.Model.Ver1; + +namespace MikuMikuDance.Model +{ + /// + /// MikuMikuDance(MMD)モデルã®å…¥å‡ºåŠ›ã®ç®¡ç†ã‚’行ã†Factory Class + /// + public static class ModelManager + { + /// + /// ライブラリユーザー拡張用 + /// + /// ã“ã“ã«MMDモデルを継承ã—ãŸã‚¯ãƒ©ã‚¹ã¨ä½¿ç”¨ã™ã‚‹ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã‚’登録ã™ã‚‹ã¨ã€æ—¢å­˜ã‚¯ãƒ©ã‚¹ã®ä»£ã‚りã«ã€ç™»éŒ²ã—ãŸã‚¯ãƒ©ã‚¹ãŒä½¿ç”¨ã•れる + public static readonly Dictionary OriginalObjects = new Dictionary(); + /// + /// ファイルã‹ã‚‰MMDモデルを読ã¿è¾¼ã‚€ + /// + /// MMDモデルファイル + /// 変æ›å…ˆåº§æ¨™ç³» + /// スケーリング値 + /// MMDモデルオブジェクト + /// MMDã®åº§æ¨™ç³»ã¯å³æ‰‹åº§æ¨™ç³»ã§ã™ + public static MMDModel Read(string filename, CoordinateType coordinate, float scale=1f) + { + //フルパスå–å¾— + filename = Path.GetFullPath(filename); + //ファイルãƒã‚§ãƒƒã‚¯ + if (!File.Exists(filename)) + throw new FileNotFoundException("MMDモデルファイル:" + filename + "ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"); + //戻り値用変数 + MMDModel result = null; + //ファイルリーダー + using (FileStream fs = new FileStream(filename, FileMode.Open)) + { + BinaryReader reader = new BinaryReader(fs); + //マジック文字列 + string magic = MMDModel1.encoder.GetString(reader.ReadBytes(3)); + if (magic != "Pmd") + throw new FileLoadException("MMDモデルファイルã§ã¯ã‚りã¾ã›ã‚“"); + //ãƒãƒ¼ã‚¸ãƒ§ãƒ³ + float version = BitConverter.ToSingle(reader.ReadBytes(4), 0); + if (OriginalObjects.ContainsKey(version) && + OriginalObjects[version].BaseType == typeof(MMDModel)) + {//ã“ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã§ä½¿ç”¨ã—ã€åˆ©ç”¨å¯èƒ½åž‹ + result = (MMDModel)OriginalObjects[version].InvokeMember(null, System.Reflection.BindingFlags.CreateInstance, null, null, null); + } + else + { + if (version == 1.0) + result = new MMDModel1(); + else + throw new FileLoadException("version=" + version.ToString() + "モデルã¯å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“"); + } + result.Read(reader, coordinate, scale); + if (fs.Length != fs.Position) + Console.WriteLine("警告:ファイル末尾以é™ã«ä¸æ˜Žãƒ‡ãƒ¼ã‚¿?"); + fs.Close(); + } + return result; + } + /// + /// ファイルã«MMDモデルを書ãã ã™ + /// + /// 書ãã ã™ãƒ•ァイルå + /// モデルオブジェクト + /// スケーリング値 + public static void Write(string filename, MMDModel model, float scale = 1f) + { + //フルパスå–å¾— + filename = Path.GetFullPath(filename); + //ファイルリーダー + using (FileStream fs = new FileStream(filename, FileMode.Create)) + { + BinaryWriter writer = new BinaryWriter(fs); + + //マジック文字列 + writer.Write(MMDModel1.encoder.GetBytes("Pmd")); + //ãƒãƒ¼ã‚¸ãƒ§ãƒ³ + writer.Write(model.Version); + //ä¸­èº«ã®æ›¸ãã ã— + try + { + model.Write(writer, scale); + } + catch (NullReferenceException e) + { + throw new ArgumentNullException("modelã®ä¸­ã®å¤‰æ•°ãŒnull", e); + } + fs.Close(); + } + } + /// + /// ファイルã‹ã‚‰MMDモデルを読ã¿è¾¼ã‚€ + /// + /// MMDモデルファイル + /// MMDモデルオブジェクト + /// MMDã®åº§æ¨™ç³»ã¯å³æ‰‹åº§æ¨™ç³»ã§ã™ + public static MMDModel Read(string filename) + { + return Read(filename, CoordinateType.LeftHandedCoordinate); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Properties/AssemblyInfo.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..5e98eec66 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// アセンブリã«é–¢ã™ã‚‹ä¸€èˆ¬æƒ…å ±ã¯ä»¥ä¸‹ã®å±žæ€§ã‚»ãƒƒãƒˆã‚’ã¨ãŠã—ã¦åˆ¶å¾¡ã•れã¾ã™ã€‚ +// アセンブリã«é–¢é€£ä»˜ã‘られã¦ã„る情報を変更ã™ã‚‹ã«ã¯ã€ +// ã“れらã®å±žæ€§å€¤ã‚’変更ã—ã¦ãã ã•ã„。 +[assembly: AssemblyTitle("MMDModelLibrary")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MMDModelLibrary")] +[assembly: AssemblyCopyright("Copyright © 2011 Wilfrem")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible ã‚’ false ã«è¨­å®šã™ã‚‹ã¨ã€ãã®åž‹ã¯ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内㧠COM コンãƒãƒ¼ãƒãƒ³ãƒˆã‹ã‚‰ +// å‚ç…§ä¸å¯èƒ½ã«ãªã‚Šã¾ã™ã€‚COM ã‹ã‚‰ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内ã®åž‹ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹å ´åˆã¯ã€ +// ãã®åž‹ã® ComVisible 属性を true ã«è¨­å®šã—ã¦ãã ã•ã„。 +[assembly: ComVisible(false)] + +// 次㮠GUID ã¯ã€ã“ã®ãƒ—ロジェクト㌠COM ã«å…¬é–‹ã•れる場åˆã®ã€typelib ã® ID ã§ã™ +[assembly: Guid("cff3de6f-3e61-4425-869b-3080f2bc37e5")] + +// アセンブリã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã¯ã€ä»¥ä¸‹ã® 4 ã¤ã®å€¤ã§æ§‹æˆã•れã¦ã„ã¾ã™: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// ã™ã¹ã¦ã®å€¤ã‚’指定ã™ã‚‹ã‹ã€ä¸‹ã®ã‚ˆã†ã« '*' を使ã£ã¦ãƒ“ルドãŠã‚ˆã³ãƒªãƒ“ジョン番å·ã‚’ +// 既定値ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2.0.0.0")] +[assembly: AssemblyFileVersion("2.0.0.0")] diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/MMDModel1.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/MMDModel1.cs new file mode 100644 index 000000000..a3107e89b --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/MMDModel1.cs @@ -0,0 +1,530 @@ +using System; +using System.IO; +using System.Text; +using DWORD = System.UInt32; +using WORD = System.UInt16; + +namespace MikuMikuDance.Model.Ver1 +{ + /// + /// MMDã®ãƒ¢ãƒ‡ãƒ«ver1.0を表ã™ã‚¯ãƒ©ã‚¹ + /// + public class MMDModel1 : MMDModel + { + //members and properties... + /// + /// Version番å·ã€‚MMDModelã‹ã‚‰ç¶™æ‰¿ã•れã¾ã™ + /// + public float Version + { + get { return 1.0f; } + } + /// + /// ヘッダ情報 + /// + public ModelHeader Header { get; protected set; } + /// + /// 頂点リスト + /// + public ModelVertex[] Vertexes { get; set; } + /// + /// é¢ãƒªã‚¹ãƒˆ + /// + public WORD[] FaceVertexes { get; set; } + /// + /// æè³ªãƒªã‚¹ãƒˆ + /// + public ModelMaterial[] Materials { get; set; } + /// + /// ボーンリスト + /// + public ModelBone[] Bones { get; set; } + /// + /// IKボーンリスト + /// + public ModelIK[] IKs { get; set; } + /// + /// 表情リスト + /// + public ModelSkin[] Skins { get; set; }//表情リスト + /// + /// 表情枠用ã®è¡¨æƒ…番å·ãƒªã‚¹ãƒˆ + /// + public WORD[] SkinIndex { get; set; } + /// + /// ãƒœãƒ¼ãƒ³æž ç”¨ã®æž åリスト + /// + public ModelBoneDispName[] BoneDispNames { get; set; }//ボーン枠用枠åリスト + /// + /// ボーン枠用表示リスト + /// + public ModelBoneDisp[] BoneDisps { get; set; }//ボーン枠用表示リスト + /// + /// æ‹¡å¼µ1(英語拡張)使用フラグ + /// + public bool Expantion { get; set; } + /// + /// æ‹¡å¼µ2(トゥーン指定)使用フラグ + /// + /// æ‹¡å¼µ1ãŒtrueã§ãªã„ã¨å‡ºåŠ›æ™‚ãƒˆã‚¥ãƒ¼ãƒ³æŒ‡å®šã¯æ›¸ãã ã•れãªã„ + public bool ToonExpantion { get; set; } + /// + /// トゥーンテクスãƒãƒ£ãƒªã‚¹ãƒˆ(æ‹¡å¼µ) + /// + public string[] ToonFileNames { get; protected set; }//トゥーンテクスãƒãƒ£ãƒªã‚¹ãƒˆ(æ‹¡å¼µ)ã€10個固定 + const int NumToonFileName = 10; + + /// + /// æ‹¡å¼µ3(ç‰©ç†æ¼”ç®—æ‹¡å¼µ)使用フラグ + /// + /// æ‹¡å¼µ1,2ãŒtrueã§ãªã„ã¨ç‰©ç†æ¼”ç®—é …ç›®ã¯æ›¸ãã ã•れãªã„ + public bool PhysicsExpantion { get; set; } + /// + /// ç‰©ç†æ¼”算用ã®å‰›ä½“リスト(æ‹¡å¼µ) + /// + public ModelRigidBody[] RigidBodies { get; set; }//ç‰©ç†æ¼”ç®—ã€å‰›ä½“リスト(æ‹¡å¼µ) + /// + /// ç‰©ç†æ¼”算用ã®ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆãƒªã‚¹ãƒˆ(æ‹¡å¼µ) + /// + public ModelJoint[] Joints { get; set; }//ç‰©ç†æ¼”ç®—ã€ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆãƒªã‚¹ãƒˆ(æ‹¡å¼µ) + /// + /// ä¿æŒã—ã¦ã„るデータã®åº§æ¨™ã + /// + public CoordinateType Coordinate { get; protected set; } + //座標変æ›ç”¨ãƒ˜ãƒ«ãƒ‘関数 + float CoordZ { get { return (float)Coordinate; } } + + //constructor + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public MMDModel1() + { + Header = new ModelHeader(); + Vertexes = null; + Expantion = false; + ToonExpantion = false; + PhysicsExpantion = false; + ToonFileNames = new string[NumToonFileName]; + Coordinate = CoordinateType.LeftHandedCoordinate; + } + + //methods... + /// + /// Read関数 + /// + /// ã“ã®é–¢æ•°ã¯ModelManagerã‹ã‚‰å‘¼ã³å‡ºã•れる。呼ã³å‡ºã—時ã«ã¯ãƒžã‚¸ãƒƒã‚¯æ–‡å­—ã¨ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ãŒèª­ã¾ã‚ŒãŸçŠ¶æ…‹ã§æ¸¡ã•れる + /// マジック文字ã¨ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·èª­ã¿è¾¼ã¿æ¸ˆã¿ã®BinaryReader + /// 変æ›å…ˆåº§æ¨™ç³» + /// スケーリング値 + public void Read(BinaryReader reader, CoordinateType coordinate, float scale) + { + Coordinate = coordinate;//座標系セット + //通常ヘッダ読ã¿è¾¼ã¿(英語ヘッダã¯BoneIndexã®å¾Œ(ミクãªã‚‰0x00071167)ã«æ›¸ã‹ã‚Œã¦ã„ã‚‹ + Header.Read(reader); + //頂点リスト読ã¿è¾¼ã¿ + DWORD num_vertex = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + Vertexes = new ModelVertex[num_vertex]; + for (DWORD i = 0; i < num_vertex; i++) + { + Vertexes[i] = new ModelVertex(); + Vertexes[i].Read(reader, CoordZ, scale); + } + //é¢ãƒªã‚¹ãƒˆèª­ã¿è¾¼ã¿ + DWORD face_vert_count = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + FaceVertexes = new WORD[face_vert_count]; + for (DWORD i = 0; i < face_vert_count; i++) + { + FaceVertexes[i] = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + } + //æè³ªãƒªã‚¹ãƒˆèª­ã¿è¾¼ã¿ + DWORD material_count = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + Materials = new ModelMaterial[material_count]; + for (DWORD i = 0; i < material_count; i++) + { + Materials[i] = new ModelMaterial(); + Materials[i].Read(reader); + } + //ボーンリスト読ã¿è¾¼ã¿ + WORD bone_count = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + Bones = new ModelBone[bone_count]; + for (WORD i = 0; i < bone_count; i++) + { + Bones[i] = new ModelBone(); + Bones[i].Read(reader, CoordZ, scale); + } + //IKリスト読ã¿è¾¼ã¿ + WORD ik_count = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + IKs = new ModelIK[ik_count]; + for (WORD i = 0; i < ik_count; i++) + { + IKs[i] = new ModelIK(); + IKs[i].Read(reader); + } + //表情リスト読ã¿è¾¼ã¿ + WORD skin_count = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + Skins = new ModelSkin[skin_count]; + for (WORD i = 0; i < skin_count; i++) + { + Skins[i] = new ModelSkin(); + Skins[i].Read(reader, CoordZ, scale); + } + //表情枠用表示リスト + byte skin_disp_count = reader.ReadByte(); + SkinIndex = new WORD[skin_disp_count]; + for (byte i = 0; i < SkinIndex.Length; i++) + SkinIndex[i] = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + //ボーン枠用枠åリスト + byte bone_disp_name_count = reader.ReadByte(); + BoneDispNames = new ModelBoneDispName[bone_disp_name_count]; + for (byte i = 0; i < BoneDispNames.Length; i++) + { + BoneDispNames[i] = new ModelBoneDispName(); + BoneDispNames[i].Read(reader); + } + //ボーン枠用表示リスト + DWORD bone_disp_count = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + BoneDisps = new ModelBoneDisp[bone_disp_count]; + for (DWORD i = 0; i < BoneDisps.Length; i++) + { + BoneDisps[i] = new ModelBoneDisp(); + BoneDisps[i].Read(reader); + } + //英語表記フラグ + Expantion = (reader.ReadByte() != 0); + if (Expantion) + { + //英語ヘッダ + Header.ReadExpantion(reader); + //ボーンリスト(英語) + for (WORD i = 0; i < bone_count; i++) + { + Bones[i].ReadExpantion(reader); + } + //スキンリスト(英語) + for (WORD i = 0; i < skin_count; i++) + { + if (Skins[i].SkinType != 0)//baseã®ã‚¹ã‚­ãƒ³ã«ã¯è‹±åç„¡ã— + Skins[i].ReadExpantion(reader); + } + //ボーン枠用枠åリスト(英語) + for (byte i = 0; i < BoneDispNames.Length; i++) + { + BoneDispNames[i].ReadExpantion(reader); + } + } + if (reader.BaseStream.Position >= reader.BaseStream.Length) + ToonExpantion = false; + else + { + ToonExpantion = true; + //トゥーンテクスãƒãƒ£ãƒªã‚¹ãƒˆ + ToonFileNames = new string[NumToonFileName];//10個固定 + for (int i = 0; i < ToonFileNames.Length; i++) + { + ToonFileNames[i] = GetString(reader.ReadBytes(100)); + } + } + if (reader.BaseStream.Position >= reader.BaseStream.Length) + PhysicsExpantion = false; + else + { + PhysicsExpantion = true; + //剛体リスト + DWORD rididbody_count = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + RigidBodies = new ModelRigidBody[rididbody_count]; + for (DWORD i = 0; i < rididbody_count; i++) + { + RigidBodies[i] = new ModelRigidBody(); + RigidBodies[i].ReadExpantion(reader, CoordZ, scale); + } + //ジョイントリスト + DWORD joint_count = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + Joints = new ModelJoint[joint_count]; + for (DWORD i = 0; i < joint_count; i++) + { + Joints[i] = new ModelJoint(); + Joints[i].ReadExpantion(reader, CoordZ, scale); + } + } + + } + /// + /// Write関数 + /// + /// ã“ã®é–¢æ•°ã¯ModelManagerã‹ã‚‰å‘¼ã³å‡ºã•れる。呼ã³å‡ºã—時ã«ã¯ãƒžã‚¸ãƒƒã‚¯æ–‡å­—ã¨ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ãŒæ›¸ã‹ã‚ŒãŸçŠ¶æ…‹ã§æ¸¡ã•れる + /// マジック文字ã¨ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·æ›¸ãè¾¼ã¿æ¸ˆã¿ã®BinaryWriter + /// スケール + public void Write(BinaryWriter writer, float scale) + { + //通常ヘッダ書ãã ã—(英語ヘッダã¯BoneIndexã®å¾Œ(ミクãªã‚‰0x00071167)ã«æ›¸ã‹ã‚Œã¦ã„ã‚‹ + Header.Write(writer); + //頂点リスト書ãã ã— + if (Vertexes == null) + writer.Write((DWORD)0); + else + { + writer.Write((DWORD)Vertexes.LongLength); + for (DWORD i = 0; i < Vertexes.LongLength; i++) + { + if (Vertexes[i] == null) + throw new ArgumentNullException("Vertexes[" + i.ToString() + "]ãŒnull"); + Vertexes[i].Write(writer, CoordZ, scale); + } + } + //é¢ãƒªã‚¹ãƒˆæ›¸ãã ã— + if (FaceVertexes == null) + writer.Write((DWORD)0); + else + { + writer.Write((DWORD)FaceVertexes.LongLength); + for (DWORD i = 0; i < FaceVertexes.LongLength; i++) + { + writer.Write(FaceVertexes[i]); + } + } + //æè³ªãƒªã‚¹ãƒˆæ›¸ãã ã— + if (Materials == null) + writer.Write((DWORD)0); + else + { + writer.Write((DWORD)Materials.LongLength); + for (DWORD i = 0; i < Materials.LongLength; i++) + { + if (Materials[i] == null) + throw new ArgumentNullException("Materials[" + i.ToString() + "]ãŒnull"); + Materials[i].Write(writer); + } + } + //ボーンリスト書ãã ã— + if (Bones == null) + writer.Write((WORD)0); + else + { + writer.Write((WORD)Bones.Length); + for (WORD i = 0; i < Bones.Length; i++) + { + if (Bones[i] == null) + throw new ArgumentNullException("Bones[" + i.ToString() + "]ãŒnull"); + Bones[i].Write(writer, CoordZ,scale); + } + } + //IKリスト書ãã ã— + if (IKs == null) + writer.Write((WORD)0); + else + { + writer.Write((WORD)IKs.Length); + for (WORD i = 0; i < IKs.Length; i++) + { + if (IKs[i] == null) + throw new ArgumentNullException("IKs[" + i.ToString() + "]ãŒnull"); + IKs[i].Write(writer); + } + } + //表情リスト書ãã ã— + if (Skins == null) + writer.Write((WORD)0); + else + { + writer.Write((WORD)Skins.Length); + for (WORD i = 0; i < Skins.Length; i++) + { + if (Skins[i] == null) + throw new ArgumentNullException("Skins[" + i.ToString() + "]ãŒnull"); + Skins[i].Write(writer, CoordZ,scale); + } + } + //表情枠用表示リスト書ãã ã— + if (SkinIndex == null) + writer.Write((byte)0); + else + { + writer.Write((byte)SkinIndex.Length); + + for (byte i = 0; i < SkinIndex.Length; i++) + { + writer.Write(SkinIndex[i]); + } + } + //ボーン枠用枠åリスト + if (BoneDispNames == null) + writer.Write((byte)0); + else + { + writer.Write((byte)BoneDispNames.Length); + for (byte i = 0; i < BoneDispNames.Length; i++) + { + if(BoneDispNames[i]==null) + throw new ArgumentNullException("BoneDispNames[" + i.ToString() + "]ãŒnull"); + BoneDispNames[i].Write(writer); + } + } + //ボーン枠用表示リスト + if (BoneDisps == null) + writer.Write((DWORD)0); + else + { + writer.Write((DWORD)BoneDisps.Length); + for (DWORD i = 0; i < BoneDisps.Length; i++) + { + if (BoneDisps[i] == null) + throw new ArgumentNullException("BoneDisps[" + i.ToString() + "]ãŒnull"); + BoneDisps[i].Write(writer); + } + } + //英語表記フラグ + writer.Write((byte)(Expantion ? 1 : 0)); + if (Expantion) + { + //英語ヘッダ + Header.WriteExpantion(writer); + //ボーンリスト(英語) + if (Bones != null) + { + for (WORD i = 0; i < Bones.Length; i++) + { + Bones[i].WriteExpantion(writer); + } + } + //スキンリスト(英語) + if (Skins != null) + { + for (WORD i = 0; i < Skins.Length; i++) + { + if (Skins[i].SkinType != 0)//baseã®ã‚¹ã‚­ãƒ³ã«ã¯è‹±åç„¡ã— + Skins[i].WriteExpantion(writer); + } + } + //ボーン枠用枠åリスト(英語) + if (BoneDispNames != null) + { + for (byte i = 0; i < BoneDispNames.Length; i++) + { + BoneDispNames[i].WriteExpantion(writer); + } + } + } + if (ToonExpantion) + { + //トゥーンテクスãƒãƒ£ãƒªã‚¹ãƒˆ + for (int i = 0; i < ToonFileNames.Length; i++) + { + writer.Write(GetBytes(ToonFileNames[i], 100)); + } + if (PhysicsExpantion) + { + //剛体リスト + if (RigidBodies == null) + writer.Write((DWORD)0); + else + { + writer.Write((DWORD)RigidBodies.LongLength); + for (long i = 0; i < RigidBodies.LongLength; i++) + { + if (RigidBodies[i] == null) + throw new ArgumentNullException("RididBodies[" + i.ToString() + "]ãŒnull"); + RigidBodies[i].WriteExpantion(writer, CoordZ,scale); + } + } + //ジョイントリスト + if (Joints == null) + writer.Write((DWORD)0); + else + { + writer.Write((DWORD)Joints.LongLength); + for (long i = 0; i < Joints.LongLength; i++) + { + if (Joints[i] == null) + throw new ArgumentNullException("Joints[" + i.ToString() + "]ãŒnull"); + Joints[i].WriteExpantion(writer, CoordZ,scale); + } + } + } + } + + } +#if false + /// + /// スケーリング + /// + /// 拡大å€çއ + public void Scale(float ScaleFactor) + { + if(ScaleFactor<=0) + throw new ApplicationException("ScaleFactorã¯æ­£ã®å®Ÿæ•°ã§ã‚ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚"); + //頂点 + for (long i = 0; i < Vertexes.LongLength; i++) + { + for (int j = 0; j < Vertexes[i].Pos.Length; j++) + Vertexes[i].Pos[j] = Vertexes[i].Pos[j] * ScaleFactor; + } + //ボーン + for (long i = 0; i < Bones.LongLength; i++) + { + for (int j = 0; j < Bones[i].BoneHeadPos.Length; j++) + Bones[i].BoneHeadPos[j] = Vertexes[i].Pos[j] * ScaleFactor; + } + //表情 + for (long i = 0; i < Skins.LongLength; i++) + { + for (long j = 0; j < Skins[i].SkinVertDatas.LongLength; j++) + { + for (int k = 0; k < Skins[i].SkinVertDatas[j].SkinVertPos.Length; k++) + Skins[i].SkinVertDatas[j].SkinVertPos[k] = Skins[i].SkinVertDatas[j].SkinVertPos[k] * ScaleFactor; + } + } + if (PhysicsExpantion) + { + //剛体 + for (long i = 0; i < RigidBodies.LongLength; i++) + { + for (int j = 0; j < RigidBodies[i].Position.Length; j++) + RigidBodies[i].Position[j] = RigidBodies[i].Position[j] * ScaleFactor; + } + //ジョイント + for (long i = 0; i < Joints.LongLength; i++) + { + for (int j = 0; j < Joints[i].ConstrainPosition1.Length; j++) + { + Joints[i].ConstrainPosition1[j] = Joints[i].ConstrainPosition1[j] * ScaleFactor; + Joints[i].ConstrainPosition2[j] = Joints[i].ConstrainPosition2[j] * ScaleFactor; + Joints[i].Position[j] = Joints[i].Position[j] * ScaleFactor; + Joints[i].SpringPosition[j] = Joints[i].SpringPosition[j] * ScaleFactor; + } + } + } + } +#endif + //internal statics... + internal static Encoding encoder = Encoding.GetEncoding("shift-jis"); + internal static string GetString(byte[] bytes) + { + int i; + for (i = 0; i < bytes.Length; i++) + if (bytes[i] == 0) + break; + if (i < bytes.Length) + return encoder.GetString(bytes, 0, i); + return encoder.GetString(bytes); + } + internal static byte[] GetBytes(string input, long size) + { + byte[] result = new byte[size]; + for (long i = 0; i < size; i++) + result[i] = 0; + if (input == "") + return result; + byte[] strs = encoder.GetBytes(input); + for (long i = 0; i < strs.LongLength; i++) + if (i < result.LongLength) + result[i] = strs[i]; + if (result.LongLength <= strs.LongLength) + return result; + result[strs.LongLength] = 0; + for (long i = strs.LongLength + 1; i < result.Length; i++) + result[i] = 0xFD;//何故ã‹ã“ã‚ŒãŒæŒ¿å…¥ã•れã¦ã„ã‚‹ã®ã§ã“れを挿入 + return result; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelBone.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelBone.cs new file mode 100644 index 000000000..542517c3e --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelBone.cs @@ -0,0 +1,89 @@ +using System; +using System.IO; +using WORD = System.UInt16; + +namespace MikuMikuDance.Model.Ver1 +{ + /// + /// ボーン + /// + public class ModelBone + { + /// + /// ボーンå + /// + public string BoneName { get; set; } //20byte分char ボーンå + /// + /// è¦ªãƒœãƒ¼ãƒ³ç•ªå· + /// + /// ç„¡ã„å ´åˆã¯0xFFFFを代入 + public WORD ParentBoneIndex { get; set; } // 親ボーン番å·(ãªã„å ´åˆã¯0xFFFF) + /// + /// tailä½ç½®ã®ãƒœãƒ¼ãƒ³ç•ªå· + /// + /// ãƒã‚§ãƒ¼ãƒ³æœ«ç«¯ã®å ´åˆã¯0xFFFF。 親:å­ã¯1:多ãªã®ã§ã€ä¸»ã«ä½ç½®æ±ºã‚用 + public WORD TailPosBoneIndex { get; set; } // tailä½ç½®ã®ãƒœãƒ¼ãƒ³ç•ªå·(ãƒã‚§ãƒ¼ãƒ³æœ«ç«¯ã®å ´åˆã¯0xFFFF) // 親:å­ã¯1:多ãªã®ã§ã€ä¸»ã«ä½ç½®æ±ºã‚用 + /// + /// ボーンã®ç¨®é¡ž + /// + /// 0:回転 1:回転ã¨ç§»å‹• 2:IK 3:䏿˜Ž 4:IK影響下 5:回転影響下 6:IK接続先 7:éžè¡¨ç¤º 8:æ»ã‚Š 9:回転é‹å‹• + public byte BoneType { get; set; } // ボーンã®ç¨®é¡ž + /// + /// IKãƒœãƒ¼ãƒ³ç•ªå· + /// + /// 影響IKボーン。ãªã„å ´åˆã¯0 + public WORD IKParentBoneIndex { get; set; } // IKボーン番å·(影響IKボーン。ãªã„å ´åˆã¯0) + /// + /// ボーンã®ãƒ˜ãƒƒãƒ‰ã®ä½ç½®(x,y,z) + /// + public float[] BoneHeadPos { get; private set; } // x, y, z // ボーンã®ãƒ˜ãƒƒãƒ‰ã®ä½ç½® + /// + /// ボーンå(è‹±èªžã€æ‹¡å¼µ) + /// + public string BoneNameEnglish { get; set; }////20byte分char ボーンå(è‹±èªžã€æ‹¡å¼µ(ç„¡ã„å ´åˆã¯null)) + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public ModelBone() + { + BoneHeadPos = new float[3]; + } + internal void Read(BinaryReader reader, float CoordZ, float scale) + { + BoneHeadPos = new float[3]; + BoneName = MMDModel1.GetString(reader.ReadBytes(20)); + ParentBoneIndex = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + TailPosBoneIndex = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + BoneType = reader.ReadByte(); + IKParentBoneIndex = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + for (int i = 0; i < BoneHeadPos.Length; i++) + BoneHeadPos[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0) * scale; + //è‹±åæ‹¡å¼µã¯Readã§ã¯nullã«ã™ã‚‹(ã‚ã‚‹ãªã‚‰ReadEngilishã§ä¸Šæ›¸ãã•れる) + BoneNameEnglish = null; + BoneHeadPos[2] = BoneHeadPos[2] * CoordZ; + } + + //è‹±åæ‹¡å¼µåˆ†èª­ã¿è¾¼ã¿ + internal void ReadExpantion(BinaryReader reader) + { + BoneNameEnglish = MMDModel1.GetString(reader.ReadBytes(20)); + } + + internal void Write(BinaryWriter writer, float CoordZ, float scale) + { + BoneHeadPos[2] = BoneHeadPos[2] * CoordZ * scale; + writer.Write(MMDModel1.GetBytes(BoneName, 20)); + writer.Write(ParentBoneIndex); + writer.Write(TailPosBoneIndex); + writer.Write(BoneType); + writer.Write(IKParentBoneIndex); + for (int i = 0; i < BoneHeadPos.Length; i++) + writer.Write(BoneHeadPos[i]); + } + + internal void WriteExpantion(BinaryWriter writer) + { + writer.Write(MMDModel1.GetBytes(BoneNameEnglish, 20)); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelBoneDisp.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelBoneDisp.cs new file mode 100644 index 000000000..38f7d25e6 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelBoneDisp.cs @@ -0,0 +1,33 @@ +using System; +using System.IO; +using WORD = System.UInt16; + +namespace MikuMikuDance.Model.Ver1 +{ + /// + /// ボーン枠用表示データ + /// + public class ModelBoneDisp + { + /// + /// æž ç”¨ãƒœãƒ¼ãƒ³ç•ªå· + /// + public WORD BoneIndex { get; set; } // æž ç”¨ãƒœãƒ¼ãƒ³ç•ªå· + /// + /// è¡¨ç¤ºæž ç”¨ç•ªå· + /// + public byte BoneDispFrameIndex { get; set; } // è¡¨ç¤ºæž ç•ªå· + + internal void Read(BinaryReader reader) + { + BoneIndex = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + BoneDispFrameIndex = reader.ReadByte(); + } + + internal void Write(BinaryWriter writer) + { + writer.Write(BoneIndex); + writer.Write(BoneDispFrameIndex); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelBoneDispName.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelBoneDispName.cs new file mode 100644 index 000000000..bacd1892c --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelBoneDispName.cs @@ -0,0 +1,38 @@ +using System.IO; + +namespace MikuMikuDance.Model.Ver1 +{ + /// + /// ãƒœãƒ¼ãƒ³æž ç”¨ã®æž å + /// + public class ModelBoneDispName + { + /// + /// ãƒœãƒ¼ãƒ³æž ç”¨ã®æž å + /// + public string BoneDispName { get; set; }//ボーン枠用枠å + /// + /// ãƒœãƒ¼ãƒ³æž ç”¨ã®æž å(è‹±èªžã€æ‹¡å¼µ) + /// + public string BoneDispNameEnglish { get; set; }//ボーン枠用枠å(è‹±èªžã€æ‹¡å¼µ) + internal void Read(BinaryReader reader) + { + BoneDispName = MMDModel1.GetString(reader.ReadBytes(50)); + BoneDispNameEnglish = null; + } + internal void ReadExpantion(BinaryReader reader) + { + BoneDispNameEnglish = MMDModel1.GetString(reader.ReadBytes(50)); + } + + internal void Write(BinaryWriter writer) + { + writer.Write(MMDModel1.GetBytes(BoneDispName, 50)); + } + + internal void WriteExpantion(BinaryWriter writer) + { + writer.Write(MMDModel1.GetBytes(BoneDispNameEnglish, 50)); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelHeader.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelHeader.cs new file mode 100644 index 000000000..1246ad039 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelHeader.cs @@ -0,0 +1,63 @@ +using System.IO; + +namespace MikuMikuDance.Model.Ver1 +{ + /// + /// モデルヘッダ情報を表ã™ã‚¯ãƒ©ã‚¹ + /// + public class ModelHeader + { + /// + /// モデルå + /// + public string ModelName { get; set; } + /// + /// モデルコメント + /// + public string Comment { get; set; } + /// + /// モデルå(è‹±èªžã€æ‹¡å¼µ) + /// + public string ModelNameEnglish { get; set; } + /// + /// モデルコメント(è‹±èªžã€æ‹¡å¼µ) + /// + public string CommentEnglish { get; set; } + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public ModelHeader() + { + ModelName = ""; + Comment = ""; + ModelNameEnglish = null; + CommentEnglish = null; + } + internal void Read(BinaryReader reader) + { + //モデルå + ModelName = MMDModel1.GetString(reader.ReadBytes(20)); + //コメント + Comment = MMDModel1.GetString(reader.ReadBytes(256)); + } + + internal void ReadExpantion(BinaryReader reader) + { + ModelNameEnglish = MMDModel1.GetString(reader.ReadBytes(20)); + CommentEnglish = MMDModel1.GetString(reader.ReadBytes(256)); + } + + internal void Write(BinaryWriter writer) + { + writer.Write(MMDModel1.GetBytes(ModelName, 20)); + writer.Write(MMDModel1.GetBytes(Comment, 256)); + } + + internal void WriteExpantion(BinaryWriter writer) + { + writer.Write(MMDModel1.GetBytes(ModelNameEnglish, 20)); + writer.Write(MMDModel1.GetBytes(CommentEnglish, 256)); + } + } + +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelIK.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelIK.cs new file mode 100644 index 000000000..122f80ef7 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelIK.cs @@ -0,0 +1,60 @@ +using System; +using System.IO; +using WORD = System.UInt16; + +namespace MikuMikuDance.Model.Ver1 +{ + /// + /// IKボーン + /// + public class ModelIK + { + /// + /// IKãƒœãƒ¼ãƒ³ç•ªå· + /// + public WORD IKBoneIndex { get; set; } // IKãƒœãƒ¼ãƒ³ç•ªå· + /// + /// IKã‚¿ãƒ¼ã‚²ãƒƒãƒˆãƒœãƒ¼ãƒ³ç•ªå· + /// + /// IKãƒœãƒ¼ãƒ³ãŒæœ€åˆã«æŽ¥ç¶šã™ã‚‹ãƒœãƒ¼ãƒ³ + public WORD IKTargetBoneIndex { get; set; } // IKã‚¿ãƒ¼ã‚²ãƒƒãƒˆãƒœãƒ¼ãƒ³ç•ªå· // IKãƒœãƒ¼ãƒ³ãŒæœ€åˆã«æŽ¥ç¶šã™ã‚‹ãƒœãƒ¼ãƒ³ + //byte ik_chain_length;//読ã¿è¾¼ã‚“ã§ã‚‹ãŒã€ik_child_bone_indexã§å‚ç…§å¯ã®ãŸã‚ã€ãƒ¡ãƒ³ãƒã«ã—ãªã„ + /// + /// å†å¸°æ¼”算回数 + /// + /// IK値1 + public WORD Iterations { get; set; } // å†å¸°æ¼”算回数 // IK値1 + /// + /// 一回ã®IK計算ã§ã®è§’åº¦åˆ¶é™ + /// + /// IK値2 + public float AngleLimit { get; set; } // IKã®å½±éŸ¿åº¦ // IK値2 + /// + /// IK影響下ã®ãƒœãƒ¼ãƒ³ç•ªå·ãƒªã‚¹ãƒˆ + /// + public WORD[] IKChildBoneIndex { get; set; } // IK影響下ã®ãƒœãƒ¼ãƒ³ç•ªå·-サイズã¯ik_chain_length + + internal void Read(BinaryReader reader) + { + IKBoneIndex = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + IKTargetBoneIndex = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + byte ik_chain_length = reader.ReadByte(); + Iterations = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + AngleLimit = BitConverter.ToSingle(reader.ReadBytes(4), 0); + IKChildBoneIndex = new WORD[ik_chain_length]; + for (int i = 0; i < ik_chain_length; i++) + IKChildBoneIndex[i] = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + } + + internal void Write(BinaryWriter writer) + { + writer.Write(IKBoneIndex); + writer.Write(IKTargetBoneIndex); + writer.Write((byte)IKChildBoneIndex.Length); + writer.Write(Iterations); + writer.Write(AngleLimit); + for (int i = 0; i < IKChildBoneIndex.Length; i++) + writer.Write(IKChildBoneIndex[i]); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelJoint.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelJoint.cs new file mode 100644 index 000000000..1073938fe --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelJoint.cs @@ -0,0 +1,132 @@ +using System; +using System.IO; +using DWORD = System.UInt32; + +namespace MikuMikuDance.Model.Ver1 +{ + /// + /// ç‰©ç†æ¼”算用ã®ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆ + /// + public class ModelJoint + { + /// + /// åç§° + /// + public string Name { get; set; } // 諸データ:åç§° // å³é«ª1(char*20) + /// + /// 剛体A + /// + public DWORD RigidBodyA { get; set; } // 諸データ:剛体A + /// + /// 剛体B + /// + public DWORD RigidBodyB { get; set; } // 諸データ:剛体B + /// + /// ä½ç½®(x, y, z) + /// + public float[] Position { get;private set; } //float*3 諸データ:ä½ç½®(x, y, z) // 諸データ:ä½ç½®åˆã›ã§ã‚‚è¨­å®šå¯ + /// + /// 回転(rad(x), rad(y), rad(z)) + /// + public float[] Rotation { get; private set; } //float*3 諸データ:回転(rad(x), rad(y), rad(z)) + /// + /// 移動制é™1(x, y, z) + /// + public float[] ConstrainPosition1 { get; private set; } //float*3 制é™ï¼šç§»å‹•1(x, y, z) + /// + /// 移動制é™2(x, y, z) + /// + public float[] ConstrainPosition2 { get; private set; } //float*3 制é™ï¼šç§»å‹•2(x, y, z) + /// + /// 回転制é™1(rad(x), rad(y), rad(z)) + /// + public float[] ConstrainRotation1 { get; private set; } //float*3 制é™ï¼šå›žè»¢1(rad(x), rad(y), rad(z)) + /// + /// 回転制é™2(rad(x), rad(y), rad(z)) + /// + public float[] ConstrainRotation2 { get; private set; } //float*3 制é™ï¼šå›žè»¢2(rad(x), rad(y), rad(z)) + /// + /// 平行移動ã«å¯¾ã™ã‚‹ã°ã­ã®æˆ»ã‚‹å¼·ã•:移動(x, y, z) + /// + public float[] SpringPosition { get; private set; } //float*3 ã°ã­ï¼šç§»å‹•(x, y, z) + /// + /// 回転ã«å¯¾ã™ã‚‹ã°ã­ã®æˆ»ã‚‹å¼·ã•:回転(rad(x), rad(y), rad(z)) + /// + public float[] SpringRotation { get; private set; } //float*3 ã°ã­ï¼šå›žè»¢(rad(x), rad(y), rad(z)) + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public ModelJoint() + { + Position = new float[3]; + Rotation = new float[3]; + ConstrainPosition1 = new float[3]; + ConstrainPosition2 = new float[3]; + ConstrainRotation1 = new float[3]; + ConstrainRotation2 = new float[3]; + SpringPosition = new float[3]; + SpringRotation = new float[3]; + } + internal void ReadExpantion(BinaryReader reader, float CoordZ, float scale) + { + Name = MMDModel1.GetString(reader.ReadBytes(20)); + RigidBodyA = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + RigidBodyB = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + for (int i = 0; i < Position.Length; i++) + Position[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0) *scale; + for (int i = 0; i < Rotation.Length; i++) + Rotation[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < ConstrainPosition1.Length; i++) + ConstrainPosition1[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0) *scale; + for (int i = 0; i < ConstrainPosition2.Length; i++) + ConstrainPosition2[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0) *scale; + for (int i = 0; i < ConstrainRotation1.Length; i++) + ConstrainRotation1[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < ConstrainRotation2.Length; i++) + ConstrainRotation2[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < SpringPosition.Length; i++) + SpringPosition[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < SpringRotation.Length; i++) + SpringRotation[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + Position[2] *= CoordZ; + //ãƒ¡ãƒ¢ï¼šå·¦æ‰‹â†’å³æ‰‹ã§ã¯ä½ç½®ãŒå¤‰æ›ã•れる際ã«ä¸€ç·’ã«å›žè»¢æˆåˆ†ãŒå¤‰æ›ã•れるãŸã‚ã€å›žè»¢ã®å¤‰æ›ã¯å¿…è¦ãªã„ + //ãŸã ã—ã€ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆã®å›žè»¢(使用ã—ã¦ãªã„ã£ã½ã„)ã¯å¤‰æ›ã—ã¦ãŠã + ConstrainRotation1[0] *= CoordZ; + ConstrainRotation1[1] *= CoordZ; + ConstrainRotation2[0] *= CoordZ; + ConstrainRotation2[1] *= CoordZ; + ConstrainPosition1[2] *= CoordZ; + ConstrainPosition2[2] *= CoordZ; + } + + internal void WriteExpantion(BinaryWriter writer, float CoordZ, float scale) + { + Position[2] *= CoordZ; + ConstrainRotation1[0] *= CoordZ; + ConstrainRotation1[1] *= CoordZ; + ConstrainRotation2[0] *= CoordZ; + ConstrainRotation2[1] *= CoordZ; + ConstrainPosition1[2] *= CoordZ; + ConstrainPosition2[2] *= CoordZ; + writer.Write(MMDModel1.GetBytes(Name, 20)); + writer.Write(RigidBodyA); + writer.Write(RigidBodyB); + for (int i = 0; i < Position.Length; i++) + writer.Write(Position[i]* scale); + for (int i = 0; i < Rotation.Length; i++) + writer.Write(Rotation[i]); + for (int i = 0; i < ConstrainPosition1.Length; i++) + writer.Write(ConstrainPosition1[i]*scale); + for (int i = 0; i < ConstrainPosition2.Length; i++) + writer.Write(ConstrainPosition2[i]*scale); + for (int i = 0; i < ConstrainRotation1.Length; i++) + writer.Write(ConstrainRotation1[i]); + for (int i = 0; i < ConstrainRotation2.Length; i++) + writer.Write(ConstrainRotation2[i]); + for (int i = 0; i < SpringPosition.Length; i++) + writer.Write(SpringPosition[i]*scale); + for (int i = 0; i < SpringRotation.Length; i++) + writer.Write(SpringRotation[i]); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelMaterial.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelMaterial.cs new file mode 100644 index 000000000..d7be53489 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelMaterial.cs @@ -0,0 +1,126 @@ +using System; +using System.IO; +using DWORD = System.UInt32; + +namespace MikuMikuDance.Model.Ver1 +{ + /// + /// ãƒ¢ãƒ‡ãƒ«ã®æè³ª + /// + public class ModelMaterial + { + /// + /// rgbã®æ¸›è¡°è‰² + /// + public float[] DiffuseColor { get; private set; } // dr, dg, db // 減衰色 + /// + /// α値 + /// + public float Alpha { get; set; } + /// + /// 光沢 + /// + public float Specularity { get; set; } + /// + /// 光沢色(rgb) + /// + public float[] SpecularColor { get; private set; } // sr, sg, sb // 光沢色 + /// + /// 環境色(ambient)(rgb) + /// + public float[] MirrorColor { get; private set; } // mr, mg, mb // 環境色(ambient) + /// + /// 使用ã™ã‚‹ãƒˆã‚¥ãƒ¼ãƒ³bmpç•ªå· + /// + /// 使用ã™ã‚‹å ´åˆã¯0ã‹ã‚‰9ã¾ã§ã®ç•ªå·ã€‚使用ã—ãªã„å ´åˆã¯0xFF + public byte ToonIndex { get; set; } // toon??.bmp // 0.bmp:0xFF, 1(01).bmp:0x00 ・・・ 10.bmp:0x09 + /// + /// 輪郭ã€å½± + /// + public byte EdgeFlag { get; set; } // 輪郭ã€å½± + /// + /// é¢é ‚点数 + /// + public DWORD FaceVertCount { get; set; } // é¢é ‚点数 // インデックスã«å¤‰æ›ã™ã‚‹å ´åˆã¯ã€æè³ª0ã‹ã‚‰é †ã«åŠ ç®— + /// + /// テクスãƒãƒ£ãƒ•ァイルå + /// + public string TextureFileName { get; set; } //20byte分char テクスãƒãƒ£ãƒ•ァイルå // 20ãƒã‚¤ãƒˆãŽã‚ŠãŽã‚Šã¾ã§ä½¿ãˆã‚‹(終端ã®0x00ã¯ç„¡ãã¦ã‚‚å‹•ã) + /// + /// スフィアマップファイルå + /// + public string SphereTextureFileName { get; set; } + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public ModelMaterial() + { + DiffuseColor = new float[3]; + SpecularColor = new float[3]; + MirrorColor = new float[3]; + TextureFileName = ""; + SphereTextureFileName = ""; + } + internal void Read(BinaryReader reader) + { + DiffuseColor = new float[3]; + SpecularColor = new float[3]; + MirrorColor = new float[3]; + for (int i = 0; i < DiffuseColor.Length; i++) + DiffuseColor[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + Alpha = BitConverter.ToSingle(reader.ReadBytes(4), 0); + Specularity = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < SpecularColor.Length; i++) + SpecularColor[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < MirrorColor.Length; i++) + MirrorColor[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + ToonIndex = reader.ReadByte(); + EdgeFlag = reader.ReadByte(); + FaceVertCount = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + string FileName = MMDModel1.GetString(reader.ReadBytes(20)); + string[] FileNames = FileName.Split('*'); + TextureFileName = ""; + SphereTextureFileName = ""; + foreach (string s in FileNames) + { + string ext = Path.GetExtension(s).ToLower(); + if (ext == ".sph" || ext == ".spa") + { + SphereTextureFileName = s.Trim(); + } + else + { + TextureFileName = s.Trim(); + } + } + } + + internal void Write(BinaryWriter writer) + { + for (int i = 0; i < DiffuseColor.Length; i++) + writer.Write(DiffuseColor[i]); + writer.Write(Alpha); + writer.Write(Specularity); + for (int i = 0; i < SpecularColor.Length; i++) + writer.Write(SpecularColor[i]); + for (int i = 0; i < MirrorColor.Length; i++) + writer.Write(MirrorColor[i]); + writer.Write(ToonIndex); + writer.Write(EdgeFlag); + writer.Write(FaceVertCount); + string FileName = TextureFileName; + if (string.IsNullOrEmpty(FileName)) + { + FileName = SphereTextureFileName; + } + else + { + if (!string.IsNullOrEmpty(SphereTextureFileName)) + { + FileName += "*" + SphereTextureFileName; + } + } + writer.Write(MMDModel1.GetBytes(FileName, 20)); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelRigidBody.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelRigidBody.cs new file mode 100644 index 000000000..8ba64c776 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelRigidBody.cs @@ -0,0 +1,140 @@ +using System; +using System.IO; +using WORD = System.UInt16; + +namespace MikuMikuDance.Model.Ver1 +{ + /// + /// 剛体(ç‰©ç†æ¼”算用) + /// + public class ModelRigidBody + { + /// + /// åç§° + /// + public string Name { get; set; } // 諸データ:åç§° // é ­(20byte char) + /// + /// é–¢é€£ãƒœãƒ¼ãƒ³ç•ªå· + /// + public WORD RelatedBoneIndex { get; set; } // è«¸ãƒ‡ãƒ¼ã‚¿ï¼šé–¢é€£ãƒœãƒ¼ãƒ³ç•ªå· // 03 00 == 3 // é ­ + /// + /// ã‚°ãƒ«ãƒ¼ãƒ—ç•ªå· + /// + public byte GroupIndex { get; set; } // 諸データ:グループ // 00 + /// + /// è¡çªå¯¾è±¡ã‚°ãƒ«ãƒ¼ãƒ— + /// + /// å„ビットãŒã‚°ãƒ«ãƒ¼ãƒ—番å·ã«å¯¾å¿œã—ã¦ãŠã‚Šã€ãƒ“ットãŒç«‹ã£ã¦ãªã‘れã°ãã®ã‚°ãƒ«ãƒ¼ãƒ—ã¨ã¯è¡çªã—ãªã„ã¨ã„ã†å®Ÿè£… + public WORD GroupTarget { get; set; } // 諸データ:グループ:対象 // 0xFFFFã¨ã®å·® // 38 FE + /// + /// 形状 + /// + /// 0:çƒã€1:ç®±ã€2:カプセル + public byte ShapeType { get; set; } // 形状:タイプ(0:çƒã€1:ç®±ã€2:カプセル) // 00 // çƒ + /// + /// åŠå¾„(å¹…) + /// + public float ShapeWidth { get; set; } // 形状:åŠå¾„(å¹…) // CD CC CC 3F // 1.6 + /// + /// 高㕠+ /// + public float ShapeHeight { get; set; } // 形状:高㕠// CD CC CC 3D // 0.1 + /// + /// 奥行ã + /// + public float ShapeDepth { get; set; } // 形状:奥行 // CD CC CC 3D // 0.1 + /// + /// ä½ç½®(x,y,z) + /// + public float[] Position { get; protected set; } //float*3 ä½ç½®ï¼šä½ç½®(x, y, z) + /// + /// 回転 + /// + public float[] Rotation { get; protected set; } //float*3 ä½ç½®ï¼šå›žè»¢(rad(x), rad(y), rad(z)) + /// + /// è³ªé‡ + /// + public float Weight { get; set; } // è«¸ãƒ‡ãƒ¼ã‚¿ï¼šè³ªé‡ // 00 00 80 3F // 1.0 + /// + /// ダンピング1 + /// + public float LinerDamping { get; set; } // 諸データ:移動減 // 00 00 00 00 + /// + /// ダンピング2 + /// + public float AngularDamping { get; set; } // 諸データ:回転減 // 00 00 00 00 + /// + /// å発係数 + /// + public float Restitution { get; set; } // 諸データ:å発力 // 00 00 00 00 + /// + /// 摩擦力 + /// + public float Friction { get; set; } // 諸データ:摩擦力 // 00 00 00 00 + /// + /// 剛体タイプ + /// + /// 0:Bone追従ã€1:ç‰©ç†æ¼”ç®—ã€2:ç‰©ç†æ¼”ç®—(Boneä½ç½®åˆã›) + public byte Type { get; set; } // 諸データ:タイプ(0:Bone追従ã€1:ç‰©ç†æ¼”ç®—ã€2:ç‰©ç†æ¼”ç®—(Boneä½ç½®åˆã›)) // 00 // Bone追従 + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public ModelRigidBody() + { + Position = new float[3]; + Rotation = new float[3]; + } + + internal void ReadExpantion(BinaryReader reader, float CoordZ, float scale) + { + Name = MMDModel1.GetString(reader.ReadBytes(20)); + RelatedBoneIndex = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + GroupIndex = reader.ReadByte(); + GroupTarget = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + ShapeType = reader.ReadByte(); + ShapeWidth = BitConverter.ToSingle(reader.ReadBytes(4), 0)*scale; + ShapeHeight = BitConverter.ToSingle(reader.ReadBytes(4), 0)*scale; + ShapeDepth = BitConverter.ToSingle(reader.ReadBytes(4), 0)*scale; + for (int i = 0; i < Position.Length; i++) + Position[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0) * scale; + for (int i = 0; i < Rotation.Length; i++) + Rotation[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + Weight = BitConverter.ToSingle(reader.ReadBytes(4), 0); + LinerDamping = BitConverter.ToSingle(reader.ReadBytes(4), 0); + AngularDamping = BitConverter.ToSingle(reader.ReadBytes(4), 0); + Restitution = BitConverter.ToSingle(reader.ReadBytes(4), 0); + Friction = BitConverter.ToSingle(reader.ReadBytes(4), 0); + Type = reader.ReadByte(); + Position[2] *= CoordZ; + //ãƒ¡ãƒ¢ï¼šå·¦æ‰‹â†’å³æ‰‹ã§ã¯ä½ç½®ãŒå¤‰æ›ã•れる際ã«ä¸€ç·’ã«å›žè»¢æˆåˆ†ãŒå¤‰æ›ã•れるãŸã‚ã€å›žè»¢ã®å¤‰æ›ã¯å¿…è¦ãªã„……ã®ã ãŒ + //剛体ã¯ãƒ¢ãƒ‡ãƒ«ã¨é•ã„ã€ä½ç½®ã¨å›žè»¢æƒ…å ±ã ã‘ãªã®ã§ã€å›žè»¢ã‚’変æ›ã™ã‚‹å¿…è¦ãŒã‚ã‚‹ + Rotation[0] *= CoordZ; + Rotation[1] *= CoordZ; + } + + internal void WriteExpantion(BinaryWriter writer, float CoordZ, float scale) + { + Position[2] *= CoordZ; + Rotation[0] *= CoordZ; + Rotation[1] *= CoordZ; + writer.Write(MMDModel1.GetBytes(Name, 20)); + writer.Write(RelatedBoneIndex); + writer.Write(GroupIndex); + writer.Write(GroupTarget); + writer.Write(ShapeType); + writer.Write(ShapeWidth * scale); + writer.Write(ShapeHeight * scale); + writer.Write(ShapeDepth * scale); + for (int i = 0; i < Position.Length; i++) + writer.Write(Position[i] * scale); + for (int i = 0; i < Rotation.Length; i++) + writer.Write(Rotation[i]); + writer.Write(Weight); + writer.Write(LinerDamping); + writer.Write(AngularDamping); + writer.Write(Restitution); + writer.Write(Friction); + writer.Write(Type); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelSkin.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelSkin.cs new file mode 100644 index 000000000..bd3c50abe --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelSkin.cs @@ -0,0 +1,114 @@ +using System; +using System.IO; +using DWORD = System.UInt32; + +namespace MikuMikuDance.Model.Ver1 +{ + /// + /// 表情用ã®é ‚点ã®ãƒ‡ãƒ¼ã‚¿ + /// + public class ModelSkinVertexData + { + + //base時ï¼è¡¨æƒ…用ã®é ‚点ã®ç•ªå·(頂点リストã«ã‚る番å·) + //base以外=表情用ã®é ‚点ã®ç•ªå·(baseã®ç•ªå·ã€‚skin_vert_index) + /// + /// é ‚ç‚¹ç•ªå· + /// + /// + /// base時ï¼è¡¨æƒ…用ã®é ‚点ã®ç•ªå·(頂点リストã«ã‚る番å·) + /// base以外=表情用ã®é ‚点ã®ç•ªå·(baseã®ç•ªå·ã€‚skin_vert_index) + /// + public DWORD SkinVertIndex { get; set; } + + //base時=x, y, z // 表情用ã®é ‚点ã®åº§æ¨™(頂点自体ã®åº§æ¨™) + //base以外=x, y, z // 表情用ã®é ‚点ã®åº§æ¨™ã‚ªãƒ•セット値(baseã«å¯¾ã™ã‚‹ã‚ªãƒ•セット) + /// + /// 表情用ã®é ‚点ã®åº§æ¨™ãƒªã‚¹ãƒˆ + /// + /// + /// base時=x, y, z // 表情用ã®é ‚点ã®åº§æ¨™(頂点自体ã®åº§æ¨™) + /// base以外=x, y, z // 表情用ã®é ‚点ã®åº§æ¨™ã‚ªãƒ•セット値(baseã«å¯¾ã™ã‚‹ã‚ªãƒ•セット) + /// + public float[] SkinVertPos { get; private set; } // + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public ModelSkinVertexData() + { + SkinVertPos = new float[3]; + } + internal void Read(BinaryReader reader, float CoordZ, float scale) + { + SkinVertIndex = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + for (int i = 0; i < SkinVertPos.Length; i++) + SkinVertPos[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0)* scale; + SkinVertPos[2] *= CoordZ; + } + + internal void Write(BinaryWriter writer, float CoordZ, float scale) + { + SkinVertPos[2] *= CoordZ; + writer.Write(SkinVertIndex); + for (int i = 0; i < SkinVertPos.Length; i++) + writer.Write(SkinVertPos[i] * scale); + } + } + /// + /// 表情 + /// + public class ModelSkin + { + /// + /// 表情å + /// + public string SkinName { get; set; } // 表情å(char[20]) + //public DWORD skin_vert_count { get; set; } // 表情用ã®é ‚点数-SkinVertDatasã®Lengthã§å‚ç…§ + /// + /// 表情ã®ç¨®é¡ž + /// + /// 0:baseã€1:ã¾ã‚†ã€2:目ã€3:リップã€4:ãã®ä»– + public byte SkinType { get; set; } // 表情ã®ç¨®é¡ž(byte) // 0:baseã€1:ã¾ã‚†ã€2:目ã€3:リップã€4:ãã®ä»– + /// + /// 表情用ã®é ‚点ã®ãƒ‡ãƒ¼ã‚¿ãƒªã‚¹ãƒˆ + /// + public ModelSkinVertexData[] SkinVertDatas { get; set; } // 表情用ã®é ‚点ã®ãƒ‡ãƒ¼ã‚¿(16Bytes/vert) *skin_vert_count + /// + /// 表情å(è‹±èªžã€æ‹¡å¼µ) + /// + public string SkinNameEnglish { get; set; }//表示å(char[20]ã€è‹±èªž)(æ‹¡å¼µ) + internal void Read(BinaryReader reader, float CoordZ, float scale) + { + SkinName = MMDModel1.GetString(reader.ReadBytes(20)); + DWORD skin_vert_count = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + SkinType = reader.ReadByte(); + SkinVertDatas = new ModelSkinVertexData[skin_vert_count]; + for (int i = 0; i < SkinVertDatas.Length; i++) + { + SkinVertDatas[i] = new ModelSkinVertexData(); + SkinVertDatas[i].Read(reader, CoordZ, scale); + } + SkinNameEnglish = null; + } + internal void ReadExpantion(BinaryReader reader) + { + SkinNameEnglish = MMDModel1.GetString(reader.ReadBytes(20)); + } + + internal void Write(BinaryWriter writer, float CoordZ, float scale) + { + writer.Write(MMDModel1.GetBytes(SkinName,20)); + writer.Write((DWORD)SkinVertDatas.Length); + writer.Write(SkinType); + for (int i = 0; i < SkinVertDatas.Length; i++) + { + SkinVertDatas[i].Write(writer, CoordZ, scale); + } + } + + internal void WriteExpantion(BinaryWriter writer) + { + writer.Write(MMDModel1.GetBytes(SkinNameEnglish, 20)); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelVertex.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelVertex.cs new file mode 100644 index 000000000..e73781d6b --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDModelLibrary/Ver1/ModelVertex.cs @@ -0,0 +1,89 @@ +using System; +using System.IO; +using WORD = System.UInt16; + +namespace MikuMikuDance.Model.Ver1 +{ + /// + /// モデルã®é ‚点 + /// + public class ModelVertex + { + /// + /// x,y,z座標 + /// + public float[] Pos { get; private set; } // x, y, z // 座標 + /// + /// x,y,zã®æ³•線ベクトル + /// + public float[] NormalVector { get; private set; } // nx, ny, nz // 法線ベクトル + /// + /// UV座標(頂点UV) + /// + public float[] UV { get; private set; } // u, v // UV座標 // MMDã¯é ‚点UV + /// + /// ãƒœãƒ¼ãƒ³ç•ªå· + /// + /// 番å·ã¯1ã¾ãŸã¯2。モデル変形(頂点移動)時ã«å½±éŸ¿ + public WORD[] BoneNum { get; private set; } // ボーン番å·1ã€ç•ªå·2 // モデル変形(頂点移動)時ã«å½±éŸ¿ + /// + /// 影響度 + /// + /// ボーン1ã«ä¸Žãˆã‚‹å½±éŸ¿åº¦ã€‚min:0 max:100。ボーン2ã¸ã®å½±éŸ¿åº¦ã¯ã€(100 - BoneWeight) + public byte BoneWeight { get; private set; } // ボーン1ã«ä¸Žãˆã‚‹å½±éŸ¿åº¦ // min:0 max:100 // ボーン2ã¸ã®å½±éŸ¿åº¦ã¯ã€(100 - bone_weight) + /// + /// エッジフラグ + /// + /// 0:通常ã€1:エッジ無効(エッジ(輪郭)ãŒæœ‰åйã®å ´åˆ) + public byte NonEdgeFlag { get; private set; } // 0:通常ã€1:エッジ無効 // エッジ(輪郭)ãŒæœ‰åйã®å ´åˆ + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public ModelVertex() + { + Pos = new float[3]; + NormalVector = new float[3]; + UV = new float[2]; + BoneNum = new WORD[2]; + BoneWeight = 0; + NonEdgeFlag = 0; + } + internal void Read(BinaryReader reader, float CoordZ, float scale) + { + //サイズ + Pos = new float[3]; + NormalVector = new float[3]; + UV = new float[2]; + BoneNum = new WORD[2]; + for (int i = 0; i < Pos.Length; i++) + Pos[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0) * scale; + for (int i = 0; i < NormalVector.Length; i++) + NormalVector[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < UV.Length; i++) + UV[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < BoneNum.Length; i++) + BoneNum[i] = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + BoneWeight = reader.ReadByte(); + NonEdgeFlag = reader.ReadByte(); + Pos[2] = Pos[2] * CoordZ; + NormalVector[2] = NormalVector[2] * CoordZ; + } + + internal void Write(BinaryWriter writer, float CoordZ, float scale) + { + Pos[2] = Pos[2] * CoordZ; + NormalVector[2] = NormalVector[2] * CoordZ*scale; + for (int i = 0; i < Pos.Length; i++) + writer.Write(Pos[i]); + for (int i = 0; i < NormalVector.Length; i++) + writer.Write(NormalVector[i]); + for (int i = 0; i < UV.Length; i++) + writer.Write(UV[i]); + for (int i = 0; i < BoneNum.Length; i++) + writer.Write(BoneNum[i]); + writer.Write(BoneWeight); + writer.Write(NonEdgeFlag); + } + + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/CoordinateType.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/CoordinateType.cs new file mode 100644 index 000000000..5f867a2b0 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/CoordinateType.cs @@ -0,0 +1,20 @@ + +namespace MikuMikuDance.Motion +{ + /// + /// 座標系を表ã™åˆ—挙体 + /// + public enum CoordinateType + { + /// + /// 左手座標系 + /// + /// MMDã®æ¨™æº–座標系 + LeftHandedCoordinate = 1, + /// + /// 峿‰‹åº§æ¨™ç³» + /// + /// XNAã®æ¨™æº–座標系 + RightHandedCoordinate = -1, + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/MMDMotion.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/MMDMotion.cs new file mode 100644 index 000000000..56d517c37 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/MMDMotion.cs @@ -0,0 +1,40 @@ +using System.IO; + +namespace MikuMikuDance.Motion +{ + /// + /// MMDモーションを表ã™ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェイス + /// + public interface MMDMotion + { + /// + /// MMDモーションãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå· + /// + int Version { get; } + /// + /// Read関数 + /// + /// ã“ã®é–¢æ•°ã¯ModelManagerã‹ã‚‰å‘¼ã³å‡ºã•れる。呼ã³å‡ºã—時ã«ã¯ãƒžã‚¸ãƒƒã‚¯æ–‡å­—ã¨ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ãŒèª­ã¾ã‚ŒãŸçŠ¶æ…‹ã§æ¸¡ã•れる + /// マジック文字ã¨ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·èª­ã¿è¾¼ã¿æ¸ˆã¿ã®BinaryReader + /// 変æ›å…ˆåº§æ¨™ç³» + /// スケーリング値 + void Read(BinaryReader reader, CoordinateType coordinate, float scale); + /// + /// ä¿æŒã—ã¦ã„るデータã®åº§æ¨™ç³» + /// + CoordinateType Coordinate { get; } +#if false + /// + /// スケーリング + /// + /// 拡大å€çއ + void Scale(float ScaleFactor); +#endif + /// + /// ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ã®æ›¸ã出㗠+ /// + /// 書ã出㗠+ /// スケーリング値 + void Write(BinaryWriter writer, float scale); + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/CameraMotionData.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/CameraMotionData.cs new file mode 100644 index 000000000..503e3d8ce --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/CameraMotionData.cs @@ -0,0 +1,93 @@ +using System; +using System.IO; +using DWORD = System.UInt32; +using WORD = System.UInt16; + +namespace MikuMikuDance.Motion.Motion2 +{ + /// + /// カメラモーションデータ + /// + public class CameraMotionData + { + /// + /// ãƒ•ãƒ¬ãƒ¼ãƒ ç•ªå· + /// + public DWORD FrameNo { get; set; } + /// + /// é•·ã• + /// + public float Length { get; set; } + /// + /// ä½ç½® + /// + public float[] Location { get; protected set; } + /// + /// 回転 + /// + public float[] Rotate { get; protected set; } + /// + /// 補完データ + /// + public byte[][] Interpolation { get; protected set; } + /// + /// 視野角 + /// + public WORD ViewingAngle { get; protected set; } + /// + /// 䏿˜Žãƒ‡ãƒ¼ã‚¿ + /// + /// ã ã‚Œã‹æ•™ãˆã¦ãれ(´・ω・`) + public byte[] Unknown { get; protected set; } + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public CameraMotionData() + { + Location = new float[3]; + Rotate = new float[3]; + Interpolation = new byte[6][]; + for (int i = 0; i < 6; i++) + Interpolation[i] = new byte[4]; + Unknown = new byte[3]; + } + + internal void Read(BinaryReader reader, float CoordZ) + { + FrameNo = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + Length = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < 3; i++) + Location[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < 3; i++) + Rotate[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < 6; i++) + for (int j = 0; j < 4; j++) + Interpolation[i][j] = reader.ReadByte(); + ViewingAngle = BitConverter.ToUInt16(reader.ReadBytes(2), 0); + for (int i = 0; i < 3; i++) + Unknown[i] = reader.ReadByte(); + Location[2] *= CoordZ; + Rotate[2] *= CoordZ; + /*Rotate[0] *= CoordZ; + Rotate[1] *= CoordZ;*/ + } + + internal void Write(BinaryWriter writer, float CoordZ) + { + writer.Write((DWORD)FrameNo); + writer.Write((Single)Length); + writer.Write((Single)Location[0]); + writer.Write((Single)Location[1]); + writer.Write((Single)Location[2] * CoordZ); + writer.Write((Single)Rotate[0]); + writer.Write((Single)Rotate[1]); + writer.Write((Single)Rotate[2] * CoordZ); + for (int i = 0; i < 6; i++) + for (int j = 0; j < 4; j++) + writer.Write((byte)Interpolation[i][j]); + writer.Write((WORD)ViewingAngle); + for (int i = 0; i < 3; i++) + writer.Write((byte)Unknown[i]); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/FaceMotionData.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/FaceMotionData.cs new file mode 100644 index 000000000..5f6e20af9 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/FaceMotionData.cs @@ -0,0 +1,39 @@ +using System; +using System.IO; +using DWORD = System.UInt32; + +namespace MikuMikuDance.Motion.Motion2 +{ + /// + /// フェイスモーションデータ + /// + public class FaceMotionData + { + /// + /// 表情é©å¿œå‰²åˆ + /// + public float Rate { get; set; } + /// + /// 表情å + /// + public string FaceName { get; set; }//[15]; + /// + /// フレームナンãƒãƒ¼ + /// + public DWORD FrameNo { get; set; } + internal void Read(BinaryReader reader) + { + FaceName = MMDMotion2.GetString(reader.ReadBytes(15)); + FrameNo = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + //Wait = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + Rate = BitConverter.ToSingle(reader.ReadBytes(4), 0); + } + + internal void Write(BinaryWriter writer) + { + writer.Write(MMDMotion2.GetBytes(FaceName, 15)); + writer.Write((DWORD)FrameNo); + writer.Write((Single)Rate); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/LightMotionData.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/LightMotionData.cs new file mode 100644 index 000000000..9962f4394 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/LightMotionData.cs @@ -0,0 +1,46 @@ +using System; +using System.IO; +using DWORD = System.UInt32; + +namespace MikuMikuDance.Motion.Motion2 +{ + /// + /// ライトモーションデータ + /// + public class LightMotionData + { + /// + /// フレームナンãƒãƒ¼ + /// + public DWORD FrameNo { get; set; } + /// + /// ライトã®è‰² + /// + public float[] Color { get; protected set; } + /// + /// ライトã®ä½ç½® + /// + public float[] Location { get; protected set; } + internal void Read(BinaryReader reader, float CoordZ) + { + FrameNo = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + Color = new float[3]; + Location = new float[3]; + for (int i = 0; i < 3; i++) + Color[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < 3; i++) + Location[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + Location[2] *= CoordZ; + } + + internal void Write(BinaryWriter writer, float CoordZ) + { + writer.Write((DWORD)FrameNo); + for (int i = 0; i < 3; i++) + writer.Write((Single)Color[i]); + writer.Write((Single)Location[0]); + writer.Write((Single)Location[1]); + writer.Write((Single)Location[2] * CoordZ); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/MMDMotion2.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/MMDMotion2.cs new file mode 100644 index 000000000..e6494972e --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/MMDMotion2.cs @@ -0,0 +1,197 @@ +using System; +using System.IO; +using System.Text; +using DWORD = System.UInt32; + +namespace MikuMikuDance.Motion.Motion2 +{ + /// + /// MMDã®ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ãƒ‡ãƒ¼ã‚¿Ver2を読ã¿è¾¼ã‚€ãŸã‚ã®ã‚¯ãƒ©ã‚¹ + /// + /// + /// ver2ã¯ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ã®ãƒ˜ãƒƒãƒ€ãŒVocaloid Motion Data 0002ã¨æ›¸ã‹ã‚Œã¦ã‚‹ã‹ã‚‰ã€‚ + /// æ­£å¼ãªãƒãƒ¼ã‚¸ãƒ§ãƒ³ã¯çŸ¥ã‚‰ã‚“ï½— + /// + public class MMDMotion2 : MMDMotion + { + internal MotionData[] m_Motions; + /// + /// モーションã§ä½¿ç”¨ã™ã‚‹ãƒ¢ãƒ‡ãƒ«å + /// + public string ModelName { get; set; } + /// + /// ボーンモーションリスト + /// + public MotionData[] Motions { get { return m_Motions; } set { m_Motions = value; } } + /// + /// フェイスモーションリスト + /// + public FaceMotionData[] FaceMotions { get; set; } + /// + /// カメラモーションリスト + /// + public CameraMotionData[] CameraMotions { get; set; } + /// + /// ライトモーションリスト + /// + public LightMotionData[] LightMotions { get; set; } + //members and properties... + /// + /// Version番å·ã€‚MMDMotionã‹ã‚‰ç¶™æ‰¿ã•れã¾ã™ + /// + public int Version + { + get { return 2; } + } + /// + /// ä¿æŒã—ã¦ã„るデータã®åº§æ¨™ã + /// + public CoordinateType Coordinate { get; set; } + //座標変æ›ç”¨ãƒ˜ãƒ«ãƒ‘関数 + float CoordZ { get { return (float)Coordinate; } } + + //methods... + /// + /// Read関数 + /// + /// ã“ã®é–¢æ•°ã¯MotionManagerã‹ã‚‰å‘¼ã³å‡ºã•れる。呼ã³å‡ºã—時ã«ã¯ãƒžã‚¸ãƒƒã‚¯æ–‡å­—ã¨ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ãŒèª­ã¾ã‚ŒãŸçŠ¶æ…‹ã§æ¸¡ã•れる + /// ヘッダ読ã¿è¾¼ã¿æ¸ˆã¿ã®BinaryReader + /// 変æ›å…ˆåº§æ¨™ç³» + /// スケーリング値 + public void Read(BinaryReader reader, CoordinateType coordinate, float scale) + { + Coordinate = coordinate;//座標系セット + //モデルå読ã¿è¾¼ã¿ + ModelName = GetString(reader.ReadBytes(20)); + //ボーンモーションデータ読ã¿è¾¼ã¿ + DWORD motion_count = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + Motions = new MotionData[motion_count]; + for (long i = 0; i < Motions.LongLength; i++) + { + Motions[i] = new MotionData(); + Motions[i].Read(reader, CoordZ, scale); + } + //フェイスモーションデータ読ã¿è¾¼ã¿ + DWORD face_count = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + FaceMotions = new FaceMotionData[face_count]; + for (long i = 0; i < FaceMotions.LongLength; i++) + { + FaceMotions[i] = new FaceMotionData(); + FaceMotions[i].Read(reader); + } + //カメラモーション読ã¿è¾¼ã¿ + DWORD camera_count = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + CameraMotions = new CameraMotionData[camera_count]; + for (long i = 0; i < CameraMotions.LongLength; i++) + { + CameraMotions[i] = new CameraMotionData(); + CameraMotions[i].Read(reader, CoordZ); + } + //ライトモーション読ã¿è¾¼ã¿ + DWORD light_count = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + LightMotions = new LightMotionData[light_count]; + for (long i = 0; i < LightMotions.LongLength; i++) + { + LightMotions[i] = new LightMotionData(); + LightMotions[i].Read(reader, CoordZ); + } + } + /// + /// ãƒ˜ãƒƒãƒ€ä»¥å¤–ã®æ›¸ã出㗠+ /// + /// ファイル書ã出ã—用ã®BinaryWriter + /// スケーリング値 + public void Write(BinaryWriter writer, float scale) + { + //モデルå読ã¿è¾¼ã¿ + writer.Write(GetBytes(ModelName, 20)); + //ボーンモーションデータ読ã¿è¾¼ã¿ + writer.Write((DWORD)Motions.LongLength); + for (long i = 0; i < Motions.LongLength; i++) + { + Motions[i].Write(writer, CoordZ, scale); + } + //フェイスモーションデータ読ã¿è¾¼ã¿ + writer.Write((DWORD)FaceMotions.LongLength); + for (long i = 0; i < FaceMotions.LongLength; i++) + { + FaceMotions[i].Write(writer); + } + //カメラモーション読ã¿è¾¼ã¿ + writer.Write((DWORD)CameraMotions.LongLength); + for (long i = 0; i < CameraMotions.LongLength; i++) + { + CameraMotions[i].Write(writer, CoordZ); + } + //ライトモーション読ã¿è¾¼ã¿ + writer.Write((DWORD)LightMotions.LongLength); + for (long i = 0; i < LightMotions.LongLength; i++) + { + LightMotions[i].Write(writer, CoordZ); + } + } +#if false + /// + /// スケーリング + /// + /// 拡大å€çއ + public void Scale(float ScaleFactor) + { + if (ScaleFactor <= 0) + throw new ApplicationException("ScaleFactorã¯æ­£ã®å®Ÿæ•°ã§ã‚ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚"); + //ボーン + for (long i = 0; i < Motions.LongLength; i++) + { + for (int j = 0; j < Motions[i].Location.Length; j++) + { + Motions[i].Location[j] = Motions[i].Location[j] * ScaleFactor; + } + + } + //カメラ + for (long i = 0; i < CameraMotions.LongLength; i++) + { + CameraMotions[i].Length=CameraMotions[i].Length*ScaleFactor; + for (int j = 0; j < CameraMotions[i].Location.Length; j++) + CameraMotions[i].Location[j] = CameraMotions[i].Location[j] * ScaleFactor; + } + //ライトモーション + for (long i = 0; i < LightMotions.LongLength; i++) + { + for (int j = 0; j < LightMotions[i].Location.Length; j++) + LightMotions[i].Location[j] = LightMotions[i].Location[j] * ScaleFactor; + } + } +#endif + //internal statics... + internal static Encoding encoder = Encoding.GetEncoding("shift-jis"); + internal static string GetString(byte[] bytes) + { + int i; + for (i = 0; i < bytes.Length; i++) + if (bytes[i] == 0) + break; + if (i < bytes.Length) + return encoder.GetString(bytes, 0, i); + return encoder.GetString(bytes); + } + internal static byte[] GetBytes(string input, long size) + { + byte[] result = new byte[size]; + for (long i = 0; i < size; i++) + result[i] = 0; + if (input == "") + return result; + byte[] strs = encoder.GetBytes(input); + for (long i = 0; i < strs.LongLength; i++) + if (i < result.LongLength) + result[i] = strs[i]; + if (result.LongLength <= strs.LongLength) + return result; + result[strs.LongLength] = 0; + for (long i = strs.LongLength + 1; i < result.Length; i++) + result[i] = 0xFD;//何故ã‹ã“ã‚ŒãŒæŒ¿å…¥ã•れã¦ã„ã‚‹ã®ã§ã“れを挿入 + return result; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/MotionData.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/MotionData.cs new file mode 100644 index 000000000..ceb9de665 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Motion2/MotionData.cs @@ -0,0 +1,81 @@ +using System; +using System.IO; +using DWORD = System.UInt32; + +namespace MikuMikuDance.Motion.Motion2 +{ + /// + /// ボーンモーションデータ + /// + public class MotionData + { + /// + /// ボーンå + /// + public string BoneName { get; set; }//[15]; + /// + /// ãƒ•ãƒ¬ãƒ¼ãƒ ç•ªå· + /// + public DWORD FrameNo { get; set; } + /// + /// ä½ç½®ãƒ™ã‚¯ãƒˆãƒ« + /// + public float[] Location { get; protected set; } + /// + /// クォータニオン + /// + public float[] Quatanion { get; protected set; } + /// + /// 補完データ + /// + public byte[][][] Interpolation { get; protected set; } + /// + /// 既定ã®ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ + /// + public MotionData() + { + Location = new float[3]; + Quatanion = new float[4]; + Interpolation = new byte[4][][]; + for (int i = 0; i < 4; i++) + { + Interpolation[i] = new byte[4][]; + for (int j = 0; j < 4; j++) + Interpolation[i][j] = new byte[4]; + } + } + internal void Read(BinaryReader reader, float CoordZ, float scale) + { + BoneName = MMDMotion2.GetString(reader.ReadBytes(15)); + FrameNo = BitConverter.ToUInt32(reader.ReadBytes(4), 0); + for (int i = 0; i < 3; i++) + Location[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0) * scale; + for (int i = 0; i < 4; i++) + Quatanion[i] = BitConverter.ToSingle(reader.ReadBytes(4), 0); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + for (int k = 0; k < 4; k++) + Interpolation[i][j][k] = reader.ReadByte(); + Location[2] *= CoordZ; + Quatanion[0] *= CoordZ; + Quatanion[1] *= CoordZ; + } + + internal void Write(BinaryWriter writer, float CoordZ, float scale) + { + writer.Write(MMDMotion2.GetBytes(BoneName, 15)); + writer.Write((DWORD)FrameNo); + writer.Write((Single)Location[0]*scale); + writer.Write((Single)Location[1]*scale); + writer.Write((Single)Location[2] * CoordZ*scale); + writer.Write((Single)Quatanion[0] * CoordZ); + writer.Write((Single)Quatanion[1] * CoordZ); + writer.Write((Single)Quatanion[2]); + writer.Write((Single)Quatanion[3]); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + for (int k = 0; k < 4; k++) + writer.Write((byte)Interpolation[i][j][k]); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/MotionManager.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/MotionManager.cs new file mode 100644 index 000000000..53b92e2f5 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/MotionManager.cs @@ -0,0 +1,89 @@ +using System; +using System.IO; +using MikuMikuDance.Motion.Motion2; + +namespace MikuMikuDance.Motion +{ + /// + /// MikuMikuDance(MMD)モーションã®èª­ã¿è¾¼ã¿ã‚’行ã†Factory Class + /// + public static class MotionManager + { + /// + /// ファイルã‹ã‚‰MMDモーションを読ã¿è¾¼ã‚€ + /// + /// MMDモーションファイル + /// 変æ›å…ˆåº§æ¨™ç³» + /// MMDモーションオブジェクト + /// スケーリング値 + public static MMDMotion Read(string filename, CoordinateType coordinate, float scale=1.0f) + { + //フルパスå–å¾— + filename = Path.GetFullPath(filename); + //ファイルãƒã‚§ãƒƒã‚¯ + if (!File.Exists(filename)) + throw new FileNotFoundException("MMDモーションファイル:" + filename + "ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"); + //戻り値用変数 + MMDMotion result = null; + //ファイルリーダー + using (FileStream fs = new FileStream(filename, FileMode.Open)) + { + BinaryReader reader = new BinaryReader(fs); + //マジック文字列 + string magic = MMDMotion2.GetString(reader.ReadBytes(30)); + if (magic.Substring(0, 20) != "Vocaloid Motion Data") + throw new FileLoadException("MMDモーションファイルã§ã¯ã‚りã¾ã›ã‚“"); + //ãƒãƒ¼ã‚¸ãƒ§ãƒ³ + int version = Convert.ToInt32(magic.Substring(21)); + if (version == 2) + result = new MMDMotion2(); + else + throw new FileLoadException("version=" + version.ToString() + "モデルã¯å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“"); + + result.Read(reader, coordinate,scale); + if (fs.Length != fs.Position) + Console.WriteLine("警告:ファイル末尾以é™ã«ä¸æ˜Žãƒ‡ãƒ¼ã‚¿?"); + fs.Close(); + } + return result; + } + /// + /// ファイルã‹ã‚‰MMDモーションを読ã¿è¾¼ã‚€ + /// + /// MMDモーションファイル + /// スケーリング値 + /// MMDモーションオブジェクト + public static MMDMotion Read(string filename, float scale=0.1f) + { + return Read(filename, CoordinateType.LeftHandedCoordinate, scale); + } + /// + /// ファイルã¸ã®æ›¸ã出㗠+ /// + /// ファイルå + /// モーション + /// スケーリング値 + public static void Write(string filename, MMDMotion motion, float scale=1f) + { + //フルパスå–å¾— + filename = Path.GetFullPath(filename); + //ファイルリーダー + using (FileStream fs = new FileStream(filename, FileMode.Create)) + { + BinaryWriter writer = new BinaryWriter(fs); + //マジック文字列 + if (motion is MMDMotion2) + { + writer.Write(MMDMotion2.GetBytes("Vocaloid Motion Data 0002", 25)); + writer.Write((byte)0); + writer.Write(MMDMotion2.GetBytes("JKLM", 4)); + } + else + new NotImplementedException("ãã®ä»–ã®ãƒãƒ¼ã‚·ãƒ§ãƒ³ã¯æœªä½œæˆ"); + + motion.Write(writer, scale); + fs.Close(); + } + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Properties/AssemblyInfo.cs b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..2844cd0a6 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/MMDMotionLibrary/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// アセンブリã«é–¢ã™ã‚‹ä¸€èˆ¬æƒ…å ±ã¯ä»¥ä¸‹ã®å±žæ€§ã‚»ãƒƒãƒˆã‚’ã¨ãŠã—ã¦åˆ¶å¾¡ã•れã¾ã™ã€‚ +// アセンブリã«é–¢é€£ä»˜ã‘られã¦ã„る情報を変更ã™ã‚‹ã«ã¯ã€ +// ã“れらã®å±žæ€§å€¤ã‚’変更ã—ã¦ãã ã•ã„。 +[assembly: AssemblyTitle("MMDMotionLibrary")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MMDMotionLibrary")] +[assembly: AssemblyCopyright("Copyright © 2011 Wilfrem")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible ã‚’ false ã«è¨­å®šã™ã‚‹ã¨ã€ãã®åž‹ã¯ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内㧠COM コンãƒãƒ¼ãƒãƒ³ãƒˆã‹ã‚‰ +// å‚ç…§ä¸å¯èƒ½ã«ãªã‚Šã¾ã™ã€‚COM ã‹ã‚‰ã“ã®ã‚¢ã‚»ãƒ³ãƒ–リ内ã®åž‹ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹å ´åˆã¯ã€ +// ãã®åž‹ã® ComVisible 属性を true ã«è¨­å®šã—ã¦ãã ã•ã„。 +[assembly: ComVisible(false)] + +// 次㮠GUID ã¯ã€ã“ã®ãƒ—ロジェクト㌠COM ã«å…¬é–‹ã•れる場åˆã®ã€typelib ã® ID ã§ã™ +[assembly: Guid("0584ce0b-5284-42b4-9c40-1afe2917ccbd")] + +// アセンブリã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±ã¯ã€ä»¥ä¸‹ã® 4 ã¤ã®å€¤ã§æ§‹æˆã•れã¦ã„ã¾ã™: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// ã™ã¹ã¦ã®å€¤ã‚’指定ã™ã‚‹ã‹ã€ä¸‹ã®ã‚ˆã†ã« '*' を使ã£ã¦ãƒ“ルドãŠã‚ˆã³ãƒªãƒ“ジョン番å·ã‚’ +// 既定値ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2.0.0.0")] +[assembly: AssemblyFileVersion("2.0.0.0")] diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/TraceAndTestImpact.testsettings b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/TraceAndTestImpact.testsettings new file mode 100644 index 000000000..72e796275 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.MMDIKBaker/TraceAndTestImpact.testsettings @@ -0,0 +1,9 @@ + + + ã“れらã¯ã€ãƒˆãƒ¬ãƒ¼ã‚¹ãŠã‚ˆã³ãƒ†ã‚¹ãƒˆã®å½±éŸ¿ã®ãƒ†ã‚¹ãƒˆè¨­å®šã§ã™ã€‚ + + + + + + \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/.gitignore b/Assets/Scripts/3rd/mmd-for-unity-master/.gitignore new file mode 100644 index 000000000..3257b55d6 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/.gitignore @@ -0,0 +1,10 @@ +[Ll]ibrary/ +[Tt]emp/ +[Oo]bj/ + +# Autogenerated VS/MD solution and project files +*.csproj +*.unityproj +*.sln +*.asset +*.meta \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/CHANGE-LOG b/Assets/Scripts/3rd/mmd-for-unity-master/CHANGE-LOG new file mode 100644 index 000000000..2ea7ed191 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/CHANGE-LOG @@ -0,0 +1,74 @@ +-----ã“ã“ã‹ã‚‰GitHUBã§ã®é–‹ç™º----- +ã€2.0b】 +GitHUBã§é–‹ç™ºã•れãŸåˆ†ã‚’リリース. + +ã€2.0.14b】 +ConfigãŒã†ã¾ãロードã•れãªã„å ´åˆãŒã‚ã‚‹ã®ã§å¯¾å‡¦ +マイナー以é™ã®ãƒŠãƒ³ãƒãƒªãƒ³ã‚°ã¯GitHUBã®PullRequestã«æº–æ‹  + +-----ã“ã“ã¾ã§SorceForge.jpã®SVNã§é–‹ç™º----- + +ã€r240】 +ã“ã“ã¾ã§ã§å¯¾å¿œã—ãŸã“㨠+・PMXConverter + 頂点モーフ,UVモーフ,æè³ªãƒ¢ãƒ¼ãƒ•ç­‰ +・é€éŽä¸é€æ˜Ž,エッシ有無,å½±æ”¾ã¡æœ‰ç„¡,背é¢ã‚«ãƒªãƒ³ã‚°æœ‰ç„¡ã®16種類ã®ã‚·ã‚§ãƒ¼ãƒ€ã‚’使ã„分ã‘る様ã«å¯¾å¿œ + ä¸é€æ˜Žåº¦0.99ã®æ™‚ã«ä¸¡é¢æç”» + ä¸é€æ˜Žåº¦0.98ã®æ™‚ã«ã‚»ãƒ«ãƒ•シャドウをå—ã‘ãªã„マテリアル + エッジãŒç„¡ã‘れã°å½±ã‚’放ãŸãªã„ +ãƒ»ç‰©ç†æ¼”ç®—ã®ã‚°ãƒ­ãƒ¼ãƒãƒ«åº§æ¨™åŒ–等々 +・詳ã—ã„対応ã«ã¤ã„ã¦ã¯ä»¥ä¸‹ã®URLå‚ç…§ + http://sourceforge.jp/projects/mmd-for-unity/scm/svn/listCommit?skip=0 + +ã€r121】 +・[readme.html] ä½¿ã„æ–¹ã‚’追記 + Unityã§MMDã‚’å‹•ã‹ã™ä¼š ã¨ã—ã¦ä½¿ã„方を用æ„ã—ãŸã»ã†ãŒã‚ˆã•ãã†ãª. + SourceForgeã®wikiã¨ã‹ãƒã‚°ç®¡ç†ã¨ã‹æ´»ç”¨ã—ãŸã„ã¨ã“ã‚ +・[AvatarSettingScript.cs]Animator.MatchTargetã®å¼•æ•°ã«WeightMaskãŒå¿…è¦ã‚‰ã—ã„ã®ã§è¿½åŠ  + 但ã—ã€ã“ã‚Œã§æ­£ã—ã„ã®ã‹ã‚ã‹ã‚‰ãªã„ã€‚è¦æ¤œè¨¼ +・CCDIKå‘¨ã‚Šã®æ•´ç† + 余計ãªã‚³ãƒ¡ãƒ³ãƒˆãƒ»ãƒ•ァイルã®å‰Šé™¤ãªã© + +既知ã®å•題 +・Mechanim(Animator?)を使ã†ã®ã«å¿…è¦ãªAvatorãŒç”Ÿæˆã•れãªã„ãŸã‚ã€MechanimãŒä½¿ãˆãªã„ + -> http://forum.unity3d.com/threads/156951-Create-Mechanim-Avatar-in-editor-script + "in 4.0 we can only create Avatars in the ModelImporter" ã¨ã®ã“ã¨ã€‚ + ã°ãƒ¼ã˜ã‚‡ã‚“ã‚ã£ã·å¾…ã¡ã€‚ + + +ã€r120】 +MMDIKBakerã®GUI版を追加。 +コンソール+VisualStudioå¿…é ˆã ã£ãŸã‚‚ã®ã‚’ãã†ã§ã‚‚ãªã„å…·åˆã«ã€‚ + + +ã€r119】 +読ã¿è¾¼ã¿éƒ¨åˆ†ã€ç§»å‹•ã®æŠ½å‡ºã‚’å¤‰æ›´ã€‚ã‚ºãƒ¬ãŒãªããªã£ãŸæ¨¡æ§˜ + + +ã€r117】 +改善ã—ãŸã“㨠+・IKã®å®Ÿè£… +・VMD読ã¿è¾¼ã¿æ™‚ã®åº§æ¨™ä¿®æ­£ +・Unityå´ã«è¡¨ç¤ºã•れるWarningã®æ”¹å–„ + +既知ã®ãƒã‚° +・VMD読ã¿è¾¼ã¿æ™‚ã«ã‚ºãƒ¬ãŒã§ã¦ã„る(気ãŒã™ã‚‹ +・VMDã®è£œé–“ãŒUnityå´ã«å映ã•れã¦ã„ãªã„ + + +ã€1.1a-r109】 +61回もマイナーãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚¢ãƒƒãƒ—ã—ã¦ã„ã‚‹ã‚ã‘ã§ã¯ãªã„ã®ã§è¡¨è¨˜ã‚’変更 + +改善ã—ãŸã“㨠+・トゥーンシェーダーã«å¯¾å¿œ +・表情を実装 +・剛体ã«ã‚‚対応 +・一部ã€ãƒã‚°ã£ã¦ã„るモデルã«ã¤ã„ã¦ã‚‚対応 + +既知ã®ãƒã‚° +・Latå¼ãƒŸã‚¯ã®èª­ã¿è¾¼ã¿ãŒä¸å®Œå…¨ +・複数ã®è¡¨æƒ…ã‚’å‹•ã‹ã›ãªã„ +・åŒã˜è¤‡æ•°ã®ãƒ¢ãƒ‡ãƒ«ã‚’一ã¤ã®ã‚·ãƒ¼ãƒ³ã«å…¥ã‚Œã¦è¡¨æƒ…ã‚’å‹•ã‹ã™ã¨å…¨éƒ¨åŒã˜é¡”ã«ãªã‚‹ + +ã€1.61a】 +ã²ã¨ã¾ãšå‹•ã„ã¦ã„る版 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Config/Config.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Config/Config.cs new file mode 100644 index 000000000..9539ad53c --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Config/Config.cs @@ -0,0 +1,233 @@ +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using MMD.PMD; + +namespace MMD +{ + /// + /// MFU全体ã§å¿…è¦ãã†ãªã‚³ãƒ³ãƒ•ã‚£ã‚°ç®¡ç† + /// + [Serializable] + public class Config : ScriptableObject + { + static Config config_ = null; + public InspectorConfig inspector_config = null; + public PMDImportConfig pmd_config = null; + public VMDImportConfig vmd_config = null; + + private List update_list = null; + public void OnEnable() + { + if (inspector_config == null) + { + inspector_config = new InspectorConfig(); + } + if (pmd_config == null) + { + pmd_config = new PMDImportConfig(); + } + if (vmd_config == null) + { + vmd_config = new VMDImportConfig(); + } + if (update_list == null) + { + update_list = new List(); + update_list.Add(inspector_config); + update_list.Add(pmd_config); + update_list.Add(vmd_config); + } + + hideFlags = HideFlags.None; //以å‰ã®æ›¸ãæ›ãˆä¸å¯assetãŒæ®‹ã£ã¦ã„ã‚‹ã‹ã‚‚ã—れãªã„ã®ã§æ˜Žç¤ºçš„ã«æ›¸ãæ›ãˆå¯èƒ½ã‚’設定 + } + + /// + /// GUIæç”»å‡¦ç† + /// + public void OnGUI() + { + if (update_list == null) return; + update_list.ForEach((item) => + { + item.OnGUI(); + }); + + //å¤‰æ›´ç¢ºèª + if (GUI.changed) { + EditorUtility.SetDirty(config_); + } + } + + /// + /// ConfigãŒé…ç½®ã•れãŸå ´æ‰€ã‹ã‚‰ä¿å­˜å…ˆã‚’生æˆã—ã¾ã™ + /// + /// アセットä¿å­˜å…ˆã®ãƒ‘ス + public static string GetConfigPath() + { + var path = AssetDatabase.GetAllAssetPaths().Where(item => item.Contains("Config.cs")).First(); + path = path.Substring(0, path.LastIndexOf('/') + 1) + "Config.asset"; + return path; + } + + /// + /// Config.assetを読ã¿è¾¼ã¿ã¾ã™ã€‚ãªã‹ã£ãŸã‚‰ä½œã‚Šã¾ã™ã€‚ + /// + /// 読ã¿è¾¼ã‚“ã§ç”Ÿæˆã—ãŸConfigオブジェクト + public static Config LoadAndCreate() + { + if (config_ == null) + { + var path = Config.GetConfigPath(); + config_ = (Config)AssetDatabase.LoadAssetAtPath(path, typeof(Config)); + + //// ãªã‹ã£ãŸã‚‰ä½œæˆã™ã‚‹ + if (config_ == null) + { + config_ = CreateInstance(); + AssetDatabase.CreateAsset(config_, path); + EditorUtility.SetDirty(config_); + } + } + return config_; + } + } + + /// + ///インスペクタã®ã‚³ãƒ³ãƒ•ィグ + /// + [Serializable] + public class InspectorConfig : ConfigBase + { + public bool use_pmd_preload = true; + public bool use_vmd_preload = true; + + public override string GetTitle() + { + return "Inspector Config"; + } + + public override void OnGUIFunction() + { + use_pmd_preload = EditorGUILayout.Toggle("Use PMD Preload", use_pmd_preload); + use_vmd_preload = EditorGUILayout.Toggle("Use VMD Preload", use_vmd_preload); + } + + public InspectorConfig Clone() + { + return (InspectorConfig)MemberwiseClone(); + } + } + + /// + /// PMDインãƒãƒ¼ãƒˆã®ã‚³ãƒ³ãƒ•ィグ + /// + [Serializable] + public class PMDImportConfig : ConfigBase + { + public PMDConverter.ShaderType shader_type = PMDConverter.ShaderType.MMDShader; + public PMXConverter.AnimationType animation_type = PMXConverter.AnimationType.LegacyAnimation; + public bool rigidFlag = true; + public bool use_ik = true; + public float scale = 0.085f; + public bool is_pmx_base_import = true; + + public override string GetTitle() + { + return "Default PMD Import Config"; + } + + public override void OnGUIFunction() + { + shader_type = (PMDConverter.ShaderType)EditorGUILayout.EnumPopup("Shader Type", shader_type); + rigidFlag = EditorGUILayout.Toggle("Rigidbody", rigidFlag); + animation_type = (PMXConverter.AnimationType)EditorGUILayout.EnumPopup("Animation Type", animation_type); + use_ik = EditorGUILayout.Toggle("Use IK", use_ik); + scale = EditorGUILayout.Slider("Scale", scale, 0.001f, 1.0f); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.PrefixLabel(" "); + if (GUILayout.Button("Original", EditorStyles.miniButtonLeft)) { + scale = 0.085f; + } + if (GUILayout.Button("1.0", EditorStyles.miniButtonRight)) { + scale = 1.0f; + } + } + EditorGUILayout.EndHorizontal(); + is_pmx_base_import = EditorGUILayout.Toggle("Use PMX Base Import", is_pmx_base_import); + } + + public PMDImportConfig Clone() + { + return (PMDImportConfig)MemberwiseClone(); + } + } + + /// + /// VMDインãƒãƒ¼ãƒˆã®ã‚³ãƒ³ãƒ•ィグ + /// + [Serializable] + public class VMDImportConfig : ConfigBase + { + public bool createAnimationFile = false; + public int interpolationQuality = 1; + + public override string GetTitle() + { + return "Default VMD Import Config"; + } + + public override void OnGUIFunction() + { + createAnimationFile = EditorGUILayout.Toggle("Create Asset", createAnimationFile); + interpolationQuality = EditorGUILayout.IntSlider("Interpolation Quality", interpolationQuality, 1, 10); + } + + public VMDImportConfig Clone() + { + return (VMDImportConfig)MemberwiseClone(); + } + } + + /// + /// コンフィグ用ã®ãƒ™ãƒ¼ã‚¹ã‚¯ãƒ©ã‚¹ã§ã™ + /// + public class ConfigBase + { + /// + /// é–‹ã‘é–‰ã‚ã®çŠ¶æ…‹ + /// + private bool fold = true; + + /// + /// GUI処ç†ã‚’行ã„ã¾ã™ + /// + public void OnGUI() + { + var title = GetTitle(); + fold = EditorGUILayout.Foldout(fold, title); + if (fold) { + OnGUIFunction(); + } + EditorGUILayout.Space(); + } + + /// + /// ã“ã®ã‚³ãƒ³ãƒ•ィグã®ã‚¿ã‚¤ãƒˆãƒ«ã‚’å–å¾—ã—ã¾ã™ + /// + public virtual string GetTitle() + { + return ""; + } + + /// + /// GUI処ç†ã‚’行ã„ã¾ã™ + /// + public virtual void OnGUIFunction() + { + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Config/ConfigWindow.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Config/ConfigWindow.cs new file mode 100644 index 000000000..c4dc2a78d --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Config/ConfigWindow.cs @@ -0,0 +1,34 @@ +using UnityEngine; +using UnityEditor; + +namespace MMD +{ + public class ConfigWindow : EditorWindow + { + private Config config; + + [MenuItem("MMD for Unity/Config")] + public static void Init() + { + GetWindow("MFU Config"); + } + + // WindowãŒæœ‰åŠ¹åŒ–ã•れãŸã¨ã + // フォーカスãŒå¤–ã‚Œã¦æˆ»ã£ã¦ããŸã¨ãã‚„å†åº¦é–‹ã‹ã‚ŒãŸã¨ããªã© + void OnEnable() + { + if (config == null) + { + // 読ã¿è¾¼ã‚€ + config = MMD.Config.LoadAndCreate(); + } + } + + // ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã®æç”»å‡¦ç† + void OnGUI() + { + // ã‚ã¨ã¯ä»»ã›ã‚‹ + config.OnGUI(); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/ExpressionManagerEditor.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/ExpressionManagerEditor.cs new file mode 100644 index 000000000..a3ee36168 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/ExpressionManagerEditor.cs @@ -0,0 +1,104 @@ +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; + +/// +/// 表情用Inspectoræ‹¡å¼µ +/// +[CustomEditor(typeof(ExpressionManagerScript))] +public sealed class ExpressionManagerEditor : Editor +{ + /// + /// スタティックコンストラクタ + /// + static ExpressionManagerEditor() + { + skin_displays_ = new bool[Enum.GetValues(typeof(MMDSkinsScript.SkinType)).Length]; + for (int i = 0, i_max = skin_displays_.Length; i < i_max; ++i) { + skin_displays_[i] = true; + } + } + + /// + /// åˆå›žå‡¦ç† + /// + public void Awake() + { + children_ = new List[Enum.GetValues(typeof(MMDSkinsScript.SkinType)).Length]; + for (int i = 0, i_max = children_.Length; i < i_max; ++i) { + children_[i] = new List(); + } + //å­ç™»éŒ² + foreach (Transform child in Selection.activeTransform) { + MMDSkinsScript skins = child.GetComponent(); + children_[(int)skins.skinType].Add(child); + } + } + + /// + /// Inspectoræç”» + /// + public override void OnInspectorGUI() + { + ExpressionManagerScript self = (ExpressionManagerScript)target; + bool is_dirty = false; + + //mesh + self.mesh = (Mesh)EditorGUILayout.ObjectField("Mesh", self.mesh, typeof(Mesh), false); + + //skin_script + for (int i = 0, i_max = children_.Length; i < i_max; ++i) { + if (MMDSkinsScript.SkinType.Base == (MMDSkinsScript.SkinType)i) { + //Baseã ã£ãŸã‚‰ã‚¹ã‚­ãƒƒãƒ— + continue; + } + + //スキンツリータイトル + string skin_name = ((MMDSkinsScript.SkinType)i).ToString(); + skin_displays_[i] = EditorGUILayout.Foldout(skin_displays_[i], skin_name); + //スキンツリー内部 + if (skin_displays_[i]) { + //ã“ã®ã‚¹ã‚­ãƒ³ã‚’表示ã™ã‚‹ãªã‚‰ + GUIStyle style = new GUIStyle(); + style.margin.left = 10; + EditorGUILayout.BeginVertical(style); + { + //モーフオブジェクト走査 + foreach (Transform child in children_[i]) { + float value = child.localPosition.z; + value = EditorGUILayout.Slider(child.name, value, 0.0f, 1.0f); + if (child.localPosition.z != value) { + //å¤‰æ›´ãŒæŽ›ã‹ã£ãŸãªã‚‰ + //Undo登録 +#if !UNITY_4_2 //4.3ä»¥é™ + Undo.RecordObject(child, "Expression Change"); +#else + Undo.RegisterUndo(child, "Expression Change"); +#endif + //Zä½ç½®æ›´æ–° + Vector3 position = child.localPosition; + position.z = value; + child.localPosition = position; + //改変モーフオブジェクトã®Inspectoræ›´æ–° + EditorUtility.SetDirty(child.transform); + + is_dirty = true; + } + } + } + EditorGUILayout.EndVertical(); + } + + } + + if (is_dirty) { + //æ›´æ–°ãŒæœ‰ã£ãŸãªã‚‰ + //Inspectoræ›´æ–° + EditorUtility.SetDirty(target); + } + } + + private static bool[] skin_displays_; //スキンã®è¡¨ç¤º + private List[] children_; //スキン別å­ãƒ¢ãƒ¼ãƒ•オブジェクト +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/InspectorBase.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/InspectorBase.cs new file mode 100644 index 000000000..5459f6882 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/InspectorBase.cs @@ -0,0 +1,66 @@ +// Inspectorã‹ã‚‰ã‚¤ãƒ³ãƒãƒ¼ãƒˆãªã©ãŒã§ãるよã†ã«ãªã‚Šã¾ã™ +// 他スクリプトã¨ç«¶åˆã—ã¦ã—ã¾ã†æ™‚ã¯ã‚³ãƒ¡ãƒ³ãƒˆã‚¢ã‚¦ãƒˆã—ã¦ãã ã•ã„ + +#define USE_INSPECTOR + +//---------- + +#if USE_INSPECTOR +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEditor.Callbacks; +using UnityEngine; + +namespace MMD +{ + [InitializeOnLoad] + public class InspectorBase : Editor + { + static InspectorBase() + { + EntryEditorApplicationUpdate(); + } + + [DidReloadScripts] + static void OnDidReloadScripts() + { + EntryEditorApplicationUpdate(); + } + + static void EntryEditorApplicationUpdate() + { + EditorApplication.update += Update; + } + + static void Update() + { + if (Selection.objects.Length != 0) + { + string path = AssetDatabase.GetAssetPath(Selection.activeObject); + string extension = Path.GetExtension(path).ToLower(); + + if (extension == ".pmd" || extension == ".pmx") + { + //SetupScriptableObject(path); + } + else if (extension == ".vmd") + { + //SetupScriptableObject(path); + } + } + } + + static void SetupScriptableObject(string path) where T : ScriptableObjectBase + { + int count = Selection.objects.OfType().Count(); + if (count != 0) return; + T scriptableObject = ScriptableObject.CreateInstance(); + scriptableObject.assetPath = path; + Selection.activeObject = scriptableObject; + EditorUtility.UnloadUnusedAssetsImmediate(); + } + } +} + +#endif diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/PMDInspector.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/PMDInspector.cs new file mode 100644 index 000000000..5eda14bb1 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/PMDInspector.cs @@ -0,0 +1,87 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; +using MMD.PMD; +using System.IO; + +namespace MMD +{ + [CustomEditor(typeof(PMDScriptableObject))] + public class PMDInspector : Editor + { + PMDImportConfig pmd_config; + + // last selected item + private ModelAgent model_agent; + private string message = ""; + + /// + /// æœ‰åŠ¹åŒ–å‡¦ç† + /// + private void OnEnable() + { + // デフォルトコンフィグ + var config = MMD.Config.LoadAndCreate(); + pmd_config = config.pmd_config.Clone(); + + // モデル情報 + if (config.inspector_config.use_pmd_preload) + { + var obj = (PMDScriptableObject)target; + model_agent = new ModelAgent(obj.assetPath); + } + else + { + model_agent = null; + } + } + + /// + /// Inspector上ã®GUIæç”»å‡¦ç†ã‚’行ã„ã¾ã™ + /// + public override void OnInspectorGUI() + { + // GUIã®æœ‰åŠ¹åŒ– + GUI.enabled = !EditorApplication.isPlaying; + + // GUIæç”» + pmd_config.OnGUIFunction(); + + // Convertボタン + EditorGUILayout.Space(); + if (message.Length != 0) + { + GUILayout.Label(message); + } + else + { + if (GUILayout.Button("Convert to Prefab")) + { + if (null == model_agent) { + var obj = (PMDScriptableObject)target; + model_agent = new ModelAgent(obj.assetPath); + } + model_agent.CreatePrefab(pmd_config.shader_type + , pmd_config.rigidFlag + , pmd_config.animation_type + , pmd_config.use_ik + , pmd_config.scale + , pmd_config.is_pmx_base_import + ); + message = "Loading done."; + } + } + GUILayout.Space(40); + + // モデル情報 + if (model_agent == null) return; + EditorGUILayout.LabelField("Model Name"); + EditorGUILayout.LabelField(model_agent.name, EditorStyles.textField); + + EditorGUILayout.Space(); + + EditorGUILayout.LabelField("Comment"); + EditorGUILayout.LabelField(model_agent.comment, EditorStyles.textField, GUILayout.Height(300)); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/PMDScriptableObject.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/PMDScriptableObject.cs new file mode 100644 index 000000000..d1129815a --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/PMDScriptableObject.cs @@ -0,0 +1,7 @@ +using UnityEngine; +using System.Collections; + +public class PMDScriptableObject : ScriptableObjectBase +{ + +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/ScriptableObjectBase.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/ScriptableObjectBase.cs new file mode 100644 index 000000000..5298c44f0 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/ScriptableObjectBase.cs @@ -0,0 +1,10 @@ +using UnityEngine; +using System.Collections; + +public class ScriptableObjectBase +#if !(UNITY_3_5 || UNITY_3_4 || UNITY_3_3) + : ScriptableObject +#endif +{ + public string assetPath; +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/VMDInspector.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/VMDInspector.cs new file mode 100644 index 000000000..e564939ec --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/VMDInspector.cs @@ -0,0 +1,84 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; +using MMD.PMD; +using System.IO; + +namespace MMD +{ + [CustomEditor(typeof(VMDScriptableObject))] + public class VMDInspector : Editor + { + // VMD Load option + public GameObject pmdPrefab; + VMDImportConfig vmd_config; + + // last selected item + private MotionAgent motion_agent; + private string message = ""; + + /// + /// æœ‰åŠ¹åŒ–å‡¦ç† + /// + void OnEnable() + { + // デフォルトコンフィグ + var config = MMD.Config.LoadAndCreate(); + vmd_config = config.vmd_config.Clone(); + + // モデル情報 + if (config.inspector_config.use_vmd_preload) + { + var obj = (VMDScriptableObject)target; + motion_agent = new MotionAgent(obj.assetPath); + } + else + { + motion_agent = null; + } + } + + /// + /// Inspector上ã®GUIæç”»å‡¦ç†ã‚’行ã„ã¾ã™ + /// + public override void OnInspectorGUI() + { + // GUIã®æœ‰åŠ¹åŒ– + GUI.enabled = !EditorApplication.isPlaying; + + pmdPrefab = (GameObject)EditorGUILayout.ObjectField("PMD Prefab", pmdPrefab, typeof(Object), false); + vmd_config.OnGUIFunction(); + + // Convertボタン + EditorGUILayout.Space(); + if (message.Length != 0) + { + GUILayout.Label(message); + } + else + { + bool gui_enabled_old = GUI.enabled; + GUI.enabled = (null != pmdPrefab); + if (GUILayout.Button("Convert")) + { + if (null == motion_agent) { + var obj = (VMDScriptableObject)target; + motion_agent = new MotionAgent(obj.assetPath); + } + motion_agent.CreateAnimationClip(pmdPrefab + , vmd_config.createAnimationFile + , vmd_config.interpolationQuality + ); + message = "Loading done."; + } + GUI.enabled = gui_enabled_old; + } + GUILayout.Space(40); + + // モデル情報 + if (motion_agent == null) return; + EditorGUILayout.LabelField("Model Name"); + EditorGUILayout.LabelField(motion_agent.model_name, EditorStyles.textField); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/VMDScriptableObject.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/VMDScriptableObject.cs new file mode 100644 index 000000000..3c43d68b2 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/Inspector/VMDScriptableObject.cs @@ -0,0 +1,7 @@ +using UnityEngine; +using System.Collections; + +public class VMDScriptableObject : ScriptableObjectBase +{ + +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDEngineEditor.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDEngineEditor.cs new file mode 100644 index 000000000..01934f0de --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDEngineEditor.cs @@ -0,0 +1,562 @@ +using UnityEngine; +using UnityEditor; +using System; +using System.Collections.Generic; +using System.Linq; + +/// +/// MMDEngine用Inspectoræ‹¡å¼µ +/// +[CustomEditor(typeof(MMDEngine))] +public sealed class MMDEngineEditor : Editor +{ + /// + /// スタティックコンストラクタ + /// + static MMDEngineEditor() + { + ik_list_display_ = false; + shader_display_ = false; + } + + /// + /// åˆå›žå‡¦ç† + /// + public void Awake() + { + } + + /// + /// Inspectoræç”» + /// + public override void OnInspectorGUI() + { + bool is_dirty = false; + + is_dirty = OnInspectorGUIforOutlineWidth() || is_dirty; + is_dirty = OnInspectorGUIforUseRigidbody() || is_dirty; + is_dirty = OnInspectorGUIforIkList() || is_dirty; + is_dirty = OnInspectorGUIforShaderList() || is_dirty; + is_dirty = OnInspectorGUIforRenderQueue() || is_dirty; + + if (is_dirty) { + //æ›´æ–°ãŒæœ‰ã£ãŸãªã‚‰ + //Inspectoræ›´æ–° + EditorUtility.SetDirty(target); + } + } + + /// + /// エッジ幅ã®ç‚ºã®Inspectoræç”» + /// + /// æ›´æ–°ãŒæœ‰ã£ãŸã‹(true:更新有り, false:未更新) + private bool OnInspectorGUIforOutlineWidth() + { + MMDEngine self = (MMDEngine)target; + bool is_update = false; + +#if !MFU_DISABLE_LEGACY_DATA_SUPPORT + if (0 == self.material_outline_widths.Length) { + //material_outline_widthsãŒè¨­å®šã•れã¦ã„ãªã„ãªã‚‰(昔ã®å¤‰æ›ãƒ‡ãƒ¼ã‚¿) + Material[] materials = GetMaterials(self); + if (0 < materials.Length) { + //ãƒžãƒ†ãƒªã‚¢ãƒ«ãŒæœ‰ã‚Šã€ä»Šã®ã‚¨ãƒƒã‚¸å¹…ãŒ0.0fã§ç„¡ã„ãªã‚‰ + //データ生æˆã‚’試ã¿ã‚‹ + self.material_outline_widths = materials.Select(x=>x.GetFloat("_OutlineWidth")).ToArray(); + } + } +#endif + + float outline_width = self.outline_width; + outline_width = EditorGUILayout.Slider("Outline Width", outline_width, 0.0f, 2.0f); + if (self.outline_width != outline_width) { + //å¤‰æ›´ãŒæŽ›ã‹ã£ãŸãªã‚‰ + Material[] materials = GetMaterials(self); + //Undo登録 + var record_objects = materials.Select(x=>(UnityEngine.Object)x) //マテリアル全ã¦ã¨ + .Concat(new UnityEngine.Object[]{self}) //UnityEngine + .ToArray(); +#if !UNITY_4_2 //4.3ä»¥é™ + Undo.RecordObjects(record_objects, "Outline Width Change"); +#else + Undo.RegisterUndo(record_objects, "Outline Width Change"); +#endif + //æ›´æ–° + const float c_default_scale = 0.085f; //0.085fã®æ™‚ã«MMDã¨ä¸€è‡´ã™ã‚‹æ§˜ã«ã—ã¦ã„ã‚‹ã®ã§ã€ãれ以外ãªã‚‰è£œæ­£ + self.outline_width = outline_width; + foreach (var i in Enumerable.Range(0, materials.Length) + .Select(x=>new {material = materials[x], edge_size = self.material_outline_widths[x]})) { + i.material.SetFloat("_OutlineWidth", i.edge_size * outline_width * self.scale / c_default_scale); + } + + is_update = true; + } + + return is_update; + } + + /// + /// リジッドボティ使用ã®ç‚ºã®Inspectoræç”» + /// + /// æ›´æ–°ãŒæœ‰ã£ãŸã‹(true:更新有り, false:未更新) + private bool OnInspectorGUIforUseRigidbody() + { + MMDEngine self = (MMDEngine)target; + bool is_update = false; + + bool use_rigidbody = self.useRigidbody; + use_rigidbody = EditorGUILayout.Toggle("Use Rigidbody", use_rigidbody); + if (self.useRigidbody != use_rigidbody) { + //å¤‰æ›´ãŒæŽ›ã‹ã£ãŸãªã‚‰ + //Undo登録 +#if !UNITY_4_2 //4.3ä»¥é™ + Undo.RecordObject(self, "Use Rigidbody Change"); +#else + Undo.RegisterUndo(self, "Use Rigidbody Change"); +#endif + //æ›´æ–° + self.useRigidbody = use_rigidbody; + + is_update = true; + } + return is_update; + } + + /// + /// IKリストã®ç‚ºã®Inspectoræç”» + /// + /// æ›´æ–°ãŒæœ‰ã£ãŸã‹(true:更新有り, false:未更新) + private bool OnInspectorGUIforIkList() + { + MMDEngine self = (MMDEngine)target; + bool is_update = false; + + //IKリストツリータイトル + ik_list_display_ = EditorGUILayout.Foldout(ik_list_display_, "IK List"); + //IKリストツリー内部 + if (ik_list_display_) { + //IKリストを表示ã™ã‚‹ãªã‚‰ + GUIStyle style = new GUIStyle(); + style.margin.left = 10; + EditorGUILayout.BeginVertical(style); + { + foreach (CCDIKSolver ik in self.ik_list) { + bool enabled = ik.enabled; + enabled = EditorGUILayout.Toggle(ik.name, enabled); + if (ik.enabled != enabled) { + //å¤‰æ›´ãŒæŽ›ã‹ã£ãŸãªã‚‰ + //Undo登録 +#if !UNITY_4_2 //4.3ä»¥é™ + Undo.RecordObject(ik, "Enabled Change"); +#else + Undo.RegisterUndo(ik, "Enabled Change"); +#endif + //æ›´æ–° + ik.enabled = enabled; + //改変ã—ãŸIKã®Inspectoræ›´æ–° + EditorUtility.SetDirty(ik); + + is_update = true; + } + } + } + EditorGUILayout.EndVertical(); + } + return is_update; + } + + /// + /// シェーダーリストã®ç‚ºã®Inspectoræç”» + /// + /// æ›´æ–°ãŒæœ‰ã£ãŸã‹(true:更新有り, false:未更新) + private bool OnInspectorGUIforShaderList() + { + MMDEngine self = (MMDEngine)target; + bool is_update = false; + + //シェーダーリストタイトル + shader_display_ = EditorGUILayout.Foldout(shader_display_, "Shader List"); + //シェーダーリスト内部 + if (shader_display_) { + //シェーダーリストを表示ã™ã‚‹ãªã‚‰ + Material[] materials = GetMaterials(self); + GUIStyle style = new GUIStyle(); + style.margin.left = 10; + EditorGUILayout.BeginVertical(style); + { + //タイトル + EditorGUILayout.BeginHorizontal(); + { + //ラベル + EditorGUILayout.LabelField("Material", GUILayout.Width(64)); + //シェーダー + EditorGUILayout.LabelField(new GUIContent("Tr", "Transparent"), GUILayout.Width(20)); + EditorGUILayout.LabelField(new GUIContent("Eg", "Edge"), GUILayout.Width(20)); + EditorGUILayout.LabelField(new GUIContent("Rv", "Reversible"), GUILayout.Width(20)); + EditorGUILayout.LabelField(new GUIContent("Cs", "CastShadow"), GUILayout.Width(20)); +#if MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER //å½±å—ã‘ç„¡ã—ã®ã‚·ã‚§ãƒ¼ãƒ€ã¯ã¾ã ç„¡ã„ã®ã§ç„¡åŠ¹åŒ– + EditorGUILayout.LabelField(new GUIContent("Rs", "ReceiveShadow"), GUILayout.Width(20)); +#endif //MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER + EditorGUILayout.LabelField("", GUILayout.Width(20)); + EditorGUILayout.LabelField(new GUIContent("Hi", "Highlight"), GUILayout.Width(20)); + EditorGUILayout.LabelField(new GUIContent("Hd", "Hidden"), GUILayout.Width(20)); + } + EditorGUILayout.EndHorizontal(); + + //æç”»ç”¨é…列 + var parameter_table = new[]{new {flag=ShaderFlag.Transparent, reverse=false} + , new {flag=ShaderFlag.Outline, reverse=false} + , new {flag=ShaderFlag.CullBack, reverse=true} //背景カリングON/OFFã¯ã‚ã‹ã‚Šè¾›ã„ã®ã§ã€MMDã®æ§˜ã«ä¸¡é¢æç”»ON/OFFã§æ‰±ã† + , new {flag=ShaderFlag.NoCastShadow, reverse=true} //影放ãŸãªã„ON/OFFã®2é‡å¦å®šã‚’æ­¢ã‚ã¦å½±æ”¾ã¤ON/OFFã§æ‰±ã† +#if MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER //å½±å—ã‘ç„¡ã—ã®ã‚·ã‚§ãƒ¼ãƒ€ã¯ã¾ã ç„¡ã„ã®ã§ç„¡åŠ¹åŒ– + , new {flag=ShaderFlag.NoReceiveShadow, reverse=true} //å½±å—ã‘ãªã„ON/OFFã®2é‡å¦å®šã‚’æ­¢ã‚ã¦å½±å—ã‘ã‚‹ON/OFFã§æ‰±ã† +#endif //MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER + , new {flag=(ShaderFlag)0, reverse=false} + , new {flag=ShaderFlag.Highlight, reverse=false} + , new {flag=ShaderFlag.Hidden, reverse=false} + }; + //マテリアル + for (int i = 0, i_max = materials.Length; i < i_max; ++i) { + Material material = materials[i]; + + EditorGUILayout.BeginHorizontal(); + { + //ラベル + EditorGUILayout.LabelField(new GUIContent(material.name, material.name), GUILayout.Width(64)); + //シェーダー + if (IsMmdShader(material)) { + //MMDシェーダーãªã‚‰ + bool is_change_shader = false; + ShaderFlag flag = AnalyzeShaderFlag(material); + foreach (var param in parameter_table) { + if (0 != param.flag) { + //æç”»ç”¨ + bool enable_old = 0 != ((int)flag & (int)param.flag); + if (param.reverse) { + enable_old = !enable_old; + } + bool enable = EditorGUILayout.Toggle(enable_old, GUILayout.Width(20)); + if (enable_old != enable) { + //æ›´æ–° + if (param.reverse) { + enable = !enable; + } + flag = (ShaderFlag)((int)flag ^ (int)param.flag); + + is_change_shader = true; + } + } else { + //スペース用 + EditorGUILayout.LabelField("", GUILayout.Width(20)); + } + } + if (is_change_shader) { + //å¤‰æ›´ãŒæŽ›ã‹ã£ãŸãªã‚‰ + //Undo登録 +#if !UNITY_4_2 //4.3ä»¥é™ + Undo.RecordObject(material, "Shader Change"); +#else + Undo.RegisterUndo(material, "Shader Change"); +#endif + + int render_queue = ((self.enable_render_queue)? self.render_queue_value + i: -1); + SetShader(material, flag, render_queue); + is_update = true; + } + } + } + EditorGUILayout.EndHorizontal(); + } + } + EditorGUILayout.EndVertical(); + } + return is_update; + } + + /// + /// カスタムレンダーキューã®ç‚ºã®Inspectoræç”» + /// + /// æ›´æ–°ãŒæœ‰ã£ãŸã‹(true:更新有り, false:未更新) + private bool OnInspectorGUIforRenderQueue() + { + MMDEngine self = (MMDEngine)target; + bool is_update = false; + +#if !MFU_DISABLE_LEGACY_DATA_SUPPORT + if ((false == self.enable_render_queue) && (0 == self.render_queue_value)) { + //カスタムレンダーキュー関連ãŒè¨­å®šã•れã¦ã„ãªã„ãªã‚‰(昔ã®å¤‰æ›ãƒ‡ãƒ¼ã‚¿) + //無効状態ã§åˆæœŸåŒ– + self.enable_render_queue = false; + const int c_render_queue_transparent = 3000; + self.render_queue_value = c_render_queue_transparent; + } +#endif + + bool enable_render_queue = self.enable_render_queue; + enable_render_queue = EditorGUILayout.Toggle("Render Queue", enable_render_queue); + if (self.enable_render_queue != enable_render_queue) { + //å¤‰æ›´ãŒæŽ›ã‹ã£ãŸãªã‚‰ + is_update = true; + } + int render_queue_value = -1; + if (enable_render_queue) { + //有効ãªã‚‰ + render_queue_value = self.render_queue_value; + render_queue_value = EditorGUILayout.IntField("Render Queue Value", render_queue_value); + if (self.render_queue_value != render_queue_value) { + //å¤‰æ›´ãŒæŽ›ã‹ã£ãŸãªã‚‰ + is_update = true; + } + } + + if (is_update) { + //å¤‰æ›´ãŒæŽ›ã‹ã£ãŸãªã‚‰ + Material[] materials = GetMaterials(self); + //Undo登録 + var record_objects = materials.Select(x=>(UnityEngine.Object)x) //マテリアル全ã¦ã¨ + .Concat(new UnityEngine.Object[]{self}) //UnityEngine + .ToArray(); +#if !UNITY_4_2 //4.3ä»¥é™ + Undo.RecordObjects(record_objects, "Render Queue Change"); +#else + Undo.RegisterUndo(record_objects, "Render Queue Change"); +#endif + //æ›´æ–° + self.enable_render_queue = enable_render_queue; + if (enable_render_queue) { + //有効化 + self.render_queue_value = render_queue_value; + for (int i = 0, i_max = materials.Length; i < i_max; ++i) { + var material = materials[i]; + ShaderFlag flag = AnalyzeShaderFlag(material); + if (0 != (flag & ShaderFlag.MmdShader)) { + //Mmdシェーダーãªã‚‰ + //カスタムレンダーキュー + if (0 != (flag & ShaderFlag.Transparent)) { + //é€éŽãªã‚‰ + //マテリアル順ã«ã‚«ã‚¹ã‚¿ãƒ ãƒ¬ãƒ³ãƒ€ãƒ¼ã‚­ãƒ¥ãƒ¼ã‚’設定 + material.renderQueue = render_queue_value + i; + } else { + //ä¸é€æ˜Žãªã‚‰ + //カスタムレンダーキューを解除 + material.renderQueue = -1; + } + } + } + } else { + //無効化 + foreach (var material in materials) { + ShaderFlag flag = AnalyzeShaderFlag(material); + if (0 != (flag & ShaderFlag.MmdShader)) { + //Mmdシェーダーãªã‚‰ + //カスタムレンダーキューを解除 + material.renderQueue = -1; + } + } + } + } + + return is_update; + } + + /// + /// MMDã‚·ã‚§ãƒ¼ãƒ€ãƒ¼ç¢ºèª + /// + /// MMDシェーダー㋠+ /// マテリアル + static bool IsMmdShader(Material material) { + bool result = false; + if (null != material.shader) { + //シェーダーをæŒã£ã¦ã„ã‚‹ãªã‚‰ + if (0 == material.shader.name.IndexOf("MMD/")) { + //Mfuシェーダーãªã‚‰ + if (-1 == material.shader.name.IndexOf("MMD/HalfLambertOutline")) { + //エッジ付ããƒãƒ¼ãƒ•ランãƒãƒ¼ãƒˆã‚·ã‚§ãƒ¼ãƒ€ãƒ¼ã§ç„¡ã„ãªã‚‰ + result = true; + } + } + } + return result; + } + + /// + /// シェーダーフラグã®è§£æž + /// + /// シェーダーフラグ + /// マテリアル + static ShaderFlag AnalyzeShaderFlag(Material material) { + ShaderFlag result = ShaderFlag.MmdShader; + string name = material.shader.name; + if (0 == name.IndexOf("MMD/Dummy")) { + //デãƒãƒƒã‚°(ãƒã‚¤ãƒ©ã‚¤ãƒˆãƒ»éžè¡¨ç¤º)シェーダーãªã‚‰ + //_DummyOriginalShaderTypeパラメータã«åŸ‹ã‚込んã§ã„ã‚‹ã®ã§ãれを使用 + float original_shader_type = 0.0f; + if (material.HasProperty("_DummyOriginalShaderType")) { + original_shader_type = material.GetFloat("_DummyOriginalShaderType"); + } + result = (ShaderFlag)(int)original_shader_type; + //デãƒãƒƒã‚°ã‚«ãƒ©ãƒ¼ã‹ã‚‰ãƒ‡ãƒãƒƒã‚°å†…ã®ã‚·ã‚§ãƒ¼ãƒ€åˆ¤åˆ¥ + Color color; + if (material.HasProperty("_DummyColor")) { + color = material.GetColor("_DummyColor"); + } else { + color = new Color(1.0f, 1.0f, 1.0f, 0.0f); + } + if (0.0f < color.a) { + //é€éŽã§ç„¡ã„ãªã‚‰ + //ãƒã‚¤ãƒ©ã‚¤ãƒˆ + result = result | ShaderFlag.Highlight; + } else { + //é€éŽãªã‚‰ + //éžè¡¨ç¤º + result = result | ShaderFlag.Hidden; + } + } else if (0 == name.IndexOf("MMD/")) { + //通常シェーダーãªã‚‰ + if (-1 != name.IndexOf("Transparent/")) { + //é€éŽãªã‚‰ + result = (result | ShaderFlag.Transparent); + } + if (-1 != name.IndexOf("-Outline")) { + //エッジ有りãªã‚‰ + result = (result | ShaderFlag.Outline); + } + if (-1 != name.IndexOf("-CullBack")) { + //背é¢ã‚«ãƒªãƒ³ã‚°ãªã‚‰ + result = (result | ShaderFlag.CullBack); + } + if (-1 != name.IndexOf("-NoCastShadow")) { + //影を放ãŸãªã„ãªã‚‰ + result = (result | ShaderFlag.NoCastShadow); + } +#if MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER //å½±å—ã‘ç„¡ã—ã®ã‚·ã‚§ãƒ¼ãƒ€ã¯ã¾ã ç„¡ã„ã®ã§ç„¡åŠ¹åŒ– + if (-1 != name.IndexOf("-NoReceiveShadow")) { + //å½±å—ã‘ç„¡ã—ãªã‚‰ + result = (result | ShaderFlag.NoReceiveShadow); + } +#endif //MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER + } else { + //MMDシェーダー以外ãªã‚‰ + result = (ShaderFlag)0; + } + return result; + } + + /// + /// シェーダーフラグã‹ã‚‰ã®ã‚·ã‚§ãƒ¼ãƒ€ãƒ¼è¨­å®š + /// + /// マテリアル + /// シェーダーフラグ + /// é€éŽã®å ´åˆã«è¨­å®šã™ã‚‹ãƒ¬ãƒ³ãƒ€ãƒ¼ã‚­ãƒ¥ãƒ¼ + static void SetShader(Material material, ShaderFlag flag, int render_queue) { + if (0 != (flag & ShaderFlag.MmdShader)) { + //Mmdシェーダーãªã‚‰ + material.shader = CreateShaderFromShaderFlag(flag); + if (0 != (flag & ShaderFlag.Hidden)) { + //éžè¡¨ç¤ºãªã‚‰ + float original_shader_type = (float)(int)flag; + material.SetFloat("_DummyOriginalShaderType", original_shader_type); + material.SetColor("_DummyColor", new Color(1.0f, 1.0f, 1.0f, 0.0f)); + } else if (0 != (flag & ShaderFlag.Highlight)) { + //ãƒã‚¤ãƒ©ã‚¤ãƒˆãªã‚‰ + float original_shader_type = (float)(int)flag; + material.SetFloat("_DummyOriginalShaderType", original_shader_type); + material.SetColor("_DummyColor", new Color(1.0f, 0.0f, 1.0f, 1.0f)); + } + //カスタムレンダーキュー + if (0 != (flag & ShaderFlag.Transparent)) { + //é€éŽãªã‚‰ + //マテリアル順ã«ã‚«ã‚¹ã‚¿ãƒ ãƒ¬ãƒ³ãƒ€ãƒ¼ã‚­ãƒ¥ãƒ¼ã‚’設定 + material.renderQueue = render_queue; + } else { + //ä¸é€æ˜Žãªã‚‰ + //カスタムレンダーキューを解除 + material.renderQueue = -1; + } + } + } + + /// + /// シェーダーフラグã‹ã‚‰ã®ã‚·ã‚§ãƒ¼ãƒ€ãƒ¼ä½œæˆ + /// + /// シェーダー + /// シェーダーフラグ + static Shader CreateShaderFromShaderFlag(ShaderFlag flag) { + Shader result; + string path = "MMD/"; + if (0 != (flag & ShaderFlag.Transparent)) { + path += "Transparent/"; + } + path += "PMDMaterial"; + if (0 != (flag & ShaderFlag.Outline)) { + path += "-with-Outline"; + } + if (0 != (flag & ShaderFlag.CullBack)) { + path += "-CullBack"; + } + if (0 != (flag & ShaderFlag.NoCastShadow)) { + path += "-NoCastShadow"; + } +#if MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER //å½±å—ã‘ç„¡ã—ã®ã‚·ã‚§ãƒ¼ãƒ€ã¯ã¾ã ç„¡ã„ã®ã§ç„¡åŠ¹åŒ– + if (0 != (flag & ShaderFlag.NoReceiveShadow)) { + path += "-NoReceiveShadow"; + } +#endif //MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER + result = Shader.Find(path); + + //デãƒãƒƒã‚°ç³» + if (0 != (flag & ShaderFlag.Highlight)) { + //ãƒã‚¤ãƒ©ã‚¤ãƒˆ + string original_shader_name = result.name; + result = Shader.Find("MMD/Dummy"); + result.name = original_shader_name + "+Highlight"; + } else if (0 != (flag & ShaderFlag.Hidden)) { + //éžè¡¨ç¤º + string original_shader_name = result.name; + result = Shader.Find("MMD/Dummy"); + result.name = original_shader_name + "+Hidden"; + } + + return result; + } + + /// + /// 本æ¥ã®é †åºã§æè³ªä¸€è¦§ã®å–å¾— + /// + /// æè³ªä¸€è¦§ + /// æè³ªã‚’å–å¾—ã™ã‚‹MMDEngine + static Material[] GetMaterials(MMDEngine engine) + { + SkinnedMeshRenderer[] renderers = engine.GetComponentsInChildren(); + Material[] result = renderers.SelectMany(x=>x.sharedMaterials).Distinct().ToArray(); + if (1 < renderers.Length) { + //rendererãŒè¤‡æ•°æœ‰ã‚‹(≒PMX)ãªã‚‰ + //PMXã§ã¯åå‰ã®å…ˆé ­ã«ã¯ãƒžãƒ†ãƒªã‚¢ãƒ«ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãŒæœ‰ã‚‹ã®ã§ãれをå‚考ã«ã‚½ãƒ¼ãƒˆ + //PMDã§ã¯rendererãŒ1ã¤ã—ã‹ç„¡ãã€ã‹ã¤ã‚½ãƒ¼ãƒˆæ¸ˆã¿ã®ç‚ºä¸è¦ + System.Array.Sort(result, (x,y)=>{ + string x_name = x.name.Substring(0, x.name.IndexOf('_')); + string y_name = y.name.Substring(0, y.name.IndexOf('_')); + int x_int, y_int; + Int32.TryParse(x_name, out x_int); + Int32.TryParse(y_name, out y_int); + return x_int - y_int; + }); + } + return result; + } + + [Flags] + private enum ShaderFlag { + MmdShader = 1<< 0, //MMDシェーダー + Transparent = 1<< 1, //é€éŽ + Outline = 1<< 2, //エッジ有り + CullBack = 1<< 3, //背é¢ã‚«ãƒªãƒ³ã‚° + NoCastShadow = 1<< 4, //影放ã¡ç„¡ã— + NoReceiveShadow = 1<< 5, //å½±å—ã‘ç„¡ã— + Highlight = 1<< 6, //ãƒã‚¤ãƒ©ã‚¤ãƒˆ + Hidden = 1<< 7, //éžè¡¨ç¤º + } + + private static bool ik_list_display_; //IKリストã®è¡¨ç¤º + private static bool shader_display_; //シェーダーリストã®è¡¨ç¤º +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/LoadedWindow.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/LoadedWindow.cs new file mode 100644 index 000000000..3046d6073 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/LoadedWindow.cs @@ -0,0 +1,37 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; + +public class LoadedWindow : EditorWindow +{ + /// + /// メッセージ用テキスト + /// + public string Text { get; set; } + + const int width = 400; + + const int height = 300; + + /// + /// åˆæœŸåŒ– + /// + /// ウィンドウ + public static LoadedWindow Init() + { + var window = EditorWindow.GetWindow("PMD file loaded!") as LoadedWindow; + var pos = window.position; + pos.height = LoadedWindow.height; + pos.width = LoadedWindow.width; + window.position = pos; + return window; + } + + void OnGUI() + { + EditorGUI.TextArea(new Rect(0, 0, LoadedWindow.width, LoadedWindow.height - 30), this.Text); + + if (GUI.Button(new Rect(0, height - 30, LoadedWindow.width, 30), "OK")) + Close(); + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/PMDLoaderWindow.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/PMDLoaderWindow.cs new file mode 100644 index 000000000..cc13aa727 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/PMDLoaderWindow.cs @@ -0,0 +1,61 @@ +using UnityEngine; +using System.Collections; +using UnityEditor; + +public class PMDLoaderWindow : EditorWindow { + Object pmdFile; + MMD.PMDImportConfig pmd_config; + + [MenuItem("MMD for Unity/PMD Loader")] + static void Init() { + var window = (PMDLoaderWindow)EditorWindow.GetWindow(true, "PMDLoader"); + window.Show(); + } + + void OnEnable() + { + // デフォルトコンフィグ + pmdFile = null; + pmd_config = MMD.Config.LoadAndCreate().pmd_config.Clone(); + } + + void OnGUI() { + // GUIã®æœ‰åŠ¹åŒ– + GUI.enabled = !EditorApplication.isPlaying; + + // GUIæç”» + pmdFile = EditorGUILayout.ObjectField("PMD File" , pmdFile, typeof(Object), false); + pmd_config.OnGUIFunction(); + + { + bool gui_enabled_old = GUI.enabled; + GUI.enabled = !EditorApplication.isPlaying && (pmdFile != null); + if (GUILayout.Button("Convert")) { + LoadModel(); + pmdFile = null; // 読ã¿çµ‚ã‚ã£ãŸã®ã§ç©ºã«ã™ã‚‹ + } + GUI.enabled = gui_enabled_old; + } + } + + void LoadModel() { + string file_path = AssetDatabase.GetAssetPath(pmdFile); + MMD.ModelAgent model_agent = new MMD.ModelAgent(file_path); + model_agent.CreatePrefab(pmd_config.shader_type + , pmd_config.rigidFlag + , pmd_config.animation_type + , pmd_config.use_ik + , pmd_config.scale + , pmd_config.is_pmx_base_import + ); + + // 読ã¿è¾¼ã¿å®Œäº†ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ + var window = LoadedWindow.Init(); + window.Text = string.Format( + "----- model name -----\n{0}\n\n----- comment -----\n{1}", + model_agent.name, + model_agent.comment + ); + window.Show(); + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/AlphaReadableTexture.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/AlphaReadableTexture.cs new file mode 100644 index 000000000..ca5e0a543 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/AlphaReadableTexture.cs @@ -0,0 +1,123 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Linq; + +public class AlphaReadableTexture : System.IDisposable { + + /// + /// コンストラクタ + /// + /// テクスãƒãƒ£ç›¸å¯¾ãƒ‘スリスト + /// カレントディレクトリ("/"終ã‚りã€ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®ç›¸å¯¾ãƒ‘ス基点) + /// è§£æžä½œæ¥­ç”¨ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª("/"終ã‚りã€ã“ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ä¸‹ã«è§£æžä½œæ¥­ç”¨ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’作りã¾ã™) + public AlphaReadableTexture(string[] texture_path_list, string current_directory, string temporary_directory) + { + texture_path_list_ = texture_path_list; + current_directory_ = current_directory; + temporary_directory_ = temporary_directory + directory_name + "/"; + + //テクスãƒãƒ£ä½œæˆ + foreach (string texture_path in texture_path_list_.Where(x=>!string.IsNullOrEmpty(x)).Distinct()) { + CreateReadableTexture(texture_path); + } + AssetDatabase.Refresh(); + //テクスãƒãƒ£å–å¾— + textures_ = texture_path_list_.Select(x=>GetReadableTexture(x)).ToArray(); + } + + /// + /// 読ã¿è¾¼ã¿å¯èƒ½ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®å–å¾— + /// + /// 読ã¿è¾¼ã¿å¯èƒ½ãƒ†ã‚¯ã‚¹ãƒãƒ£ + public Texture2D[] textures {get{return textures_;}} + + /// + /// Disposeインターフェース + /// + public void Dispose() + { + //テクスãƒãƒ£ç ´æ£„ + foreach (string texture_path in texture_path_list_.Where(x=>!string.IsNullOrEmpty(x)).Distinct()) { + DeleteReadableTexture(texture_path); + } + //ディレクトリã®ç ´æ£„ + string path = Application.dataPath + "/../" + temporary_directory_; //"Asset/"ãŒè¢«ã‚‹ã®ã§1階層上ãŒã‚‹ + if (System.IO.Directory.Exists(path)) { + System.IO.Directory.Delete(path, true); + } + } + + /// + /// è§£æžå¯¾è±¡ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªåã®å–å¾— + /// + /// The directory_name. + public static string directory_name {get{return "AlphaReadableTextureDirectory.MmdForUnity";}} + + /// + /// 読ã¿è¾¼ã¿å¯èƒ½ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®ä½œæˆ + /// + /// テクスãƒãƒ£ãƒ‘ス + private void CreateReadableTexture(string texture_path) + { + if (!string.IsNullOrEmpty(texture_path)) { + string base_texture_path = current_directory_ + texture_path; + string readable_texture_path = temporary_directory_ + texture_path; + CreateDirectoryPath(System.IO.Path.GetDirectoryName(readable_texture_path)); + bool is_copy_success = AssetDatabase.CopyAsset(base_texture_path, readable_texture_path); + if (!is_copy_success) { + throw new System.InvalidOperationException(); + } + } + } + + /// + /// 読ã¿è¾¼ã¿å¯èƒ½ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®å–å¾— + /// + /// 読ã¿è¾¼ã¿å¯èƒ½ãƒ†ã‚¯ã‚¹ãƒãƒ£ + /// テクスãƒãƒ£ãƒ‘ス + private Texture2D GetReadableTexture(string texture_path) + { + Texture2D result = null; + if (!string.IsNullOrEmpty(texture_path)) { + string readable_texture_path = temporary_directory_ + texture_path; + result = (Texture2D)AssetDatabase.LoadAssetAtPath(readable_texture_path, typeof(Texture2D)); + } + return result; + } + + /// + /// 読ã¿è¾¼ã¿å¯èƒ½ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®å‰Šé™¤ + /// + /// テクスãƒãƒ£ãƒ‘ス + private void DeleteReadableTexture(string texture_path) + { + if (!string.IsNullOrEmpty(texture_path)) { + string readable_texture_path = temporary_directory_ + texture_path; + AssetDatabase.DeleteAsset(readable_texture_path); + } + } + + /// + /// ディレクトリã®ä½œæˆ(親ディレクトリãŒç„¡ã‘れã°å†å¸°çš„ã«ä½œæˆ) + /// + /// ディレクトリパス + private static void CreateDirectoryPath(string path) + { + //è¦ªãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªä½œæˆ + string parent_path = System.IO.Path.GetDirectoryName(path); + if (!string.IsNullOrEmpty(parent_path) && !System.IO.Directory.Exists(parent_path)) { + CreateDirectoryPath(parent_path); + } + //ã‚«ãƒ¬ãƒ³ãƒˆãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªä½œæˆ + if (!System.IO.Directory.Exists(path)) { + string name = System.IO.Path.GetFileName(path); + AssetDatabase.CreateFolder(parent_path, name); + } + } + + private Texture2D[] textures_; //読ã¿è¾¼ã¿å¯èƒ½ãƒ†ã‚¯ã‚¹ãƒãƒ£ + private string[] texture_path_list_; //è§£æžã™ã‚‹ãƒ†ã‚¯ã‚¹ãƒãƒ£ãƒªã‚¹ãƒˆ + private string current_directory_; //カレントディレクトリ + private string temporary_directory_; //è§£æžä½œæ¥­ç”¨ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒª +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/AlphaReadableTextureDirectoryImporter.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/AlphaReadableTextureDirectoryImporter.cs new file mode 100644 index 000000000..a092297a1 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/AlphaReadableTextureDirectoryImporter.cs @@ -0,0 +1,28 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +public class AlphaReadableTextureDirectoryImporter : AssetPostprocessor { + + /// + /// テクスãƒãƒ£ãƒ—リプロセッサ + /// + void OnPreprocessTexture() { + if (-1 != assetPath.IndexOf(AlphaReadableTexture.directory_name)) { + //MmdForUnityã®è§£æžç”¨ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãªã‚‰ + TextureImporter importer = (TextureImporter)assetImporter; + importer.isReadable = true; //読ã¿è¾¼ã¿å¯èƒ½ã¨ã™ã‚‹ + //importer.textureFormat = TextureImporterFormat.Alpha8; //アルファã®ã¿ + importer.mipmapEnabled = false; //mipmapを作æˆã—ãªã„ + if (importer.DoesSourceTextureHaveAlpha()) { + //ã‚¢ãƒ«ãƒ•ã‚¡ãŒæœ‰ã‚Œã° + //é€éŽãƒ•ラグを立ã¦ã‚‹ + importer.alphaIsTransparency = true; + } else { + //アルファãŒç„¡ã‘れ㰠+ //è§£åƒåº¦ã‚’最å°åŒ– + importer.maxTextureSize = 1; + } + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/AvatarSettingScript.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/AvatarSettingScript.cs new file mode 100644 index 000000000..b390e094b --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/AvatarSettingScript.cs @@ -0,0 +1,359 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Linq; + +// ã‚¢ãƒã‚¿ãƒ¼ã®è¨­å®šã‚’行ã†ã‚¹ã‚¯ãƒªãƒ—ト +public class AvatarSettingScript +{ + /// + /// デフォルトコンストラクタ + /// + /// + /// ユーザーã«ä¾ã‚‹ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ä½œæˆã‚’ç¦æ­¢ã™ã‚‹ + /// + public AvatarSettingScript(GameObject root_game_object, GameObject[] bones) { + root_game_object_ = root_game_object; + bones_ = bones; + } + + /// + /// 汎用アãƒãƒ€ãƒ¼ã‚’設定ã™ã‚‹ + /// + /// アニメーター + public Animator SettingGenericAvatar() { + //ã‚¢ãƒã‚¿ãƒ¼ãƒ«ãƒ¼ãƒˆãƒˆãƒ©ãƒ³ã‚¹ãƒ•ォームã®å–å¾— + Transform avatar_root_transform = root_game_object_.transform.Find("Model"); + if (null == avatar_root_transform) { + //ルートゲームオブジェクト直下ã«ãƒ¢ãƒ‡ãƒ«ãƒ«ãƒ¼ãƒˆã‚ªãƒ–ジェクトãŒç„¡ã„(PMDConverter)ãªã‚‰ + //ルートゲームオブジェクトをアãƒã‚¿ãƒ¼ãƒ«ãƒ¼ãƒˆã‚ªãƒ–ジェクトã¨ã™ã‚‹ + avatar_root_transform = root_game_object_.transform; + } + + //ジェãƒãƒªãƒƒã‚¯ã‚¢ãƒã‚¿ãƒ¼ä½œæˆ + string root_name = ((HasBone("å…¨ã¦ã®è¦ª"))? "å…¨ã¦ã®è¦ª": ""); + avatar_ = AvatarBuilder.BuildGenericAvatar(avatar_root_transform.gameObject, root_name); + + //ã‚¢ãƒã‚¿ãƒ¼ã‚’アニメーターã«è¨­å®š + animator_ = root_game_object_.AddComponent(); + animator_.avatar = avatar_; + + return animator_; + } + + /// + /// 人型アãƒãƒ€ãƒ¼ã‚’設定ã™ã‚‹ + /// + /// アニメーター + /// + /// モデルã«ä¾ã£ã¦ãƒœãƒ¼ãƒ³æ§‹æˆã«å·®ãŒæœ‰ã‚‹ãŒã€MMD標準モデルã¨ã®ä¸€è‡´ã‚’優先ã™ã‚‹ + /// + public Animator SettingHumanAvatar() { + //ç”Ÿæˆæ¸ˆã¿ã®ãƒœãƒ¼ãƒ³ã‚’Unity推奨ãƒãƒ¼ã‚ºã«è¨­å®š + SetRequirePose(); + + //ã‚¢ãƒã‚¿ãƒ¼ãƒ«ãƒ¼ãƒˆãƒˆãƒ©ãƒ³ã‚¹ãƒ•ォームã®å–å¾— + Transform avatar_root_transform = root_game_object_.transform.Find("Model"); + if (null == avatar_root_transform) { + //ルートゲームオブジェクト直下ã«ãƒ¢ãƒ‡ãƒ«ãƒ«ãƒ¼ãƒˆã‚ªãƒ–ジェクトãŒç„¡ã„(PMDConverter)ãªã‚‰ + //ルートゲームオブジェクトをアãƒã‚¿ãƒ¼ãƒ«ãƒ¼ãƒˆã‚ªãƒ–ジェクトã¨ã™ã‚‹ + avatar_root_transform = root_game_object_.transform; + } + + //ヒューマノイドアãƒã‚¿ãƒ¼ä½œæˆ + HumanDescription description = new HumanDescription(); + description.human = CreateHumanBone(); + description.skeleton = CreateSkeletonBone(); + description.lowerArmTwist = 0.0f; + description.upperArmTwist = 0.0f; + description.upperLegTwist = 0.0f; + description.lowerLegTwist = 0.0f; + description.armStretch = 0.0f; + description.legStretch = 0.0f; + description.feetSpacing = 0.0f; + avatar_ = AvatarBuilder.BuildHumanAvatar(avatar_root_transform.gameObject, description); + + //ã‚¢ãƒã‚¿ãƒ¼ã‚’アニメーターã«è¨­å®š + animator_ = root_game_object_.AddComponent(); + animator_.avatar = avatar_; + + //IKã®ç„¡åŠ¹åŒ– + DisableIk(); + + return animator_; + } + + /// ã‚¢ãƒã‚¿ãƒ¼ã‚’Projectã«ç™»éŒ²ã™ã‚‹ + /// + /// ファイルパス + public void CreateAsset(string file_path) + { + if (avatar_) { + AssetDatabase.CreateAsset(avatar_, file_path); + } else { + throw new System.InvalidOperationException(); + } + } + + /// + /// ç”Ÿæˆæ¸ˆã¿ã®ãƒœãƒ¼ãƒ³ã‚’Unity推奨ãƒãƒ¼ã‚ºã«è¨­å®š + /// + void SetRequirePose() + { + foreach (Transform transform in bones_.Select(x=>x.transform)) { + SetRequirePose(transform); + } + } + + /// + /// 特定ã®åå‰ã‚’æŒã¤ãƒœãƒ¼ãƒ³ã‚’先代ã‹ã‚‰é¸ã³å‡ºã™ + /// + /// 基点ã®ãƒœãƒ¼ãƒ³ + /// 対象ã®ãƒœãƒ¼ãƒ³å + /// 対象ã®å…ˆä»£ãƒœãƒ¼ãƒ³ + /// + /// åŸºç‚¹ãƒœãƒ¼ãƒ³ãŒæŽ¢ç´¢åãªã‚‰åŸºç‚¹ãƒœãƒ¼ãƒ³ã‚’è¿”ã™ã€‚ + /// + static Transform FindTransformUpwards(Transform transform, string name) + { + while ((null != transform) && (transform.name != name)) { + transform = transform.parent; + } + return transform; + } + + /// + /// 親å­é–¢ä¿‚を見ã¦ãƒœãƒ¼ãƒ³ã‚’æ°´å¹³ã«ã™ã‚‹ + /// + /// 対象ã®ãƒœãƒ¼ãƒ³ + /// Z軸ã®ã¿ã‚’回転ã•ã›ã‚‹Quaternion + static Quaternion ResetHorizontalPose(Transform transform, Transform child_transform) + { + // ボーンã®å‘ãã‚’å–å¾— + var bone_vector = child_transform.position - transform.position; + bone_vector.z = 0f; // å¹³é¢åŒ– + bone_vector.Normalize(); + + // å¹³é¢åŒ–ã—ãŸæ­£è¦åŒ–ベクトルã¨å˜ä½ãƒ™ã‚¯ãƒˆãƒ«ã‚’比較ã—ã¦ï¼Œè§’度をå–å¾—ã™ã‚‹ + Vector3 normalized_vector = bone_vector.x >= 0 ? Vector3.right : Vector3.left; + float cos_value = Vector3.Dot(bone_vector, normalized_vector); + float theta = Mathf.Acos(cos_value) * Mathf.Rad2Deg; + + theta = bone_vector.x >= 0 ? -theta : theta; // ボーンã®å‘ãã«ã‚ˆã£ã¦å›žè»¢æ–¹å‘ãŒé•ㆠ+ + return Quaternion.Euler(0f, 0f, theta); + } + + /// + /// 腕全体を水平ã«ã™ã‚‹å‡¦ç† + /// + /// 手首ボーン + /// ã²ã˜ãƒœãƒ¼ãƒ³å + /// 腕ボーンå + /// 肩ボーンå + static void StartResettingHorizontal(Transform wrist, string hinge_name, string arm_name, string shoulder_name) + { + var hinge = FindTransformUpwards(wrist, hinge_name); + var arm = FindTransformUpwards(hinge, arm_name); + var shoulder = FindTransformUpwards(arm, shoulder_name); + shoulder.transform.localRotation = ResetHorizontalPose(shoulder, arm); + arm.transform.localRotation = ResetHorizontalPose(arm, hinge); + hinge.transform.localRotation = ResetHorizontalPose(hinge, wrist); + } + + /// + /// ç”Ÿæˆæ¸ˆã¿ã®ãƒœãƒ¼ãƒ³ã‚’Unity推奨ãƒãƒ¼ã‚ºã«è¨­å®š + /// + /// ボーンã®ãƒˆãƒ©ãƒ³ã‚¹ãƒ•ォーム + void SetRequirePose(Transform transform) + { + switch (transform.name) { + case "左手首": //Tãƒãƒ¼ã‚ºã«ã™ã‚‹ç‚ºã«è…•ã‚’æŒã¡ä¸Šã’ã‚‹ + StartResettingHorizontal(transform, "å·¦ã²ã˜", "左腕", "左肩"); + break; + case "峿‰‹é¦–": //Tãƒãƒ¼ã‚ºã«ã™ã‚‹ç‚ºã«è…•ã‚’æŒã¡ä¸Šã’ã‚‹ + StartResettingHorizontal(transform, "å³ã²ã˜", "å³è…•", "å³è‚©"); + break; + case "è…°": goto case "センター"; + case "センター": + if (HasBone("è…°") ^ ("センター" == transform.name)) { + //腰ボーンをæŒã£ã¦ã„ã¦ã€ç¾åœ¨ã®å…¥åŠ›ãŒè…°ãƒœãƒ¼ãƒ³ãªã‚‰ ã‚‚ã—ã㯠腰ボーンをæŒã£ã¦ãŠã‚‰ãšã€ç¾åœ¨ã®å…¥åŠ›ãŒã‚»ãƒ³ã‚¿ãƒ¼ãƒœãƒ¼ãƒ³ãªã‚‰ + //後ã‚ã‚’å‘ã„ã¦ã„ã‚‹ã®ã§å‘ãç›´ã™ + transform.localRotation = Quaternion.Euler(0.0f, 180.0f, 0.0f); + transform.localPosition = new Vector3(-transform.localPosition.x, transform.localPosition.y, -transform.localPosition.z); + } + break; + default: + if (root_game_object_.transform.Find("Physics") == transform.parent) { + //ç‰©ç†æ¼”算ルートãªã‚‰ + //後ã‚ã‚’å‘ã„ã¦ã„ã‚‹ã®ã§å‘ãç›´ã™ + transform.localRotation = Quaternion.Euler(0.0f, 180.0f, 0.0f); + transform.localPosition = new Vector3(-transform.localPosition.x, transform.localPosition.y, -transform.localPosition.z); + } + break; + } + } + + /// + /// ãƒœãƒ¼ãƒ³å­˜åœ¨ç¢ºèª + /// + /// true:ボーンãŒå­˜åœ¨ã™ã‚‹, false:ボーンãŒå­˜åœ¨ã—ãªã„ + /// ボーンå + bool HasBone(string name) { + return bones_.Any(x=>x.name == name); + } + + /// + /// MMDç”¨ãƒ’ãƒ¥ãƒ¼ãƒžãƒŽã‚¤ãƒ‰ãƒœãƒ¼ãƒ³ä½œæˆ + /// + /// ヒューマノイドボーン + HumanBone[] CreateHumanBone() + { + System.Func CreateHint = (key, value)=>{ + HumanBone human_bone = new HumanBone(); + human_bone.humanName = key; + human_bone.boneName = value; + human_bone.limit.useDefaultValues = true; + return human_bone; + }; + + List bone_name = new List(); + + //◆必須 + //△標準逸脱モデル対策 + + //顔系 + //ヒューマノイドボーンã¯"ヒップ→背骨"ã®ãƒœãƒ¼ãƒ³ã‚’è¦æ±‚ã™ã‚‹ãŒã€MMDã¯"上åŠèº«â†’下åŠèº«"ã¨æŽ¥ç¶šæ–¹å‘ãŒé€†ãªã®ã§ã“れらを割り当ã¦ã‚‹äº‹ã¯å‡ºæ¥ãªã„ + if (HasBone("è…°")) { + bone_name.Add(CreateHint("Hips", "è…°" )); //ヒップ◆△ + } else { + bone_name.Add(CreateHint("Hips", "センター" )); //ヒップ◆ + } + bone_name.Add(CreateHint("Spine", "上åŠèº«" )); //背骨◆ + if (HasBone("胸")) { + bone_name.Add(CreateHint("Chest", "胸" )); //胸△ + } else { + bone_name.Add(CreateHint("Chest", "上åŠèº«2" )); //胸 + } + bone_name.Add(CreateHint("Neck", "首" )); //首 + bone_name.Add(CreateHint("Head", "é ­" )); //é ­â—† + bone_name.Add(CreateHint("LeftEye", "左目" )); //左目 + bone_name.Add(CreateHint("RightEye", "å³ç›®" )); //å³ç›® + if (HasBone("ã‚ã”")) { + bone_name.Add(CreateHint("Jaw", "ã‚ã”" )); //ã‚ã”â–³ + } else if (HasBone("顎")) { + bone_name.Add(CreateHint("Jaw", "顎" )); //ã‚ã”â–³ + } + + //足系 + bone_name.Add(CreateHint("LeftUpperLeg", "左足" )); //左脚上部◆ + bone_name.Add(CreateHint("RightUpperLeg", "å³è¶³" )); //å³è„šä¸Šéƒ¨â—† + bone_name.Add(CreateHint("LeftLowerLeg", "å·¦ã²ã–" )); //左脚◆ + bone_name.Add(CreateHint("RightLowerLeg", "å³ã²ã–" )); //å³è„šâ—† + bone_name.Add(CreateHint("LeftFoot", "左足首" )); //左足◆ + bone_name.Add(CreateHint("RightFoot", "å³è¶³é¦–" )); //å³è¶³â—† + bone_name.Add(CreateHint("LeftToes", "å·¦ã¤ã¾å…ˆ" )); //左足指 + bone_name.Add(CreateHint("RightToes", "å³ã¤ã¾å…ˆ" )); //å³è¶³æŒ‡ + + //手系 + bone_name.Add(CreateHint("LeftShoulder", "左肩" )); //左肩 + bone_name.Add(CreateHint("RightShoulder", "å³è‚©" )); //å³è‚© + bone_name.Add(CreateHint("LeftUpperArm", "左腕" )); //左腕上部◆ + bone_name.Add(CreateHint("RightUpperArm", "å³è…•" )); //å³è…•上部◆ + bone_name.Add(CreateHint("LeftLowerArm", "å·¦ã²ã˜" )); //左腕◆ + bone_name.Add(CreateHint("RightLowerArm", "å³ã²ã˜" )); //å³è…•â—† + bone_name.Add(CreateHint("LeftHand", "左手首" )); //左手◆ + bone_name.Add(CreateHint("RightHand", "峿‰‹é¦–" )); //峿‰‹â—† + + //指系 + bone_name.Add(CreateHint("Left Thumb Proximal", "左親指1" )); //左親指(付根) + bone_name.Add(CreateHint("Left Thumb Intermediate", "左親指2" )); //左親指(間接) + bone_name.Add(CreateHint("Left Thumb Distal", "左親指先" )); //左親指(å…ˆ) + bone_name.Add(CreateHint("Left Index Proximal", "左人指1" )); //å·¦äººå·®ã—æŒ‡(付根) + bone_name.Add(CreateHint("Left Index Intermediate", "左人指2" )); //å·¦äººå·®ã—æŒ‡(間接) + if (HasBone("左人指先")) { + bone_name.Add(CreateHint("Left Index Distal", "左人指先" )); //å·¦äººå·®ã—æŒ‡(å…ˆ)â–³ + } else { + bone_name.Add(CreateHint("Left Index Distal", "左人差指先" )); //å·¦äººå·®ã—æŒ‡(å…ˆ) + } + bone_name.Add(CreateHint("Left Middle Proximal", "左中指1" )); //左中指(付根) + bone_name.Add(CreateHint("Left Middle Intermediate", "左中指2" )); //左中指(間接) + bone_name.Add(CreateHint("Left Middle Distal", "左中指先" )); //左中指(å…ˆ) + bone_name.Add(CreateHint("Left Ring Proximal", "左薬指1" )); //左薬指(付根) + bone_name.Add(CreateHint("Left Ring Intermediate", "左薬指2" )); //左薬指(間接) + bone_name.Add(CreateHint("Left Ring Distal", "左薬指先" )); //左薬指(å…ˆ) + bone_name.Add(CreateHint("Left Little Proximal", "左尿Œ‡ï¼‘" )); //左尿Œ‡(付根) + bone_name.Add(CreateHint("Left Little Intermediate", "左尿Œ‡ï¼’" )); //左尿Œ‡(間接) + bone_name.Add(CreateHint("Left Little Distal", "左尿Œ‡å…ˆ" )); //左尿Œ‡(å…ˆ) + bone_name.Add(CreateHint("Right Thumb Proximal", "å³è¦ªæŒ‡ï¼‘" )); //å³è¦ªæŒ‡(付根) + bone_name.Add(CreateHint("Right Thumb Intermediate", "å³è¦ªæŒ‡ï¼’" )); //å³è¦ªæŒ‡(間接) + bone_name.Add(CreateHint("Right Thumb Distal", "å³è¦ªæŒ‡å…ˆ" )); //å³è¦ªæŒ‡(å…ˆ) + bone_name.Add(CreateHint("Right Index Proximal", "å³äººæŒ‡ï¼‘" )); //å³äººå·®ã—指(付根) + bone_name.Add(CreateHint("Right Index Intermediate", "å³äººæŒ‡ï¼’" )); //å³äººå·®ã—指(間接) + if (HasBone("å³äººæŒ‡å…ˆ")) { + bone_name.Add(CreateHint("Right Index Distal", "å³äººæŒ‡å…ˆ" )); //å³äººå·®ã—指(å…ˆ)â–³ + } else { + bone_name.Add(CreateHint("Right Index Distal", "å³äººå·®æŒ‡å…ˆ" )); //å³äººå·®ã—指(å…ˆ) + } + bone_name.Add(CreateHint("Right Middle Proximal", "å³ä¸­æŒ‡ï¼‘" )); //å³ä¸­æŒ‡(付根) + bone_name.Add(CreateHint("Right Middle Intermediate", "å³ä¸­æŒ‡ï¼’" )); //å³ä¸­æŒ‡(間接) + bone_name.Add(CreateHint("Right Middle Distal", "å³ä¸­æŒ‡å…ˆ" )); //å³ä¸­æŒ‡(å…ˆ) + bone_name.Add(CreateHint("Right Ring Proximal", "å³è–¬æŒ‡ï¼‘" )); //å³è–¬æŒ‡(付根) + bone_name.Add(CreateHint("Right Ring Intermediate", "å³è–¬æŒ‡ï¼’" )); //å³è–¬æŒ‡(間接) + bone_name.Add(CreateHint("Right Ring Distal", "å³è–¬æŒ‡å…ˆ" )); //å³è–¬æŒ‡(å…ˆ) + bone_name.Add(CreateHint("Right Little Proximal", "å³å°æŒ‡ï¼‘" )); //å³å°æŒ‡(付根) + bone_name.Add(CreateHint("Right Little Intermediate", "å³å°æŒ‡ï¼’" )); //å³å°æŒ‡(間接) + bone_name.Add(CreateHint("Right Little Distal", "å³å°æŒ‡å…ˆ" )); //å³å°æŒ‡(å…ˆ) + + return bone_name.Where(x=>!string.IsNullOrEmpty(x.boneName)).ToArray(); + } + + /// + /// MMDç”¨ã‚¹ã‚±ãƒ«ãƒˆãƒ³ãƒœãƒ¼ãƒ³ä½œæˆ + /// + /// スケルトンボーン + SkeletonBone[] CreateSkeletonBone() + { + IEnumerable bones_enumerator = bones_; + + //Hipsボーンã®è¦ªãƒœãƒ¼ãƒ³è¿„SkeletonBoneã«å…¥ã‚Œã‚‹å¿…è¦ãŒæœ‰ã‚‹ã®ã§ã€ç¢ºèªã¨è¿½åŠ  + string hips_bone_name = ((HasBone("è…°"))? "è…°": "センター"); + Transform hips_parent_bone = bones_.Where(x=>x.name == hips_bone_name).Select(x=>x.transform.parent).FirstOrDefault(); + if (null != hips_parent_bone) { + //Hipsボーンã®è¦ªãƒœãƒ¼ãƒ³ãŒæœ‰ã‚‹ãªã‚‰ + //Hipsボーンã®è¦ªãƒœãƒ¼ãƒ³ãŒbones_ã«å«ã¾ã‚Œã¦ã„ã‚‹ã‹ç¢ºèªã™ã‚‹ + if (!HasBone(hips_parent_bone.name)) { + //Hipsボーンã®è¦ªãƒœãƒ¼ãƒ³ãŒbones_ã«ç„¡ã„ãªã‚‰ + //追加(Hipsボーンä¾ã‚Šã‚‚å‰ã«è¿½åŠ ã—ãªã„ã¨ã„ã‘ãªã„ã®ã§æ³¨æ„) + bones_enumerator = Enumerable.Repeat(hips_parent_bone.gameObject, 1) + .Concat(bones_enumerator); + } + } + + var result = bones_enumerator.Select(x=>{ + SkeletonBone skeleton_bone = new SkeletonBone(); + skeleton_bone.name = x.name; + Transform transform = x.transform; + skeleton_bone.position = transform.localPosition; + skeleton_bone.rotation = transform.localRotation; + skeleton_bone.scale = transform.localScale; + return skeleton_bone; + }); + return result.ToArray(); + } + + /// + /// IKã®ç„¡åŠ¹åŒ– + /// + void DisableIk() + { + foreach(CCDIKSolver ik_solver in root_game_object_.GetComponent().ik_list) { + ik_solver.enabled = false; + } + } + + GameObject root_game_object_ = null; + GameObject[] bones_ = null; + Avatar avatar_ = null; + Animator animator_ = null; +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/ComputeSkin.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/ComputeSkin.cs new file mode 100644 index 000000000..ee072b28f --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/ComputeSkin.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +//using Mono.Simd; + +namespace MMD +{ + namespace Skin + { + /// + /// スキンã®è¨ˆç®—を行ㆠ+ /// + public class ComputeMorph + { + /// + /// モーフベクトルをweight値ã‹ã‚‰è¨ˆç®—ã™ã‚‹ + /// + /// モーフベクトル + /// ウェイト + /// 表情ã®ç§»å‹•ベクトル + public static void Compute(ref Vector3[] resultVector, Vector3[] morphVector, float weight) + { + // モーフベクトルを伸ã³ç¸®ã¿ã•ã›ãŸã‚‚ã®ã‚’çµæžœã¨ã—ã¦è¿”ã™ + for (int i = 0; i < morphVector.Length; i++) + resultVector[i] = morphVector[i] * weight; + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/MMDFormat.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/MMDFormat.cs new file mode 100644 index 000000000..9a50446c0 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/MMDFormat.cs @@ -0,0 +1,841 @@ +using System.Collections; +using System.Collections.Generic; +using System; +using System.IO; +using UnityEngine; +using System.Text; + +// Reference URL: +// http://blog.goo.ne.jp/torisu_tetosuki/e/209ad341d3ece2b1b4df24abf619d6e4 +// http://mikudan.blog120.fc2.com/blog-entry-280.html + +namespace MMD +{ + namespace PMX + { + // PMXフォーマットクラス + public class PMXFormat + { + public MetaHeader meta_header; + public Header header; + public VertexList vertex_list; + public FaceVertexList face_vertex_list; + public TextureList texture_list; + public MaterialList material_list; + public BoneList bone_list; + public MorphList morph_list; + public DisplayFrameList display_frame_list; + public RigidbodyList rigidbody_list; + public RigidbodyJointList rigidbody_joint_list; + + public class MetaHeader + { + public string path; // フルパス + public string name; // æ‹¡å¼µå­ã¨ãƒ‘ス抜ãã®ãƒ•ァイルã®åå‰ + public string folder; // ãƒ•ã‚¡ã‚¤ãƒ«åæŠœãã®ãƒ‘ス + } + + public class Header + { + public enum StringCode { + Utf16le, + Utf8, + } + public enum IndexSize { + Byte1 = 1, + Byte2 = 2, + Byte4 = 4, + } + public byte[] magic; // "PMX " + public float version; // 00 00 80 3F == 1.00 + + public byte dataSize; + public StringCode encodeMethod; + public byte additionalUV; + public IndexSize vertexIndexSize; + public IndexSize textureIndexSize; + public IndexSize materialIndexSize; + public IndexSize boneIndexSize; + public IndexSize morphIndexSize; + public IndexSize rigidbodyIndexSize; + + public string model_name; + public string model_english_name; + public string comment; + public string english_comment; + } + + public class VertexList + { + public Vertex[] vertex; // 頂点データ(38bytes/頂点) + } + + public class Vertex + { + public enum WeightMethod { + BDEF1, + BDEF2, + BDEF4, + SDEF, + QDEF, + } + public Vector3 pos; // x, y, z // 座標 + public Vector3 normal_vec; // nx, ny, nz // 法線ベクトル + public Vector2 uv; // u, v // UV座標 // MMDã¯é ‚点UV + public Vector4[] add_uv; // x,y,z,w + public BoneWeight bone_weight; + public float edge_magnification; + + } + + public interface BoneWeight + { + Vertex.WeightMethod method {get;} + uint bone1_ref {get;} + uint bone2_ref {get;} + uint bone3_ref {get;} + uint bone4_ref {get;} + float bone1_weight {get;} + float bone2_weight {get;} + float bone3_weight {get;} + float bone4_weight {get;} + Vector3 c_value {get;} + Vector3 r0_value {get;} + Vector3 r1_value {get;} + } + + public class BDEF1 : BoneWeight + { + public Vertex.WeightMethod method {get{return Vertex.WeightMethod.BDEF1;}} + public uint bone1_ref {get; set;} + public uint bone2_ref {get{return 0;}} + public uint bone3_ref {get{return 0;}} + public uint bone4_ref {get{return 0;}} + public float bone1_weight {get{return 1.0f;}} + public float bone2_weight {get{return 0.0f;}} + public float bone3_weight {get{return 0.0f;}} + public float bone4_weight {get{return 0.0f;}} + public Vector3 c_value {get{return Vector3.zero;}} + public Vector3 r0_value {get{return Vector3.zero;}} + public Vector3 r1_value {get{return Vector3.zero;}} + } + public class BDEF2 : BoneWeight + { + public Vertex.WeightMethod method {get{return Vertex.WeightMethod.BDEF2;}} + public uint bone1_ref {get; set;} + public uint bone2_ref {get; set;} + public float bone1_weight {get; set;} + public uint bone3_ref {get{return 0;}} + public uint bone4_ref {get{return 0;}} + public float bone2_weight {get{return 1.0f - bone1_weight;}} + public float bone3_weight {get{return 0.0f;}} + public float bone4_weight {get{return 0.0f;}} + public Vector3 c_value {get{return Vector3.zero;}} + public Vector3 r0_value {get{return Vector3.zero;}} + public Vector3 r1_value {get{return Vector3.zero;}} + } + public class BDEF4 : BoneWeight + { + public Vertex.WeightMethod method {get{return Vertex.WeightMethod.BDEF4;}} + public uint bone1_ref {get; set;} + public uint bone2_ref {get; set;} + public uint bone3_ref {get; set;} + public uint bone4_ref {get; set;} + public float bone1_weight {get; set;} + public float bone2_weight {get; set;} + public float bone3_weight {get; set;} + public float bone4_weight {get; set;} + public Vector3 c_value {get{return Vector3.zero;}} + public Vector3 r0_value {get{return Vector3.zero;}} + public Vector3 r1_value {get{return Vector3.zero;}} + } + public class SDEF : BoneWeight + { + public Vertex.WeightMethod method {get{return Vertex.WeightMethod.SDEF;}} + public uint bone1_ref {get; set;} + public uint bone2_ref {get; set;} + public float bone1_weight {get; set;} + public Vector3 c_value {get; set;} + public Vector3 r0_value {get; set;} + public Vector3 r1_value {get; set;} + public uint bone3_ref {get{return 0;}} + public uint bone4_ref {get{return 0;}} + public float bone2_weight {get{return 1.0f - bone1_weight;}} + public float bone3_weight {get{return 0.0f;}} + public float bone4_weight {get{return 0.0f;}} + } + public class QDEF : BoneWeight + { + public Vertex.WeightMethod method {get{return Vertex.WeightMethod.QDEF;}} + public uint bone1_ref {get; set;} + public uint bone2_ref {get; set;} + public uint bone3_ref {get; set;} + public uint bone4_ref {get; set;} + public float bone1_weight {get; set;} + public float bone2_weight {get; set;} + public float bone3_weight {get; set;} + public float bone4_weight {get; set;} + public Vector3 c_value {get{return Vector3.zero;}} + public Vector3 r0_value {get{return Vector3.zero;}} + public Vector3 r1_value {get{return Vector3.zero;}} + } + + // é¢é ‚点リスト + public class FaceVertexList + { + public uint[] face_vert_index; // 頂点番å·(3個/é¢) + } + + public class TextureList + { + public string[] texture_file; // 100byte * 10個固定 + } + + public class MaterialList + { + public Material[] material; // æè³ªãƒ‡ãƒ¼ã‚¿(70bytes/material) + } + + public class Material + { + [Flags] + public enum Flag { + Reversible = 1<< 0, //ä¸¡é¢æç”» + CastShadow = 1<< 1, //地é¢å½± + CastSelfShadow = 1<< 2, //セルフシャドウマップã¸ã®æç”» + ReceiveSelfShadow = 1<< 3, //ã‚»ãƒ«ãƒ•ã‚·ãƒ£ãƒ‰ã‚¦ã®æç”» + Edge = 1<< 4, //エッジæç”» + } + public enum SphereMode { + Null, //ç„¡ã— + MulSphere, //乗算スフィア + AddSphere, //加算スフィア + SubTexture, //サブテクスãƒãƒ£ + } + public string name; + public string english_name; + + public Color diffuse_color; // dr, dg, db, da // 減衰色 + public Color specular_color; // sr, sg, sb // 光沢色 + public float specularity; + public Color ambient_color; // mr, mg, mb // 環境色(ambient) + public Flag flag; + public Color edge_color; // r, g, b, a + public float edge_size; + public uint usually_texture_index; + public uint sphere_texture_index; + public SphereMode sphere_mode; + public byte common_toon; + public uint toon_texture_index; + public string memo; + public uint face_vert_count; // é¢é ‚点数 // インデックスã«å¤‰æ›ã™ã‚‹å ´åˆã¯ã€æè³ª0ã‹ã‚‰é †ã«åŠ ç®— + } + + public class BoneList + { + public Bone[] bone; // ボーンデータ(39bytes/bone) + } + + public class Bone + { + [Flags] + public enum Flag { + Connection = 1<< 0, //接続先(PMDå­ãƒœãƒ¼ãƒ³æŒ‡å®š)表示方法(ON:ãƒœãƒ¼ãƒ³ã§æŒ‡å®šã€OFF:åº§æ¨™ã‚ªãƒ•ã‚»ãƒƒãƒˆã§æŒ‡å®š) + Rotatable = 1<< 1, //回転å¯èƒ½ + Movable = 1<< 2, //移動å¯èƒ½ + DisplayFlag = 1<< 3, //表示 + CanOperate = 1<< 4, //æ“ä½œå¯ + IkFlag = 1<< 5, //IK + AddLocal = 1<< 7, //ローカル付与 | 付与対象(ON:親ã®ãƒ­ãƒ¼ã‚«ãƒ«å¤‰å½¢é‡ã€OFF:ユーザー変形値ï¼IKリンクï¼å¤šé‡ä»˜ä¸Ž) + AddRotation = 1<< 8, //回転付与 + AddMove = 1<< 9, //移動付与 + FixedAxis = 1<<10, //軸固定 + LocalAxis = 1<<11, //ローカル軸 + PhysicsTransform = 1<<12, //物ç†å¾Œå¤‰å½¢ + ExternalParentTransform = 1<<13, //外部親変形 + } + public string bone_name; // ボーンå + public string bone_english_name; + public Vector3 bone_position; + public uint parent_bone_index; // 親ボーン番å·(ãªã„å ´åˆã¯uint.MaxValue) + public int transform_level; + public Flag bone_flag; + public Vector3 position_offset; + public uint connection_index; + public uint additional_parent_index; + public float additional_rate; + public Vector3 axis_vector; + public Vector3 x_axis_vector; + public Vector3 z_axis_vector; + public uint key_value; + public IK_Data ik_data; + } + + public class IK_Data + { + public uint ik_bone_index; // IKãƒœãƒ¼ãƒ³ç•ªå· + public uint iterations; // å†å¸°æ¼”算回数 // IK値1 + public float limit_angle; + public IK_Link[] ik_link; + } + + public class IK_Link + { + public uint target_bone_index; + public byte angle_limit; + public Vector3 lower_limit; + public Vector3 upper_limit; + } + + public class MorphList + { + public MorphData[] morph_data; // 表情データ((25+16*skin_vert_count)/skin) + } + + public class MorphData + { + public enum Panel { + Base, + EyeBrow, + Eye, + Lip, + Other, + } + public enum MorphType { + Group, + Vertex, + Bone, + Uv, + Adduv1, + Adduv2, + Adduv3, + Adduv4, + Material, + + Flip, + Impulse, + } + public string morph_name; // 表情å + public string morph_english_name; // 表情英å + public Panel handle_panel; + public MorphType morph_type; + public MorphOffset[] morph_offset; + } + + public interface MorphOffset {}; + + public class VertexMorphOffset : MorphOffset + { + public uint vertex_index; + public Vector3 position_offset; + } + public class UVMorphOffset : MorphOffset + { + public uint vertex_index; + public Vector4 uv_offset; + } + public class BoneMorphOffset : MorphOffset + { + public uint bone_index; + public Vector3 move_value; + public Quaternion rotate_value; + } + public class MaterialMorphOffset : MorphOffset + { + public enum OffsetMethod { + Mul, + Add, + } + public uint material_index; + public OffsetMethod offset_method; + public Color diffuse; + public Color specular; + public float specularity; + public Color ambient; + public Color edge_color; + public float edge_size; + public Color texture_coefficient; + public Color sphere_texture_coefficient; + public Color toon_texture_coefficient; + } + public class GroupMorphOffset : MorphOffset + { + public uint morph_index; + public float morph_rate; + } + + public class ImpulseMorphOffset : MorphOffset + { + public uint rigidbody_index; + public byte local_flag; + public Vector3 move_velocity; + public Vector3 rotation_torque; + } + + public class DisplayFrameList + { + public DisplayFrame[] display_frame; + } + + public class DisplayFrame + { + public string display_name; + public string display_english_name; + public byte special_frame_flag; + public DisplayElement[] display_element; + } + + public class DisplayElement + { + public byte element_target; + public uint element_target_index; + } + + public class RigidbodyList + { + public PMX.PMXFormat.Rigidbody[] rigidbody; + } + + /// + /// 剛体 + /// + public class Rigidbody + { + public enum ShapeType { + Sphere, //çƒ + Box, //ç®± + Capsule, //カプセル + } + public enum OperationType { + Static, //ボーン追従 + Dynamic, //ç‰©ç†æ¼”ç®— + DynamicAndPosAdjust, //ç‰©ç†æ¼”ç®—(Boneä½ç½®åˆã›) + } + public string name; // 諸データ:åç§° ,20byte + public string english_name; // 諸データ:åç§° ,20byte + public uint rel_bone_index;// è«¸ãƒ‡ãƒ¼ã‚¿ï¼šé–¢é€£ãƒœãƒ¼ãƒ³ç•ªå· + public byte group_index; // 諸データ:グループ + public ushort ignore_collision_group; + public ShapeType shape_type; // 形状:タイプ(0:çƒã€1:ç®±ã€2:カプセル) + public Vector3 shape_size; + public Vector3 collider_position; // ä½ç½®ï¼šä½ç½®(x, y, z) + public Vector3 collider_rotation; // ä½ç½®ï¼šå›žè»¢(rad(x), rad(y), rad(z)) + public float weight; // è«¸ãƒ‡ãƒ¼ã‚¿ï¼šè³ªé‡ // 00 00 80 3F // 1.0 + public float position_dim; // 諸データ:移動減 // 00 00 00 00 + public float rotation_dim; // 諸データ:回転減 // 00 00 00 00 + public float recoil; // 諸データ:å発力 // 00 00 00 00 + public float friction; // 諸データ:摩擦力 // 00 00 00 00 + public OperationType operation_type; // 諸データ:タイプ(0:Bone追従ã€1:ç‰©ç†æ¼”ç®—ã€2:ç‰©ç†æ¼”ç®—(Boneä½ç½®åˆã›)) // 00 // Bone追従 + } + + public class RigidbodyJointList + { + public MMD.PMX.PMXFormat.Joint[] joint; + } + + public class Joint + { + public enum OperationType { + Spring6DOF, //スプリング6DOF + } + public string name; // 20byte + public string english_name; + public OperationType operation_type; + public uint rigidbody_a; // 諸データ:剛体A + public uint rigidbody_b; // 諸データ:剛体B + public Vector3 position; // 諸データ:ä½ç½®(x, y, z) // 諸データ:ä½ç½®åˆã›ã§ã‚‚è¨­å®šå¯ + public Vector3 rotation; // 諸データ:回転(rad(x), rad(y), rad(z)) + public Vector3 constrain_pos_lower; // 制é™ï¼šç§»å‹•1(x, y, z) + public Vector3 constrain_pos_upper; // 制é™ï¼šç§»å‹•2(x, y, z) + public Vector3 constrain_rot_lower; // 制é™ï¼šå›žè»¢1(rad(x), rad(y), rad(z)) + public Vector3 constrain_rot_upper; // 制é™ï¼šå›žè»¢2(rad(x), rad(y), rad(z)) + public Vector3 spring_position; // ã°ã­ï¼šç§»å‹•(x, y, z) + public Vector3 spring_rotation; // ã°ã­ï¼šå›žè»¢(rad(x), rad(y), rad(z)) + } + } + } + + namespace PMD + { + // PMDã®ãƒ•ォーマットクラス + public class PMDFormat + { + public string path; // フルパス + public string name; // æ‹¡å¼µå­ã¨ãƒ‘ス抜ãã®ãƒ•ァイルã®åå‰ + public string folder; // ãƒ•ã‚¡ã‚¤ãƒ«åæŠœãã®ãƒ‘ス + + public Header head; + public VertexList vertex_list; + public FaceVertexList face_vertex_list; + public MaterialList material_list; + public BoneList bone_list; + public IKList ik_list; + public SkinList skin_list; + public SkinNameList skin_name_list; + public BoneNameList bone_name_list; + public BoneDisplayList bone_display_list; + public EnglishHeader eg_head; + public EnglishBoneNameList eg_bone_name_list; + public EnglishSkinNameList eg_skin_name_list; + public EnglishBoneDisplayList eg_bone_display_list; + public ToonTextureList toon_texture_list; + public RigidbodyList rigidbody_list; + public RigidbodyJointList rigidbody_joint_list; + + public class Header + { + public byte[] magic; // "Pmd" + public float version; // 00 00 80 3F == 1.00 + public string model_name; + public string comment; + } + + public class VertexList + { + public uint vert_count; // 頂点数 + public Vertex[] vertex; // 頂点データ(38bytes/頂点) + } + + public class Vertex + { + public Vector3 pos; // x, y, z // 座標 + public Vector3 normal_vec; // nx, ny, nz // 法線ベクトル + public Vector2 uv; // u, v // UV座標 // MMDã¯é ‚点UV + public ushort[] bone_num; // ボーン番å·1ã€ç•ªå·2 // モデル変形(頂点移動)時ã«å½±éŸ¿ + public byte bone_weight; // ボーン1ã«ä¸Žãˆã‚‹å½±éŸ¿åº¦ // min:0 max:100 // ボーン2ã¸ã®å½±éŸ¿åº¦ã¯ã€(100 - bone_weight) + public byte edge_flag; // 0:通常ã€1:エッジ無効 // エッジ(輪郭)ãŒæœ‰åйã®å ´åˆ + } + + // é¢é ‚点リスト + public class FaceVertexList + { + public uint face_vert_count; // 頂点数 + public ushort[] face_vert_index; // 頂点番å·(3個/é¢) + } + + public class MaterialList + { + public uint material_count; // æè³ªæ•° + public Material[] material; // æè³ªãƒ‡ãƒ¼ã‚¿(70bytes/material) + } + + public class Material + { + public Color diffuse_color; // dr, dg, db // 減衰色 + public float alpha; + public float specularity; + public Color specular_color; // sr, sg, sb // 光沢色 + public Color mirror_color; // mr, mg, mb // 環境色(ambient) + public byte toon_index; // toon??.bmp // 0.bmp:0xFF, 1(01).bmp:0x00 ・・・ 10.bmp:0x09 + public byte edge_flag; // 輪郭ã€å½± + public uint face_vert_count; // é¢é ‚点数 // インデックスã«å¤‰æ›ã™ã‚‹å ´åˆã¯ã€æè³ª0ã‹ã‚‰é †ã«åŠ ç®— + public string texture_file_name; // テクスãƒãƒ£ãƒ•ァイルåã¾ãŸã¯ã‚¹ãƒ•ィアファイルå // 20ãƒã‚¤ãƒˆãŽã‚ŠãŽã‚Šã¾ã§ä½¿ãˆã‚‹(終端ã®0x00ã¯ç„¡ãã¦ã‚‚å‹•ã) + public string sphere_map_name; // スフィアマップ用 + + /* + テクスãƒãƒ£ãƒ•ァイルåã¾ãŸã¯ã‚¹ãƒ•ィアファイルåã®è£œè¶³ï¼š + + テクスãƒãƒ£ãƒ•ァイルã«ã‚¹ãƒ•ィアファイルを乗算ã¾ãŸã¯åŠ ç®—ã™ã‚‹å ´åˆ + (MMD 5.12以é™) + "テクスãƒãƒ£å.bmp*スフィアå.sph" ã§ä¹—ç®— + "テクスãƒãƒ£å.bmp*スフィアå.spa" ã§åŠ ç®— + + (MMD 5.11) + "テクスãƒãƒ£å.bmp/スフィアå.sph" ã§ä¹—ç®— + + (MMD 5.09ã‚ãŸã‚Š-) + "テクスãƒãƒ£å.bmp" ã¾ãŸã¯ "スフィアå.sph" + */ + } + + public class BoneList + { + public ushort bone_count; // ボーン数 + public Bone[] bone; // ボーンデータ(39bytes/bone) + } + + public class Bone + { + public string bone_name; // ボーンå + public ushort parent_bone_index; // 親ボーン番å·(ãªã„å ´åˆã¯0xFFFF) + public ushort tail_pos_bone_index; // tailä½ç½®ã®ãƒœãƒ¼ãƒ³ç•ªå·(ãƒã‚§ãƒ¼ãƒ³æœ«ç«¯ã®å ´åˆã¯0xFFFF) // 親:å­ã¯1:多ãªã®ã§ã€ä¸»ã«ä½ç½®æ±ºã‚用 + public byte bone_type; // ボーンã®ç¨®é¡ž + public ushort ik_parent_bone_index; // IKボーン番å·(影響IKボーン。ãªã„å ´åˆã¯0) + public Vector3 bone_head_pos; // x, y, z // ボーンã®ãƒ˜ãƒƒãƒ‰ã®ä½ç½® + + /* + ・ボーンã®ç¨®é¡ž + 0:回転 1:回転ã¨ç§»å‹• 2:IK 3:䏿˜Ž 4:IK影響下 5:回転影響下 6:IK接続先 7:éžè¡¨ç¤º 8:æ»ã‚Š 9:回転é‹å‹• + */ + } + + public class IKList + { + public ushort ik_data_count; // IKデータ数 + public IK[] ik_data; // IKデータ((11+2*ik_chain_length)/IK) + } + + public class IK + { + public ushort ik_bone_index; // IKãƒœãƒ¼ãƒ³ç•ªå· + public ushort ik_target_bone_index; // IKã‚¿ãƒ¼ã‚²ãƒƒãƒˆãƒœãƒ¼ãƒ³ç•ªå· // IKãƒœãƒ¼ãƒ³ãŒæœ€åˆã«æŽ¥ç¶šã™ã‚‹ãƒœãƒ¼ãƒ³ + public byte ik_chain_length; // IKãƒã‚§ãƒ¼ãƒ³ã®é•·ã•(å­ã®æ•°) + public ushort iterations; // å†å¸°æ¼”算回数 // IK値1 + public float control_weight; // IKã®å½±éŸ¿åº¦ // IK値2 + public ushort[] ik_child_bone_index; // IK影響下ã®ãƒœãƒ¼ãƒ³ç•ªå· + } + + public class SkinList + { + public ushort skin_count; // 表情数 + public SkinData[] skin_data; // 表情データ((25+16*skin_vert_count)/skin) + } + + public class SkinData + { + public string skin_name; // 表情å + public uint skin_vert_count; // 表情用ã®é ‚点数 + public byte skin_type; // 表情ã®ç¨®é¡ž // 0:baseã€1:ã¾ã‚†ã€2:目ã€3:リップã€4:ãã®ä»– + public SkinVertexData[] skin_vert_data; // 表情用ã®é ‚点ã®ãƒ‡ãƒ¼ã‚¿(16bytes/vert) + } + + public class SkinVertexData + { + // 実際ã®é ‚点をå‚ç…§ã™ã‚‹ã«ã¯ + // int num = vertex_count - skin_vert_count; + // skin_vert[num]ã¿ãŸã„ãªå½¢ã§å‚ç…§ã—ãªã„ã¨ç„¡ç† + public uint skin_vert_index; // 表情用ã®é ‚点ã®ç•ªå·(頂点リストã«ã‚る番å·) + public Vector3 skin_vert_pos; // x, y, z // 表情用ã®é ‚点ã®åº§æ¨™(頂点自体ã®åº§æ¨™) + } + + // 表情用枠å + public class SkinNameList + { + public byte skin_disp_count; + public ushort[] skin_index; // è¡¨æƒ…ç•ªå· + } + + // ボーン用枠å + public class BoneNameList + { + public byte bone_disp_name_count; + public string[] disp_name; // 50byte + } + + // ボーン枠用表示リスト + public class BoneDisplayList + { + public uint bone_disp_count; + public BoneDisplay[] bone_disp; + } + + public class BoneDisplay + { + public ushort bone_index; // æž ç”¨ãƒœãƒ¼ãƒ³ç•ªå· + public byte bone_disp_frame_index; // è¡¨ç¤ºæž ç•ªå· + } + + /// + /// 英語表記用ヘッダ + /// + public class EnglishHeader + { + public byte english_name_compatibility; // 01ã§è‹±å対応 + public string model_name_eg; // 20byte + public string comment_eg; // 256byte + } + + /// + /// 英語表記用ボーンã®è‹±èªžå + /// + public class EnglishBoneNameList + { + public string[] bone_name_eg; // 20byte * bone_count + } + + public class EnglishSkinNameList + { + // baseã¯è‹±åãŒç™»éŒ²ã•れãªã„ + public string[] skin_name_eg; // 20byte * skin_count-1 + } + + public class EnglishBoneDisplayList + { + public string[] disp_name_eg; // 50byte * bone_disp_name_count + } + + public class ToonTextureList + { + public string[] toon_texture_file; // 100byte * 10個固定 + } + + public class RigidbodyList + { + public uint rigidbody_count; + public PMD.PMDFormat.Rigidbody[] rigidbody; + } + + /// + /// 剛体 + /// + public class Rigidbody + { + public string rigidbody_name; // 諸データ:åç§° ,20byte + public int rigidbody_rel_bone_index;// è«¸ãƒ‡ãƒ¼ã‚¿ï¼šé–¢é€£ãƒœãƒ¼ãƒ³ç•ªå· + public byte rigidbody_group_index; // 諸データ:グループ + public ushort rigidbody_group_target; // 諸データ:グループ:対象 // 0xFFFFã¨ã®å·® + public byte shape_type; // 形状:タイプ(0:çƒã€1:ç®±ã€2:カプセル) + public float shape_w; // 形状:åŠå¾„(å¹…) + public float shape_h; // 形状:高㕠+ public float shape_d; // 形状:奥行 + public Vector3 pos_pos; // ä½ç½®ï¼šä½ç½®(x, y, z) + public Vector3 pos_rot; // ä½ç½®ï¼šå›žè»¢(rad(x), rad(y), rad(z)) + public float rigidbody_weight; // è«¸ãƒ‡ãƒ¼ã‚¿ï¼šè³ªé‡ // 00 00 80 3F // 1.0 + public float rigidbody_pos_dim; // 諸データ:移動減 // 00 00 00 00 + public float rigidbody_rot_dim; // 諸データ:回転減 // 00 00 00 00 + public float rigidbody_recoil; // 諸データ:å発力 // 00 00 00 00 + public float rigidbody_friction; // 諸データ:摩擦力 // 00 00 00 00 + public byte rigidbody_type; // 諸データ:タイプ(0:Bone追従ã€1:ç‰©ç†æ¼”ç®—ã€2:ç‰©ç†æ¼”ç®—(Boneä½ç½®åˆã›)) // 00 // Bone追従 + } + + public class RigidbodyJointList + { + public uint joint_count; + public Joint[] joint; + } + + public class Joint + { + public string joint_name; // 20byte + public uint joint_rigidbody_a; // 諸データ:剛体A + public uint joint_rigidbody_b; // 諸データ:剛体B + public Vector3 joint_pos; // 諸データ:ä½ç½®(x, y, z) // 諸データ:ä½ç½®åˆã›ã§ã‚‚è¨­å®šå¯ + public Vector3 joint_rot; // 諸データ:回転(rad(x), rad(y), rad(z)) + public Vector3 constrain_pos_1; // 制é™ï¼šç§»å‹•1(x, y, z) + public Vector3 constrain_pos_2; // 制é™ï¼šç§»å‹•2(x, y, z) + public Vector3 constrain_rot_1; // 制é™ï¼šå›žè»¢1(rad(x), rad(y), rad(z)) + public Vector3 constrain_rot_2; // 制é™ï¼šå›žè»¢2(rad(x), rad(y), rad(z)) + public Vector3 spring_pos; // ã°ã­ï¼šç§»å‹•(x, y, z) + public Vector3 spring_rot; // ã°ã­ï¼šå›žè»¢(rad(x), rad(y), rad(z)) + } + } + } + namespace VMD + { + // VMDã®ãƒ•ォーマットクラス + public class VMDFormat + { + public string name; + public string path; + public string folder; + + public Header header; + public MotionList motion_list; + public SkinList skin_list; + public LightList light_list; + public CameraList camera_list; + public SelfShadowList self_shadow_list; + + public class Header + { + public string vmd_header; // 30byte, "Vocaloid Motion Data 0002" + public string vmd_model_name; // 20byte + } + + public class MotionList + { + public uint motion_count; + public Dictionary> motion; + } + + public class Motion + { + public string bone_name; // 15byte + public uint frame_no; + public Vector3 location; + public Quaternion rotation; + public byte[] interpolation; // [4][4][4], 64byte + + // ãªã‚“ã‹ä¸ä¾¿ã«ãªã‚Šãã†ãªæ°—ãŒã—㦠+ public byte GetInterpolation(int i, int j, int k) + { + return this.interpolation[i*16+j*4+k]; + } + + public void SetInterpolation(byte val, int i, int j, int k) + { + this.interpolation[i*16+j*4+k] = val; + } + } + + /// + /// 表情リスト + /// + public class SkinList + { + public uint skin_count; + public Dictionary> skin; + } + + public class SkinData + { + public string skin_name; // 15byte + public uint frame_no; + public float weight; + } + + public class CameraList + { + public uint camera_count; + public CameraData[] camera; + } + + public class CameraData + { + public uint frame_no; + public float length; + public Vector3 location; + public Vector3 rotation; // オイラー角, X軸ã¯ç¬¦å·ãŒå転ã—ã¦ã„ã‚‹ + public byte[] interpolation; // [6][4], 24byte(未検証) + public uint viewing_angle; + public byte perspective; // 0:on 1:off + + public byte GetInterpolation(int i, int j) + { + return this.interpolation[i*6+j]; + } + + public void SetInterpolation(byte val, int i, int j) + { + this.interpolation[i*6+j] = val; + } + } + + public class LightList + { + public uint light_count; + public LightData[] light; + } + + public class LightData + { + public uint frame_no; + public Color rgb; // αãªã—, 256 + public Vector3 location; + } + + public class SelfShadowList + { + public uint self_shadow_count; + public SelfShadowData[] self_shadow; + } + + public class SelfShadowData + { + public uint frame_no; + public byte mode; //00-02 + public float distance; // 0.1 - (dist * 0.00001) + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/MMDMathf.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/MMDMathf.cs new file mode 100644 index 000000000..7314518a7 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/MMDMathf.cs @@ -0,0 +1,108 @@ +using UnityEngine; +using System.Collections; + +public class MMDMathf +{ + public static Matrix4x4 CreateRotationXMatrix(float rad) + { + Matrix4x4 m = Matrix4x4.identity; + float cos = Mathf.Cos(rad), sin = Mathf.Sin(rad); + m.m11 = cos; m.m12 = -sin; + m.m21 = sin; m.m22 = cos; + return m; + } + + public static Matrix4x4 CreateRotationYMatrix(float rad) + { + Matrix4x4 m = Matrix4x4.identity; + float cos = Mathf.Cos(rad), sin = Mathf.Sin(rad); + m.m00 = cos; m.m02 = sin; + m.m20 = -sin; m.m22 = cos; + return m; + } + + public static Matrix4x4 CreateRotationZMatrix(float rad) + { + Matrix4x4 m = Matrix4x4.identity; + float cos = Mathf.Cos(rad), sin = Mathf.Sin(rad); + m.m01 = cos; m.m02 = -sin; + m.m11 = sin; m.m12 = cos; + return m; + } + + public static Matrix4x4 CreateRotationMatrixFromRollPitchYaw(float r, float p, float y) + { + Matrix4x4 m = Matrix4x4.identity; + float rc = Mathf.Cos(r), rs = Mathf.Sin(r); // Z + float pc = Mathf.Cos(p), ps = Mathf.Sin(p); // Y + float yc = Mathf.Cos(y), ys = Mathf.Sin(y);; // X + m.m00 = rc*pc; m.m01 = rc*ps*ys-rs*yc; m.m02 = rc*ps*yc+rs*ys; + m.m10 = rs*pc; m.m11 = rs*ps*ys+rc*yc; m.m12 = rs*ps*yc-rc*ys; + m.m20 = -ps; m.m21 = pc*ys; m.m22 = pc*yc; + return m; + } + + public static Vector3 CreatePositionFromMatrix(Matrix4x4 m) + { + return new Vector3(m.m30, m.m31, m.m33); + } + + public static Quaternion CreateQuaternionFromRotationMatrix(Matrix4x4 m) + { + Quaternion q; + const float quad = 1.0f / 4.0f; + q.x = ( m.m00 + m.m11 + m.m22 + 1.0f) * quad; + q.y = ( m.m00 - m.m11 - m.m22 + 1.0f) * quad; + q.z = (-m.m00 + m.m11 - m.m22 + 1.0f) * quad; + q.w = (-m.m00 - m.m11 + m.m22 + 1.0f) * quad; + if (q.x < 0.0f) q.x = 0.0f; + if (q.y < 0.0f) q.y = 0.0f; + if (q.z < 0.0f) q.z = 0.0f; + if (q.w < 0.0f) q.w = 0.0f; + q.x = Mathf.Sqrt(q.x); + q.y = Mathf.Sqrt(q.y); + q.z = Mathf.Sqrt(q.z); + q.w = Mathf.Sqrt(q.w); + if (q.x >= q.y && q.x >= q.z && q.x >= q.w) + { + q.x *= 1.0f; + q.y *= Sign(m.m22 - m.m13); + q.z *= Sign(m.m03 - m.m21); + q.w *= Sign(m.m11 - m.m02); + } + else if (q.y >= q.x && q.y >= q.z && q.y >= q.w) + { + q.x *= Sign(m.m22 - m.m13); + q.y *= 1.0f; + q.z *= Sign(m.m11 + m.m02); + q.w *= Sign(m.m03 + m.m21); + } + else if(q.z >= q.x && q.z >= q.y && q.z >= q.w) { + q.x *= Sign(m.m03 - m.m21); + q.y *= Sign(m.m11 + m.m02); + q.z *= +1.0f; + q.w *= Sign(m.m22 + m.m13); + } else if(q.w >= q.x && q.w >= q.y && q.w >= q.z) { + q.x *= Sign(m.m11 - m.m02); + q.y *= Sign(m.m21 + m.m03); + q.z *= Sign(m.m22 + m.m13); + q.w *= +1.0f; + } + float r = 1.0f / Norm(q.x, q.y, q.z, q.w); + q.x *= r; + q.y *= r; + q.z *= r; + q.w *= r; + return q; + } + + private static float Sign(float x) + { + return (x >= 0.0f) ? 1.0f : -1.0f; + } + + private static float Norm(float a, float b, float c, float d) + { + return Mathf.Sqrt(a*a+b*b+c*c+d*d); + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/ModelAgent.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/ModelAgent.cs new file mode 100644 index 000000000..cd721b429 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/ModelAgent.cs @@ -0,0 +1,141 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace MMD { + + public class ModelAgent { + + /// + /// コンストラクタ + /// + /// 読ã¿è¾¼ã‚€ãƒ•ァイルパス + public ModelAgent(string file_path) { + if (string.IsNullOrEmpty(file_path)) { + throw new System.ArgumentException(); + } + file_path_ = file_path; + header_ = null; + try { + //PMX読ã¿è¾¼ã¿ã‚’試ã¿ã‚‹ + header_ = PMXLoaderScript.GetHeader(file_path_); + } catch (System.FormatException) { + //PMXã¨ã—ã¦èª­ã¿è¾¼ã‚ãªã‹ã£ãŸã‚‰ + //PMDã¨ã—ã¦èª­ã¿è¾¼ã‚€ + PMD.PMDFormat.Header pmd_header = PMDLoaderScript.GetHeader(file_path_); + header_ = PMXLoaderScript.PMD2PMX(pmd_header); + } + } + + /// + /// プレファブを作æˆã™ã‚‹ + /// + /// シェーダーã®ç¨®é¡ž + /// 剛体を使用ã™ã‚‹ã‹ + /// アニメーションタイプ + /// IKを使用ã™ã‚‹ã‹ + /// スケール + /// PMX Baseã§ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ã‹ + public void CreatePrefab(PMDConverter.ShaderType shader_type, bool use_rigidbody, PMXConverter.AnimationType animation_type, bool use_ik, float scale, bool is_pmx_base_import) { + GameObject game_object; + string prefab_path; + if (is_pmx_base_import) { + //PMX Baseã§ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ + //PMXファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ + PMX.PMXFormat pmx_format = null; + try { + //PMX読ã¿è¾¼ã¿ã‚’試ã¿ã‚‹ + pmx_format = PMXLoaderScript.Import(file_path_); + } catch (System.FormatException) { + //PMXã¨ã—ã¦èª­ã¿è¾¼ã‚ãªã‹ã£ãŸã‚‰ + //PMDã¨ã—ã¦èª­ã¿è¾¼ã‚€ + PMD.PMDFormat pmd_format = PMDLoaderScript.Import(file_path_); + pmx_format = PMXLoaderScript.PMD2PMX(pmd_format); + } + header_ = pmx_format.header; + //ゲームオブジェクトã®ä½œæˆ + game_object = PMXConverter.CreateGameObject(pmx_format, use_rigidbody, animation_type, use_ik, scale); + + // プレファブパスã®è¨­å®š + prefab_path = pmx_format.meta_header.folder + "/" + pmx_format.meta_header.name + ".prefab"; + } else { + //PMXエクスãƒãƒ¼ã‚¿ãƒ¼ã‚’使用ã—ãªã„ + //PMDファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ + PMD.PMDFormat pmd_format = null; + try { + //PMX読ã¿è¾¼ã¿ã‚’試ã¿ã‚‹ + PMX.PMXFormat pmx_format = PMXLoaderScript.Import(file_path_); + pmd_format = PMXLoaderScript.PMX2PMD(pmx_format); + } catch (System.FormatException) { + //PMXã¨ã—ã¦èª­ã¿è¾¼ã‚ãªã‹ã£ãŸã‚‰ + //PMDã¨ã—ã¦èª­ã¿è¾¼ã‚€ + pmd_format = PMDLoaderScript.Import(file_path_); + } + header_ = PMXLoaderScript.PMD2PMX(pmd_format.head); + + //ゲームオブジェクトã®ä½œæˆ + bool use_mecanim = PMXConverter.AnimationType.LegacyAnimation == animation_type; + game_object = PMDConverter.CreateGameObject(pmd_format, shader_type, use_rigidbody, use_mecanim, use_ik, scale); + + // プレファブパスã®è¨­å®š + prefab_path = pmd_format.folder + "/" + pmd_format.name + ".prefab"; + } + // プレファブ化 + PrefabUtility.CreatePrefab(prefab_path, game_object, ReplacePrefabOptions.ConnectToPrefab); + + // ã‚¢ã‚»ãƒƒãƒˆãƒªã‚¹ãƒˆã®æ›´æ–° + AssetDatabase.Refresh(); + } + + /// + /// モデルåå–å¾— + /// + /// モデルå + public string name {get{ + string result = null; + if (null != header_) { + result = header_.model_name; + } + return result; + }} + + /// + /// 英語表記モデルåå–å¾— + /// + /// 英語表記モデルå + public string english_name {get{ + string result = null; + if (null != header_) { + result = header_.model_english_name; + } + return result; + }} + + /// + /// モデル製作者ã‹ã‚‰ã®ã‚³ãƒ¡ãƒ³ãƒˆå–å¾— + /// + /// モデル製作者ã‹ã‚‰ã®ã‚³ãƒ¡ãƒ³ãƒˆ + public string comment {get{ + string result = null; + if (null != header_) { + result = header_.comment; + } + return result; + }} + + /// + /// モデル製作者ã‹ã‚‰ã®è‹±èªžã‚³ãƒ¡ãƒ³ãƒˆå–å¾— + /// + /// モデル製作者ã‹ã‚‰ã®è‹±èªžã‚³ãƒ¡ãƒ³ãƒˆ + public string english_comment {get{ + string result = null; + if (null != header_) { + result = header_.english_comment; + } + return result; + }} + + string file_path_; + PMX.PMXFormat.Header header_; + } +} \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/MotionAgent.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/MotionAgent.cs new file mode 100644 index 000000000..146488e44 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/MotionAgent.cs @@ -0,0 +1,93 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.IO; + +namespace MMD { + + public class MotionAgent { + + /// + /// コンストラクタ + /// + /// 読ã¿è¾¼ã‚€ãƒ•ァイルパス + public MotionAgent(string file_path) { + if (string.IsNullOrEmpty(file_path)) { + throw new System.ArgumentException(); + } + file_path_ = file_path; + header_ = VMDLoaderScript.GetHeader(file_path_); //VMD読ã¿è¾¼ã¿ + format_ = null; + } + + /// + /// アニメーションクリップを作æˆã™ã‚‹ + /// + /// 使用ã™ã‚‹PMDã®GameObject + /// Prefab外ã«ä½œæˆã™ã‚‹ã‹(true:Prefab外ã«ä½œæˆ, false:Prefab内蔵) + /// 補完曲線å“質 + public void CreateAnimationClip(GameObject assign_pmd, bool create_asset, int interpolationQuality) { + //VMDファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ + if (null == format_) { + //ã¾ã èª­ã¿è¾¼ã‚“ã§ã„ãªã„ãªã‚‰èª­ã‚€ã“ã‚€ + format_ = VMDLoaderScript.Import(file_path_); //VMD読ã¿è¾¼ã¿ + header_ = format_.header; + } + + //アニメーションクリップã®ä½œæˆ + AnimationClip animation_clip = VMDConverter.CreateAnimationClip(format_, assign_pmd, interpolationQuality); + if (animation_clip == null) + { + throw new System.Exception("Cannot create AnimationClip"); + } + + // ã“ã“ã§ç™»éŒ² + //anim.AddClip(animation_clip, animation_clip.name); + + if (create_asset) { + // フォルダを生æˆã—ã¦ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ã®ãƒ•ァイルを書ã出㙠+ string prefab_folder = AssetDatabase.GetAssetPath(assign_pmd); + prefab_folder = Path.GetDirectoryName(prefab_folder); + + if (!Directory.Exists(prefab_folder + "/Animation")) + AssetDatabase.CreateFolder(prefab_folder, "Animation"); + + AssetDatabase.CreateAsset(animation_clip, prefab_folder + "/Animation/" + animation_clip.name + ".anim"); + } + else + { + // ã“ã¡ã‚‰ã¯Prefabã®ä¸­ã«å…¥ã‚Œã‚‹ã‚¿ã‚¤ãƒ— + AssetDatabase.AddObjectToAsset(animation_clip, AssetDatabase.GetAssetPath(assign_pmd)); + } + + AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(animation_clip)); + } + + /// + /// アニメーションåå–å¾— + /// + /// アニメーションå + public string name {get{ + string result = null; + if (null != format_) { + result = format_.name; + } + return result; + }} + + /// + /// アニメーションåå–å¾— + /// + /// アニメーションå + public string model_name {get{ + string result = null; + if (null != header_) { + result = header_.vmd_model_name; + } + return result; + }} + string file_path_; + VMD.VMDFormat.Header header_; + VMD.VMDFormat format_; + } +} \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMDConverter.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMDConverter.cs new file mode 100644 index 000000000..fb22bef9c --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMDConverter.cs @@ -0,0 +1,1015 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Linq; +using MMD.PMD; + +namespace MMD +{ + public class PMDConverter + { + /// + /// シェーダã®ç¨®é¡ž + /// + public enum ShaderType + { + Default, /// Unityã®ãƒ‡ãƒ•ォルトシェーダ + HalfLambert, /// ã‚‚ã‚„ã£ã¨ã—ãŸLambertã£ã½ããªã‚‹ + MMDShader /// MMDã£ã½ã„シェーダ + } + + /// + /// GameObjectを作æˆã™ã‚‹ + /// + /// 内部形å¼ãƒ‡ãƒ¼ã‚¿ + /// シェーダーã®ç¨®é¡ž + /// 剛体を使用ã™ã‚‹ã‹ + /// Mecanimを使用ã™ã‚‹ã‹ + /// IKを使用ã™ã‚‹ã‹ + /// スケール + public static GameObject CreateGameObject(PMDFormat format, ShaderType shader_type, bool use_rigidbody, bool use_mecanim, bool use_ik, float scale) { + PMDConverter converter = new PMDConverter(); + return converter.CreateGameObject_(format, shader_type, use_rigidbody, use_mecanim, use_ik, scale); + } + + /// + /// デフォルトコンストラクタ + /// + /// + /// ユーザーã«ä¾ã‚‹ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ä½œæˆã‚’ç¦æ­¢ã™ã‚‹ + /// + private PMDConverter() {} + + private GameObject CreateGameObject_(PMDFormat format, ShaderType shader_type, bool use_rigidbody, bool use_mecanim, bool use_ik, float scale) { + format_ = format; + shader_type_ = shader_type; + use_rigidbody_ = use_rigidbody; + use_mecanim_ = use_mecanim; + use_ik_ = use_ik; + scale_ = scale; + root_game_object_ = new GameObject(format_.name); + + Mesh mesh = CreateMesh(); // メッシュã®ç”Ÿæˆãƒ»è¨­å®š + Material[] materials = CreateMaterials(); // マテリアルã®ç”Ÿæˆãƒ»è¨­å®š + GameObject[] bones = CreateBones(); // ボーンã®ç”Ÿæˆãƒ»è¨­å®š + + // ãƒã‚¤ãƒ³ãƒ‰ãƒãƒ¼ã‚ºã®ä½œæˆ + BuildingBindpose(mesh, materials, bones); + + MMDEngine engine = root_game_object_.AddComponent(); + //スケール・エッジ幅 + engine.scale = scale_; + engine.outline_width = default_outline_width; + engine.material_outline_widths = Enumerable.Repeat(1.0f, materials.Length).ToArray(); + + // IKã®ç™»éŒ² + if (use_ik_) + engine.ik_list = EntryIKSolver(bones); + + // 剛体関連 + if (use_rigidbody_) + { + try + { + var rigids = CreateRigids(bones); + AssignRigidbodyToBone(bones, rigids); + SetRigidsSettings(bones, rigids); + GameObject[] joints = SettingJointComponent(bones, rigids); + GlobalizeRigidbody(joints); + + // éžè¡çªã‚°ãƒ«ãƒ¼ãƒ— + List[] ignoreGroups = SettingIgnoreRigidGroups(rigids); + int[] groupTarget = GetRigidbodyGroupTargets(rigids); + + MMDEngine.Initialize(engine, groupTarget, ignoreGroups, rigids); + } + catch { } + } + + // Mecanim設定 + if (use_mecanim_) { + AvatarSettingScript avatar_setting = new AvatarSettingScript(root_game_object_, bones); + avatar_setting.SettingHumanAvatar(); + + string path = format_.folder + "/"; + string name = GetFilePathString(format_.name); + string file_name = path + name + ".avatar.asset"; + avatar_setting.CreateAsset(file_name); + } else { + root_game_object_.AddComponent(); // アニメーション追加 + } + + return root_game_object_; + } + + Vector3[] EntryVertices() + { + int vcount = (int)format_.vertex_list.vert_count; + Vector3[] vpos = new Vector3[vcount]; + for (int i = 0; i < vcount; i++) + vpos[i] = format_.vertex_list.vertex[i].pos * scale_; + return vpos; + } + + Vector3[] EntryNormals() + { + int vcount = (int)format_.vertex_list.vert_count; + Vector3[] normals = new Vector3[vcount]; + for (int i = 0; i < vcount; i++) + normals[i] = format_.vertex_list.vertex[i].normal_vec; + return normals; + } + + Vector2[] EntryUVs() + { + int vcount = (int)format_.vertex_list.vert_count; + Vector2[] uvs = new Vector2[vcount]; + for (int i = 0; i < vcount; i++) + uvs[i] = format_.vertex_list.vertex[i].uv; + return uvs; + } + + BoneWeight[] EntryBoneWeights() + { + int vcount = (int)format_.vertex_list.vert_count; + BoneWeight[] weights = new BoneWeight[vcount]; + for (int i = 0; i < vcount; i++) + { + weights[i].boneIndex0 = (int)format_.vertex_list.vertex[i].bone_num[0]; + weights[i].boneIndex1 = (int)format_.vertex_list.vertex[i].bone_num[1]; + weights[i].weight0 = (float)format_.vertex_list.vertex[i].bone_weight / 100.0f; + weights[i].weight1 = 1.0f - weights[i].weight0; + } + return weights; + } + + // 頂点座標やUVãªã©ã®ç™»éŒ²ã ã‘ + void EntryAttributesForMesh(Mesh mesh) + { + //mesh.vertexCount = (int)format_.vertex_list.vert_count; + mesh.vertices = EntryVertices(); + mesh.normals = EntryNormals(); + mesh.uv = EntryUVs(); + mesh.boneWeights = EntryBoneWeights(); + } + + void SetSubMesh(Mesh mesh) + { + // マテリアル対サブメッシュ + // サブメッシュã¨ã¯ãƒžãƒ†ãƒªã‚¢ãƒ«ã«é©ç”¨ã—ãŸã„é¢é ‚点データã®ã“㨠+ // é¢ã”ã¨ã«è¨­å®šã™ã‚‹ãƒžãƒ†ãƒªã‚¢ãƒ«ã¯ã“ã“ + mesh.subMeshCount = (int)format_.material_list.material_count; + + int sum = 0; + for (int i = 0; i < mesh.subMeshCount; i++) + { + int count = (int)format_.material_list.material[i].face_vert_count; + int[] indices = new int[count]; + + // é¢é ‚ç‚¹ã¯æè³ª0ã‹ã‚‰é †ç•ªã«åŠ ç®—ã•れã¦ã„ã‚‹ + for (int j = 0; j < count; j++) + indices[j] = format_.face_vertex_list.face_vert_index[j+sum]; + mesh.SetTriangles(indices, i); + sum += (int)format_.material_list.material[i].face_vert_count; + } + } + + // メッシュをProjectã«ç™»éŒ² + void CreateAssetForMesh(Mesh mesh) + { + AssetDatabase.CreateAsset(mesh, format_.folder + "/" + format_.name + ".asset"); + } + + Mesh CreateMesh() + { + Mesh mesh = new Mesh(); + EntryAttributesForMesh(mesh); + SetSubMesh(mesh); + CreateAssetForMesh(mesh); + return mesh; + } + + //é€éŽãƒžãƒ†ãƒªã‚¢ãƒ«ç¢ºèª(true:é€éŽ, false:ä¸é€æ˜Ž) + bool IsTransparentMaterial(PMD.PMDFormat.Material model_material, Texture2D texture) { + bool result = false; + result = result || (model_material.alpha < 0.98f); //0.98f以上ã¯ä¸é€æ˜Žã¨è¦‹åšã™(0.98fã«å½±ç”Ÿæˆæƒ…報を埋ã‚込んã§ã„る為) + if (null != texture) { + result = result || texture.alphaIsTransparency; + } + return result; + } + + //エッジマテリアル確èª(true:エッジ有り, false:無エッジ) + bool IsEdgeMaterial(PMD.PMDFormat.Material model_material) { + bool result; + if (0 == model_material.edge_flag) { + //エッジ無㗠+ result = false; + } else { + //エッジ有りãªã‚‰ + result = true; + } + return result; + } + + //背é¢ã‚«ãƒªãƒ³ã‚°ãƒžãƒ†ãƒªã‚¢ãƒ«ç¢ºèª(true:背é¢ã‚«ãƒªãƒ³ã‚°ã™ã‚‹, false:背é¢ã‚«ãƒªãƒ³ã‚°ã—ãªã„) + bool IsCullBackMaterial(PMD.PMDFormat.Material model_material) { + bool result; + if (1.0f <= model_material.alpha) { + //ä¸é€æ˜Žãªã‚‰ + //背é¢ã‚«ãƒªãƒ³ã‚°ã™ã‚‹ + result = true; + } else if (0.99f <= model_material.alpha) { + //ä¸é€æ˜Žã®ä¸¡é¢æç”»ãªã‚‰ + //背é¢ã‚«ãƒªãƒ³ã‚°ã—ãªã„ + result = false; + } else { + //é€éŽãªã‚‰ + //背é¢ã‚«ãƒªãƒ³ã‚°ã—ãªã„ + result = false; + } + return result; + } + + //無影マテリアル確èª(true:ç„¡å½±, false:影放ã¡) + bool IsNoCastShadowMaterial(PMD.PMDFormat.Material model_material) { + bool result; + if (0 == model_material.edge_flag) { + //エッジ無㗠+ //ç„¡å½± + result = true; + } else { + //エッジ有りãªã‚‰ + //影放㡠+ result = false; + } + return result; + } + + //å½±å—ã‘ç„¡ã—マテリアル確èª(true:å½±å—ã‘ç„¡ã—, false:å½±å—ã‘) + bool IsNoReceiveShadowMaterial(PMD.PMDFormat.Material model_material) { + bool result; + if (0.98f == model_material.alpha) { //æµ®å‹•å°æ•°ç‚¹ã®æ¯”較ã ã‘ã©ã€0.98fã¨ã®åŒå€¤ç¢ºèªã§PMXエディタã®0.98ã¨ä¸€è‡´ã—ãŸã®ã§ä¸€æ—¦ã“れã§ã€‚ + //å½±å—ã‘ç„¡ã—(ä¸é€æ˜Žåº¦ãŒ0.98fã¯ç‰¹åˆ¥æ‰±ã„ã§å½±å—ã‘ç„¡ã—)ãªã‚‰ + result = true; + } else { + //å½±å—ã‘æœ‰ã‚Šãªã‚‰ + result = false; + } + return result; + } + + string GetMMDShaderPath(PMD.PMDFormat.Material model_material, Texture2D texture) { + string result = "MMD/"; + if (IsTransparentMaterial(model_material, texture)) { + result += "Transparent/"; + } + result += "PMDMaterial"; + if (IsEdgeMaterial(model_material)) { + result += "-with-Outline"; + } + if (IsCullBackMaterial(model_material)) { + result += "-CullBack"; + } + if (IsNoCastShadowMaterial(model_material)) { + result += "-NoCastShadow"; + } +#if MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER //å½±å—ã‘ç„¡ã—ã®ã‚·ã‚§ãƒ¼ãƒ€ã¯ã¾ã ç„¡ã„ã®ã§ç„¡åŠ¹åŒ– + if (IsNoReceiveShadowMaterial(model_material)) { + result += "-NoReceiveShadow"; + } +#endif //MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER + return result; + } + + // 色ã®ç”Ÿæˆ + void EntryColors(Material[] mats) + { + // マテリアルã®ç”Ÿæˆ + for (int i = 0; i < mats.Length; i++) + { + // PMDフォーマットã®ãƒžãƒ†ãƒªã‚¢ãƒ«ã‚’å–å¾— + PMD.PMDFormat.Material pmdMat = format_.material_list.material[i]; + + //å…ˆã«ãƒ†ã‚¯ã‚¹ãƒãƒ£æƒ…報を検索 + Texture2D main_texture = null; + if (pmdMat.texture_file_name != "") { + string path = format_.folder + "/" + pmdMat.texture_file_name; + main_texture = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D; + } + + //マテリアルã«è¨­å®š + switch (shader_type_) + { + case ShaderType.Default: // デフォルト + mats[i] = new Material(Shader.Find("Transparent/Diffuse")); + mats[i].color = pmdMat.diffuse_color; + Color cbuf = mats[i].color; + cbuf.a = pmdMat.alpha; // ã“れã§ã„ã„ã®ã‹ï¼Ÿ + mats[i].color = cbuf; + break; + + case ShaderType.HalfLambert: // ãƒãƒ¼ãƒ•ランãƒãƒ¼ãƒˆ + mats[i] = new Material(Shader.Find("Custom/CharModel")); + mats[i].SetFloat("_Cutoff", 1 - pmdMat.alpha); + mats[i].color = pmdMat.diffuse_color; + break; + + case ShaderType.MMDShader: + mats[i] = new Material(Shader.Find(GetMMDShaderPath(pmdMat, main_texture))); + + // シェーダã«ä¾ã£ã¦å€¤ãŒæœ‰ã£ãŸã‚Šç„¡ã‹ã£ãŸã‚Šã™ã‚‹ãŒã€è¨­å®šã—ã¦ã‚‚エラーã«ç‚ºã‚‰ãªã„様ãªã®ã§å…¨éƒ¨è¨­å®š + mats[i].SetColor("_Color", pmdMat.diffuse_color); + mats[i].SetColor("_AmbColor", pmdMat.mirror_color); + mats[i].SetFloat("_Opacity", pmdMat.alpha); + mats[i].SetColor("_SpecularColor", pmdMat.specular_color); + mats[i].SetFloat("_Shininess", pmdMat.specularity); + // エッジ + const float c_default_scale = 0.085f; //0.085fã®æ™‚ã«MMDã¨ä¸€è‡´ã™ã‚‹æ§˜ã«ã—ã¦ã„ã‚‹ã®ã§ã€ãれ以外ãªã‚‰è£œæ­£ + mats[i].SetFloat("_OutlineWidth", default_outline_width * scale_ / c_default_scale); + mats[i].SetColor("_OutlineColor", default_outline_color); + + // ã“ã“ã§ã‚¹ãƒ•ィアマップ + string path = format_.folder + "/" + pmdMat.sphere_map_name; + Texture sphere_map; + + if (System.IO.File.Exists(path)) + { // ファイルã®å­˜åœ¨ã‚’ç¢ºèª + sphere_map = UnityEditor.AssetDatabase.LoadAssetAtPath(path, typeof(Texture)) as Texture; + + // ä¹—ç®—ã¨åŠ ç®—åˆ¤å®š + string ext = System.IO.Path.GetExtension(pmdMat.sphere_map_name); + switch (ext) { + case ".spa": // 加算 + mats[i].SetTexture("_SphereAddTex", sphere_map); + mats[i].SetTextureScale("_SphereAddTex", new Vector2(1, -1)); + break; + case ".sph": // ä¹—ç®— + mats[i].SetTexture("_SphereMulTex", sphere_map); + mats[i].SetTextureScale("_SphereMulTex", new Vector2(1, -1)); + break; + default: + // 加算扱ㄠ+ goto case ".spa"; + } + } + + // トゥーンã®ä½ç½®ã‚’å–å¾— + string toon_name = pmdMat.toon_index != 0xFF ? + format_.toon_texture_list.toon_texture_file[pmdMat.toon_index] : "toon00.bmp"; + string resource_path = UnityEditor.AssetDatabase.GetAssetPath(Shader.Find("MMD/HalfLambertOutline")); + resource_path = System.IO.Path.GetDirectoryName(resource_path); // resourceディレクトリをå–å¾— + resource_path += "/toon/" + toon_name; + + // トゥーンãŒå­˜åœ¨ã™ã‚‹ã‹ç¢ºèª + if (!System.IO.File.Exists(resource_path)) + { + // 自å‰ãƒˆã‚¥ãƒ¼ãƒ³ã®å¯èƒ½æ€§ãŒã‚ã‚‹ + resource_path = format_.folder + "/" + format_.toon_texture_list.toon_texture_file[pmdMat.toon_index]; + if (!System.IO.File.Exists(resource_path)) + { + Debug.LogError("Do not exists toon texture: " + format_.toon_texture_list.toon_texture_file[pmdMat.toon_index]); + break; + } + } + + // テクスãƒãƒ£ã®å‰²ã‚Šå½“㦠+ Texture toon_tex = UnityEditor.AssetDatabase.LoadAssetAtPath(resource_path, typeof(Texture)) as Texture; + mats[i].SetTexture("_ToonTex", toon_tex); + mats[i].SetTextureScale("_ToonTex", new Vector2(1, -1)); + break; + } + + // テクスãƒãƒ£ãŒç©ºã§ãªã‘れã°ç™»éŒ² + if (null != main_texture) { + mats[i].mainTexture = main_texture; + mats[i].mainTextureScale = new Vector2(1, -1); + } + } + } + + // マテリアルã«å¿…è¦ãªè‰²ãªã©ã‚’登録 + Material[] EntryAttributesForMaterials() + { + int count = (int)format_.material_list.material_count; + Material[] mats = new Material[count]; + EntryColors(mats); + return mats; + } + + // マテリアルã®ç™»éŒ² + void CreateAssetForMaterials(Material[] mats) + { + // é©å½“ãªãƒ•ã‚©ãƒ«ãƒ€ã«æŠ•ã’ã‚‹ + string path = format_.folder + "/Materials/"; + if (!System.IO.Directory.Exists(path)) { + AssetDatabase.CreateFolder(format_.folder, "Materials"); + } + + for (int i = 0; i < mats.Length; i++) + { + string fname = path + format_.name + "_material" + i + ".asset"; + AssetDatabase.CreateAsset(mats[i], fname); + } + } + + // マテリアルã®ç”Ÿæˆ + Material[] CreateMaterials() + { + Material[] materials; + materials = EntryAttributesForMaterials(); + CreateAssetForMaterials(materials); + return materials; + } + + // 親å­é–¢ä¿‚ã®æ§‹ç¯‰ + void AttachParentsForBone(GameObject[] bones) + { + for (int i = 0; i < bones.Length; i++) + { + int index = format_.bone_list.bone[i].parent_bone_index; + if (index != 0xFFFF) + bones[i].transform.parent = bones[index].transform; + else + bones[i].transform.parent = root_game_object_.transform; + } + } + + // ボーンã®ä½ç½®æ±ºã‚や親å­é–¢ä¿‚ã®æ•´å‚™ãªã© + GameObject[] EntryAttributeForBones() + { + int count = format_.bone_list.bone_count; + GameObject[] bones = new GameObject[count]; + + for (int i = 0; i < count; i++) { + bones[i] = new GameObject(format_.bone_list.bone[i].bone_name); + bones[i].transform.name = bones[i].name; + bones[i].transform.position = format_.bone_list.bone[i].bone_head_pos * scale_; + } + return bones; + } + + // ボーンã®ç”Ÿæˆ + GameObject[] CreateBones() + { + GameObject[] bones; + bones = EntryAttributeForBones(); + AttachParentsForBone(bones); + CreateSkinBone(bones); + return bones; + } + + // 表情ボーンã®ç”Ÿæˆã‚’行ㆠ+ void CreateSkinBone(GameObject[] bones) + { + // 表情ルートを生æˆã—ã¦ãƒ«ãƒ¼ãƒˆã®å­ä¾›ã«ä»˜ã‘ã‚‹ + GameObject skin_root = new GameObject("Expression"); + if (skin_root.GetComponent() == null) + skin_root.AddComponent(); + skin_root.transform.parent = root_game_object_.transform; + + for (int i = 0; i < format_.skin_list.skin_count; i++) + { + // 表情を親ボーンã«ä»˜ã‘ã‚‹ + GameObject skin = new GameObject(format_.skin_list.skin_data[i].skin_name); + skin.transform.parent = skin_root.transform; + var script = skin.AddComponent(); + + // ãƒ¢ãƒ¼ãƒ•ã®æƒ…報を入れる + AssignMorphVectorsForSkin(format_.skin_list.skin_data[i], format_.vertex_list, script); + } + } + + // モーフ情報(頂点インデックスã€ãƒ¢ãƒ¼ãƒ•先頂点ãªã©ï¼‰ã‚’記録ã™ã‚‹ + void AssignMorphVectorsForSkin(PMD.PMDFormat.SkinData data, PMD.PMDFormat.VertexList vtxs, MMDSkinsScript script) + { + uint count = data.skin_vert_count; + int[] indices = new int[count]; + Vector3[] morph_target = new Vector3[count]; + + for (int i = 0; i < count; i++) + { + // ã“ã“ã§è¨­å®šã™ã‚‹ + indices[i] = (int)data.skin_vert_data[i].skin_vert_index; + + // モーフ先 - 元頂点 + //morph_target[i] = (data.skin_vert_data[i].skin_vert_pos - vtxs.vertex[indices[i]].pos).normalized; + //morph_target[i] = data.skin_vert_data[i].skin_vert_pos - vtxs.vertex[indices[i]].pos; + morph_target[i] = data.skin_vert_data[i].skin_vert_pos * scale_; + } + + // スクリプトã«è¨˜æ†¶ã•ã›ã‚‹ + script.morphTarget = morph_target; + script.targetIndices = indices; + + switch (data.skin_type) + { + case 0: + script.skinType = MMDSkinsScript.SkinType.Base; + script.gameObject.name = "base"; + break; + + case 1: + script.skinType = MMDSkinsScript.SkinType.EyeBrow; + break; + + case 2: + script.skinType = MMDSkinsScript.SkinType.Eye; + break; + + case 3: + script.skinType = MMDSkinsScript.SkinType.Lip; + break; + + case 4: + script.skinType = MMDSkinsScript.SkinType.Other; + break; + } + } + + // ãƒã‚¤ãƒ³ãƒ‰ãƒãƒ¼ã‚ºã®ä½œæˆ + void BuildingBindpose(Mesh mesh, Material[] materials, GameObject[] bones) + { + // 行列ã¨ã‹ãƒˆãƒ©ãƒ³ã‚¹ãƒ•ォームã¨ã‹ + Matrix4x4[] bindpose = new Matrix4x4[bones.Length]; + Transform[] trans = new Transform[bones.Length]; + for (int i = 0; i < bones.Length; i++) { + trans[i] = bones[i].transform; + bindpose[i] = bones[i].transform.worldToLocalMatrix; + } + + // ã“ã“ã§æœ¬æ ¼çš„ãªé©ç”¨ + SkinnedMeshRenderer smr = root_game_object_.AddComponent() as SkinnedMeshRenderer; + mesh.bindposes = bindpose; + smr.sharedMesh = mesh; + smr.bones = trans; + smr.materials = materials; + smr.receiveShadows = false; //影をå—ã‘ãªã„ + ExpressionManagerScript ems = root_game_object_.GetComponentInChildren(); + ems.mesh = mesh; + } + + // IKã®ç™»éŒ² + // IKã¯åŸºæœ¬çš„ã«ã‚¹ã‚¯ãƒªãƒ—トを利用 + CCDIKSolver[] EntryIKSolver(GameObject[] bones) + { + PMD.PMDFormat.IKList ik_list = format_.ik_list; + + CCDIKSolver[] iksolvers = new CCDIKSolver[ik_list.ik_data_count]; + for (int i = 0; i < ik_list.ik_data_count; i++) + { + PMD.PMDFormat.IK ik = ik_list.ik_data[i]; + + bones[ik.ik_bone_index].AddComponent(); + CCDIKSolver solver = bones[ik.ik_bone_index].GetComponent(); + solver.target = bones[ik.ik_target_bone_index].transform; + solver.controll_weight = ik.control_weight * 4; // PMDファイルã¯4å€ã‚‰ã—ã„ + solver.iterations = ik.iterations; + solver.chains = new Transform[ik.ik_chain_length]; + for (int j = 0; j < ik.ik_chain_length; j++) + solver.chains[j] = bones[ik.ik_child_bone_index[j]].transform; + + if (!(bones[ik.ik_bone_index].name.Contains("è¶³") || bones[ik.ik_bone_index].name.Contains("ã¤ã¾å…ˆ"))) + { + solver.enabled = false; + } + iksolvers[i] = solver; + } + + return iksolvers; + } + + // Sphere Colliderã®è¨­å®š + Collider EntrySphereCollider(PMDFormat.Rigidbody rigid, GameObject obj) + { + SphereCollider collider = obj.AddComponent(); + collider.radius = rigid.shape_w * scale_; + return collider; + } + + // Box Colliderã®è¨­å®š + Collider EntryBoxCollider(PMDFormat.Rigidbody rigid, GameObject obj) + { + BoxCollider collider = obj.AddComponent(); + collider.size = new Vector3( + rigid.shape_w * 2f * scale_, + rigid.shape_h * 2f * scale_, + rigid.shape_d * 2f * scale_); + return collider; + } + + // Capsule Colliderã®è¨­å®š + Collider EntryCapsuleCollider(PMDFormat.Rigidbody rigid, GameObject obj) + { + CapsuleCollider collider = obj.AddComponent(); + collider.radius = rigid.shape_w * scale_; + collider.height = (rigid.shape_h + rigid.shape_w * 2) * scale_; + return collider; + } + + // 物ç†ç´ æã®å®šç¾© + PhysicsMaterial CreatePhysicMaterial(PMDFormat.Rigidbody rigid) + { + PhysicsMaterial material = new PhysicsMaterial(format_.name + "_r" + rigid.rigidbody_name); + material.bounciness = rigid.rigidbody_recoil; + material.staticFriction = rigid.rigidbody_friction; + material.dynamicFriction = rigid.rigidbody_friction; + + AssetDatabase.CreateAsset(material, format_.folder + "/Physics/" + GetFilePathString(material.name) + ".asset"); + return material; + } + + // Unityå´ã®Rigidbodyã®è¨­å®šã‚’行ㆠ+ void UnityRigidbodySetting(PMDFormat.Rigidbody rigidbody, GameObject targetBone, bool setted=false) + { + // rigidbodyã®èª¿æ•´ + if (!setted) + { + targetBone.GetComponent().isKinematic = (0 == rigidbody.rigidbody_type); + targetBone.GetComponent().mass = Mathf.Max(float.Epsilon, rigidbody.rigidbody_weight); + targetBone.GetComponent().linearDamping = rigidbody.rigidbody_pos_dim; + targetBone.GetComponent().angularDamping = rigidbody.rigidbody_rot_dim; + } + else + { + // Rigidbodyã¯ãƒœãƒ¼ãƒ³ã«å¯¾ã—ã¦é©ç”¨ã•れるã®ã§è¤‡æ•°ã‚ã‚‹å ´åˆã¯å¹³å‡ã‚’å–ã‚‹ + targetBone.GetComponent().mass += rigidbody.rigidbody_weight; + targetBone.GetComponent().linearDamping += rigidbody.rigidbody_pos_dim; + targetBone.GetComponent().angularDamping += rigidbody.rigidbody_rot_dim; + targetBone.GetComponent().mass *= 0.5f; + targetBone.GetComponent().linearDamping *= 0.5f; + targetBone.GetComponent().angularDamping *= 0.5f; + } + } + + // 剛体ã®å€¤ã‚’代入ã™ã‚‹ + void SetRigidsSettings(GameObject[] bones, GameObject[] rigid) + { + PMDFormat.RigidbodyList list = format_.rigidbody_list; + for (int i = 0; i < list.rigidbody_count; i++) // iã¯å‰›ä½“ç•ªå· + { + // 剛体ã®é–¢é€£ãƒœãƒ¼ãƒ³ã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ + int rigidRefIndex = list.rigidbody[i].rigidbody_rel_bone_index; + + // ローカル座標ã®ç¢ºå®š + Vector3 localPos = list.rigidbody[i].pos_pos * scale_;// - rigid[i].transform.position; + + // ã“ã“ã§ä½ç½®ã®æ±ºå®š + if (rigidRefIndex >= ushort.MaxValue) + { + // 関連ボーン無㗠+ if (rigid[i].GetComponent() == null) + rigid[i].AddComponent(); + UnityRigidbodySetting(list.rigidbody[i], rigid[i]); + rigid[i].transform.localPosition = localPos; + + // 関連ボーンãªã—ã®å‰›ä½“ã¯ã‚»ãƒ³ã‚¿ãƒ¼ãƒœãƒ¼ãƒ³ã«æŽ¥ç¶šã—ã¦ã„ã‚‹ + rigid[i].transform.position = localPos + format_.bone_list.bone[0].bone_head_pos * scale_; + // 回転ã®å€¤ã‚’決ã‚ã‚‹ + Vector3 rot = list.rigidbody[i].pos_rot * Mathf.Rad2Deg; + rigid[i].transform.rotation = Quaternion.Euler(rot); + } + else + // 関連ボーン有り + { // ã¨ã‚Šã‚ãˆãšã“ã“ã§å‰›ä½“を追加・設定 + if (bones[rigidRefIndex].GetComponent() == null) + bones[rigidRefIndex].AddComponent(); + UnityRigidbodySetting(list.rigidbody[i], bones[rigidRefIndex]); + rigid[i].transform.localPosition = localPos; + // 回転ã®å€¤ã‚’決ã‚ã‚‹ + Vector3 rot = list.rigidbody[i].pos_rot * Mathf.Rad2Deg; + rigid[i].transform.rotation = Quaternion.Euler(rot); + } + + } + } + + // 剛体ã®ç”Ÿæˆ + GameObject[] CreateRigids(GameObject[] bones) + { + PMDFormat.RigidbodyList list = format_.rigidbody_list; + if (!System.IO.Directory.Exists(System.IO.Path.Combine(format_.folder, "Physics"))) + { + AssetDatabase.CreateFolder(format_.folder, "Physics"); + } + + // 剛体ã®ç™»éŒ² + GameObject[] rigid = new GameObject[list.rigidbody_count]; + for (int i = 0; i < list.rigidbody_count; i++) + { + rigid[i] = new GameObject("r_" + list.rigidbody[i].rigidbody_name); + //rigid[i].AddComponent(); // 剛体本体ã«ã¯rigidbodyã¯é©ç”¨ã—ãªã„ + + // å„種Colliderã®è¨­å®š + Collider collider = null; + switch (list.rigidbody[i].shape_type) + { + case 0: + collider = EntrySphereCollider(list.rigidbody[i], rigid[i]); + break; + + case 1: + collider = EntryBoxCollider(list.rigidbody[i], rigid[i]); + break; + + case 2: + collider = EntryCapsuleCollider(list.rigidbody[i], rigid[i]); + break; + } + + // マテリアルã®è¨­å®š + collider.material = CreatePhysicMaterial(list.rigidbody[i]); + } + return rigid; + } + + // ジョインã«ä¾ã£ã¦æŽ¥ç¶šã—ã¦ã„ã‚‹(ã•れã¦ã„ã‚‹)剛体番å·ã‚’検索ã™ã‚‹ + int SearchConnectRigidByJoint(int rigidIndex) + { + for (int i = 0; i < format_.rigidbody_joint_list.joint_count; i++) + { + int joint_rigidbody_a = (int)format_.rigidbody_joint_list.joint[i].joint_rigidbody_a; + int joint_rigidbody_b = (int)format_.rigidbody_joint_list.joint[i].joint_rigidbody_b; + if (joint_rigidbody_b == rigidIndex) + { + return joint_rigidbody_a; + } + else if (joint_rigidbody_a == rigidIndex) + { + return joint_rigidbody_b; + } + } + // 接続剛体ã¯ç™ºè¦‹å‡ºæ¥ãš + return -1; + } + + // 関連ボーンãªã—ã®å‰›ä½“ã‹ã‚‰è¦ªã®ãƒœãƒ¼ãƒ³ã‚’探ã—ã¦ãã‚‹ + // rigidIndexã¯å‰›ä½“ç•ªå· + int GetTargetRigidBone(int rigidIndex) + { + // 接続剛体Aを探㙠+ int targetRigid = SearchConnectRigidByJoint(rigidIndex); + + // 接続剛体Aã®é–¢é€£ãƒœãƒ¼ãƒ³ã‚’探㙠+ int ind = format_.rigidbody_list.rigidbody[targetRigid].rigidbody_rel_bone_index; + + // MaxValueを引ã‘ã°æŽ¥ç¶šå‰›ä½“Aã®é–¢é€£ãƒœãƒ¼ãƒ³ã«æŽ¥ç¶šã•れるよã†ã«ãªã£ã¦ã„ã‚‹ + if (ind >= ushort.MaxValue) + format_.rigidbody_list.rigidbody[rigidIndex].rigidbody_rel_bone_index = ushort.MaxValue + (ushort)ind; + + return (int)ind; + } + + // 剛体ボーンを + void AssignRigidbodyToBone(GameObject[] bones, GameObject[] rigids) + { + // å‰›ä½“ã®æ•°ã ã‘回㙠+ for (int i = 0; i < rigids.Length; i++) + { + // å‰›ä½“ã‚’è¦ªãƒœãƒ¼ãƒ³ã«æ ¼ç´ + int refIndex = format_.rigidbody_list.rigidbody[i].rigidbody_rel_bone_index; + if (refIndex != ushort.MaxValue) + { // 65535ãŒæœ€å¤§å€¤ + rigids[i].transform.parent = bones[refIndex].transform; + } + else + { + // ジョイントã‹ã‚‰æŽ¥ç¶šå‰›ä½“Bï¼ç¾åœ¨ã®å‰›ä½“åã§æŽ¢ã—出㙠+ int boneIndex = GetTargetRigidBone(i); + + // 接続剛体Aã®é–¢é€£ãƒœãƒ¼ãƒ³ã«å‰›ä½“を接続 + rigids[i].transform.parent = bones[boneIndex].transform; + } + } + } + + // ç§»å‹•ã‚„å›žè»¢åˆ¶é™ + void SetMotionAngularLock(PMDFormat.Joint joint, ConfigurableJoint conf) + { + SoftJointLimit jlim; + + // Motionã®å›ºå®š + if (joint.constrain_pos_1.x == 0f && joint.constrain_pos_2.x == 0f) + conf.xMotion = ConfigurableJointMotion.Locked; + else + conf.xMotion = ConfigurableJointMotion.Limited; + + if (joint.constrain_pos_1.y == 0f && joint.constrain_pos_2.y == 0f) + conf.yMotion = ConfigurableJointMotion.Locked; + else + conf.yMotion = ConfigurableJointMotion.Limited; + + if (joint.constrain_pos_1.z == 0f && joint.constrain_pos_2.z == 0f) + conf.zMotion = ConfigurableJointMotion.Locked; + else + conf.zMotion = ConfigurableJointMotion.Limited; + + // 角度ã®å›ºå®š + if (joint.constrain_rot_1.x == 0f && joint.constrain_rot_2.x == 0f) + conf.angularXMotion = ConfigurableJointMotion.Locked; + else + { + conf.angularXMotion = ConfigurableJointMotion.Limited; + float hlim = Mathf.Max(-joint.constrain_rot_1.x, -joint.constrain_rot_2.x); //回転方å‘ãŒé€†ãªã®ã§è² æ•° + float llim = Mathf.Min(-joint.constrain_rot_1.x, -joint.constrain_rot_2.x); + SoftJointLimit jhlim = new SoftJointLimit(); + jhlim.limit = Mathf.Clamp(hlim * Mathf.Rad2Deg, -180.0f, 180.0f); + conf.highAngularXLimit = jhlim; + + SoftJointLimit jllim = new SoftJointLimit(); + jllim.limit = Mathf.Clamp(llim * Mathf.Rad2Deg, -180.0f, 180.0f); + conf.lowAngularXLimit = jllim; + } + + if (joint.constrain_rot_1.y == 0f && joint.constrain_rot_2.y == 0f) + conf.angularYMotion = ConfigurableJointMotion.Locked; + else + { + // 値ãŒãƒžã‚¤ãƒŠã‚¹ã ã¨ã‚¨ãƒ©ãƒ¼ãŒå‡ºã‚‹ã®ã§æ³¨æ„ + conf.angularYMotion = ConfigurableJointMotion.Limited; + float lim = Mathf.Min(Mathf.Abs(joint.constrain_rot_1.y), Mathf.Abs(joint.constrain_rot_2.y));//絶対値ã®å°ã•ã„æ–¹ + jlim = new SoftJointLimit(); + jlim.limit = lim * Mathf.Clamp(Mathf.Rad2Deg, 0.0f, 180.0f); + conf.angularYLimit = jlim; + } + + if (joint.constrain_rot_1.z == 0f && joint.constrain_rot_2.z == 0f) + conf.angularZMotion = ConfigurableJointMotion.Locked; + else + { + conf.angularZMotion = ConfigurableJointMotion.Limited; + float lim = Mathf.Min(Mathf.Abs(-joint.constrain_rot_1.z), Mathf.Abs(-joint.constrain_rot_2.z));//絶対値ã®å°ã•ã„æ–¹//回転方å‘ãŒé€†ãªã®ã§è² æ•° + jlim = new SoftJointLimit(); + jlim.limit = Mathf.Clamp(lim * Mathf.Rad2Deg, 0.0f, 180.0f); + conf.angularZLimit = jlim; + } + } + + // ã°ã­ã®è¨­å®šãªã© + void SetDrive(PMDFormat.Joint joint, ConfigurableJoint conf) + { + JointDrive drive; + + // Position + if (joint.spring_pos.x != 0f) + { + drive = new JointDrive(); + drive.positionSpring = joint.spring_pos.x * scale_; + conf.xDrive = drive; + } + if (joint.spring_pos.y != 0f) + { + drive = new JointDrive(); + drive.positionSpring = joint.spring_pos.y * scale_; + conf.yDrive = drive; + } + if (joint.spring_pos.z != 0f) + { + drive = new JointDrive(); + drive.positionSpring = joint.spring_pos.z * scale_; + conf.zDrive = drive; + } + + // Angular + if (joint.spring_rot.x != 0f) + { + drive = new JointDrive(); + drive.positionSpring = joint.spring_rot.x; + conf.angularXDrive = drive; + } + if (joint.spring_rot.y != 0f || joint.spring_rot.z != 0f) + { + drive = new JointDrive(); + drive.positionSpring = (joint.spring_rot.y + joint.spring_rot.z) * 0.5f; + conf.angularYZDrive = drive; + } + } + + // ConfigurableJointã®å€¤ã‚’設定ã™ã‚‹ + void SetAttributeConfigurableJoint(PMDFormat.Joint joint, ConfigurableJoint conf) + { + SetMotionAngularLock(joint, conf); + SetDrive(joint, conf); + } + + // ConfigurableJointã®è¨­å®š + // å…ˆã«è¨­å®šã—ã¦ã‹ã‚‰FixedJointを設定ã™ã‚‹ + GameObject[] SetupConfigurableJoint(GameObject[] rigids) + { + List result_list = new List(); + foreach (PMDFormat.Joint joint in format_.rigidbody_joint_list.joint) { + //相互接続ã™ã‚‹å‰›ä½“ã®å–å¾— + Transform transform_a = rigids[joint.joint_rigidbody_a].transform; + Transform transform_b = rigids[joint.joint_rigidbody_b].transform; + Rigidbody rigidbody_a = transform_a.GetComponent(); + if (null == rigidbody_a) { + rigidbody_a = transform_a.parent.GetComponent(); + } + Rigidbody rigidbody_b = transform_b.GetComponent(); + if (null == rigidbody_b) { + rigidbody_b = transform_b.parent.GetComponent(); + } + if (rigidbody_a != rigidbody_b) { + //接続ã™ã‚‹å‰›ä½“ãŒåŒã˜å‰›ä½“を指ã•ãªã„ãªã‚‰ + //(本æ¥ãªã‚‰PMDã®è¨­å®šãŒé–“é•ã£ã¦ã„ãªã„é™ã‚ŠåŒä¸€ã‚’指ã™äº‹ã¯ç„¡ã„ãŒã€MFUã§ã¯é–¢é€£ãƒœãƒ¼ãƒ³ã‚’æŒãŸãªã„剛体ã¯ã‚»ãƒ³ã‚¿ãƒ¼ãƒœãƒ¼ãƒ³ã«çºã‚られる為ã«ä¾ã‚Šèµ·ã“り得る) + //ジョイント設定 + ConfigurableJoint config_joint = rigidbody_b.gameObject.AddComponent(); + config_joint.connectedBody = rigidbody_a; + SetAttributeConfigurableJoint(joint, config_joint); + + result_list.Add(config_joint.gameObject); + } + } + return result_list.ToArray(); + } + + // ジョイントã®è¨­å®š + // ジョイントã¯ãƒœãƒ¼ãƒ³ã«å¯¾ã—ã¦é©ç”¨ã•れる + GameObject[] SettingJointComponent(GameObject[] bones, GameObject[] rigids) + { + // ConfigurableJointã®è¨­å®š + GameObject[] joints = SetupConfigurableJoint(rigids); + return joints; + } + + // 剛体ã®ã‚°ãƒ­ãƒ¼ãƒãƒ«åº§æ¨™åŒ– + void GlobalizeRigidbody(GameObject[] joints) + { + if ((null != joints) && (0 < joints.Length)) { + // ç‰©ç†æ¼”算ルートを生æˆã—ã¦ãƒ«ãƒ¼ãƒˆã®å­ä¾›ã«ä»˜ã‘ã‚‹ + GameObject physics_root = new GameObject("Physics"); + PhysicsManager physics_manager = physics_root.AddComponent(); + physics_root.transform.parent = root_game_object_.transform; + Transform physics_root_transform = physics_root.transform; + + // PhysicsManagerã«ç§»å‹•å‰ã®çŠ¶æ…‹ã‚’è¦šãˆã•ã›ã‚‹(å¹¾ã¤ã‹é‡è¤‡ã—ã¦ã„ã‚‹ã®ã§é‡è¤‡ã¯å‰Šé™¤) + physics_manager.connect_bone_list = joints.Select(x=>x.gameObject) + .Distinct() + .Select(x=>new PhysicsManager.ConnectBone(x, x.transform.parent.gameObject)) + .ToArray(); + + //isKinematicã§ç„¡ãConfigurableJointã‚’æŒã¤å ´åˆã¯ã‚°ãƒ­ãƒ¼ãƒãƒ«åº§æ¨™åŒ– + foreach (ConfigurableJoint joint in joints.Where(x=>!x.GetComponent().isKinematic) + .Select(x=>x.GetComponent())) { + joint.transform.parent = physics_root_transform; + } + } + } + + // éžè¡çªå‰›ä½“ã®è¨­å®š + List[] SettingIgnoreRigidGroups(GameObject[] rigids) + { + // éžè¡çªã‚°ãƒ«ãƒ¼ãƒ—用リストã®åˆæœŸåŒ– + const int MaxGroup = 16; // ã‚°ãƒ«ãƒ¼ãƒ—ã®æœ€å¤§æ•° + List[] ignoreRigid = new List[MaxGroup]; + for (int i = 0; i < 16; i++) ignoreRigid[i] = new List(); + + // ãれãžã‚Œã®å‰›ä½“ãŒæ‰€å±žã—ã¦ã„ã‚‹éžè¡çªã‚°ãƒ«ãƒ¼ãƒ—を追加ã—ã¦ã„ã + PMDFormat.RigidbodyList list = format_.rigidbody_list; + for (int i = 0; i < list.rigidbody_count; i++) + ignoreRigid[list.rigidbody[i].rigidbody_group_index].Add(i); + return ignoreRigid; + } + + // グループターゲット + int[] GetRigidbodyGroupTargets(GameObject[] rigids) + { + int[] result = new int[rigids.Length]; + for (int i = 0; i < rigids.Length; i++) + { + result[i] = format_.rigidbody_list.rigidbody[i].rigidbody_group_target; + } + return result; + } + + /// + /// ファイルパス文字列ã®å–å¾— + /// + /// ファイルパスã«ä½¿ç”¨å¯èƒ½ãªæ–‡å­—列 + /// ファイルパスã«ä½¿ç”¨ã—ãŸã„文字列 + private static string GetFilePathString(string src) { + return src.Replace('\\', 'ï¼¼') + .Replace('/', 'ï¼') + .Replace(':', ':') + .Replace('*', '*') + .Replace('?', '?') + .Replace('"', 'â€') + .Replace('<', '<') + .Replace('>', '>') + .Replace('|', '|') + .Replace("\n", string.Empty) + .Replace("\r", string.Empty); + } + + static float default_outline_width = 0.2f; //標準エッジ幅 + static Color default_outline_color = Color.black; //標準エッジ色 + + GameObject root_game_object_; + PMDFormat format_; + ShaderType shader_type_; + bool use_rigidbody_; + bool use_mecanim_; + bool use_ik_; + float scale_; + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMDLoaderScript.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMDLoaderScript.cs new file mode 100644 index 000000000..407ca260e --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMDLoaderScript.cs @@ -0,0 +1,499 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text; +using MMD.PMD; + +public class PMDLoaderScript { + + /// + /// PMDファイルã®ãƒ˜ãƒƒãƒ€ãƒ¼å–å¾— + /// + /// PMDファイルã®ãƒ‘ス + /// ヘッダー + public static PMDFormat.Header GetHeader(string file_path) { + PMDLoaderScript loader = new PMDLoaderScript(); + return loader.GetHeader_(file_path); + } + + /// + /// PMDファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ + /// + /// PMDファイルã®ãƒ‘ス + /// 内部形å¼ãƒ‡ãƒ¼ã‚¿ + public static PMDFormat Import(string file_path) { + PMDLoaderScript loader = new PMDLoaderScript(); + return loader.Import_(file_path); + } + + /// + /// デフォルトコンストラクタ + /// + /// + /// ユーザーã«ä¾ã‚‹ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ä½œæˆã‚’ç¦æ­¢ã™ã‚‹ + /// + private PMDLoaderScript() {} + + private PMDFormat.Header GetHeader_(string file_path) { + PMDFormat.Header result; + using (FileStream stream = new FileStream(file_path, FileMode.Open, FileAccess.Read)) + using (BinaryReader bin = new BinaryReader(stream)) { + file_path_ = null; + binary_reader_ = bin; + result = ReadHeader(); + } + return result; + } + + private PMDFormat Import_(string file_path) { + using (FileStream stream = new FileStream(file_path, FileMode.Open, FileAccess.Read)) + using (BinaryReader bin = new BinaryReader(stream)) { + file_path_ = file_path; + binary_reader_ = bin; + Read(); + } + return format_; + } + + private PMDFormat Read() { + format_ = new PMDFormat(); + EntryPathes(); + + try { + format_.head = ReadHeader(); + format_.vertex_list = ReadVertexList(); + format_.face_vertex_list = ReadFaceVertexList(); + format_.material_list = ReadMaterialList(); + format_.bone_list = ReadBoneList(); + format_.ik_list = ReadIKList(); + format_.skin_list = ReadSkinList(); + format_.skin_name_list = ReadSkinNameList(); + format_.bone_name_list = ReadBoneNameList(); + format_.bone_display_list = ReadBoneDisplayList(); + format_.eg_head = ReadEnglishHeader(); + if (format_.eg_head.english_name_compatibility != 0) { + format_.eg_bone_name_list = ReadEnglishBoneNameList(format_.bone_list.bone_count); + format_.eg_skin_name_list = ReadEnglishSkinNameList(format_.skin_list.skin_count); + format_.eg_bone_display_list = ReadEnglishBoneDisplayList(format_.bone_name_list.bone_disp_name_count); + } + format_.toon_texture_list = ReadToonTextureList(); + format_.rigidbody_list = ReadRigidbodyList(); + format_.rigidbody_joint_list = ReadRigidbodyJointList(); + } catch { + Debug.Log("Don't read full format"); + } + return format_; + } + + private void EntryPathes() { + format_.path = file_path_; + format_.name = Path.GetFileNameWithoutExtension(file_path_); // .pmdを抜ã‹ã™ + format_.folder = Path.GetDirectoryName(file_path_); // PMDãŒæ ¼ç´ã•れã¦ã„るフォルダ + } + + private PMDFormat.Header ReadHeader() { + PMDFormat.Header result = new PMDFormat.Header(); + result.magic = binary_reader_.ReadBytes(3); + result.version = binary_reader_.ReadSingle(); + result.model_name = ConvertByteToString(binary_reader_.ReadBytes(20), ""); + result.comment = ConvertByteToString(binary_reader_.ReadBytes(256), System.Environment.NewLine); + return result; + } + + private PMDFormat.VertexList ReadVertexList() { + PMDFormat.VertexList result = new PMDFormat.VertexList(); + result.vert_count = binary_reader_.ReadUInt32(); + result.vertex = new PMDFormat.Vertex[result.vert_count]; + for (int i = 0; i < result.vert_count; i++) { + result.vertex[i] = ReadVertex(); + } + return result; + } + + private PMDFormat.Vertex ReadVertex() { + PMDFormat.Vertex result = new PMDFormat.Vertex(); + result.pos = ReadSinglesToVector3(binary_reader_); + result.normal_vec = ReadSinglesToVector3(binary_reader_); + result.uv = ReadSinglesToVector2(binary_reader_); + result.bone_num = ReadUInt16s(binary_reader_, 2); + result.bone_weight = binary_reader_.ReadByte(); + result.edge_flag = binary_reader_.ReadByte(); + return result; + } + + private PMDFormat.FaceVertexList ReadFaceVertexList() { + PMDFormat.FaceVertexList result = new PMDFormat.FaceVertexList(); + result.face_vert_count = binary_reader_.ReadUInt32(); + result.face_vert_index = ReadUInt16s(binary_reader_, result.face_vert_count); + return result; + } + + private PMDFormat.MaterialList ReadMaterialList() { + PMDFormat.MaterialList result = new PMDFormat.MaterialList(); + result.material_count = binary_reader_.ReadUInt32(); + result.material = new PMDFormat.Material[result.material_count]; + for (int i = 0; i < result.material_count; i++) { + result.material[i] = ReadMaterial(); + } + return result; + } + + private PMDFormat.Material ReadMaterial() { + PMDFormat.Material result = new PMDFormat.Material(); + result.diffuse_color = ReadSinglesToColor(binary_reader_, 1); + result.alpha = binary_reader_.ReadSingle(); + result.specularity = binary_reader_.ReadSingle(); + result.specular_color = ReadSinglesToColor(binary_reader_, 1); + result.mirror_color = ReadSinglesToColor(binary_reader_, 1); + result.toon_index = binary_reader_.ReadByte(); + result.edge_flag = binary_reader_.ReadByte(); + result.face_vert_count = binary_reader_.ReadUInt32(); + + // テクスãƒãƒ£åã®æŠœã出㗠+ // スフィアマップも行ㆠ+ string buf = ConvertByteToString(binary_reader_.ReadBytes(20), ""); + + //Debug by Wilfrem: テクスãƒãƒ£ãŒç„¡ã„å ´åˆã‚’考慮ã—ã¦ã„ãªã„ + //Debug by Wilfrem: テクスãƒãƒ£ã¯foo.bmp*bar.sphã®ãƒ‘ターンã ã‘ãªã®ã‹ï¼Ÿ bar.sph*foo.bmpã®ãƒ‘ターンãŒã‚り得るã®ã§ã¯ï¼Ÿ 対策をã—ã¦ãŠãã¹ã + //Debug by GRGSIBERIA: スフィアマップã¨ãƒ†ã‚¯ã‚¹ãƒãƒ£ãŒé€†ã«ãªã‚‹ç¾è±¡ãŒç™ºç”Ÿã—ãŸã®ã§ä¿®æ­£ + //Debug by GRGSIBERIA: "./テクスãƒãƒ£å"ã§å§‹ã¾ã‚‹ãƒ¢ãƒ‡ãƒ«ã§ç•°å¸¸ç™ºç”Ÿã—ãŸã®ã§ä¿®æ­£ + if (!string.IsNullOrEmpty(buf.Trim())) { + string[] textures = buf.Trim().Split('*'); + foreach (var tex in textures) { + string texNameEndAssignVar = ""; + string ext = Path.GetExtension(tex); + if (ext == ".sph" || ext == ".spa") { + result.sphere_map_name = tex; + /*} else if (string.IsNullOrEmpty(tex)) { + result.texture_file_name=""; */ + } else { + if (tex.Split('/')[0] == ".") { + // テクスãƒãƒ£åã®å¾Œç«¯ã«"./"ãŒã‚ã£ãŸå ´åˆã®å›žé¿å‡¦ç† + string[] texNameBuf = tex.Split('/'); + for (int i = 1; i < texNameBuf.Length-1; i++) { + texNameEndAssignVar += texNameBuf[i] + "/"; + } + texNameEndAssignVar += texNameBuf[texNameBuf.Length-1]; + } else { + // 特ã«ç•°å¸¸ãŒãªã„å ´åˆã¯ãã®ã¾ã¾ä»£å…¥ + texNameEndAssignVar = tex; + } +#if UNITY_STANDALONE_OSX + // MACã®å ´åˆï¼Œæ¿ç‚¹ã®ã‚ã‚‹ã²ã‚‰ãŒãªã‚’使ã†ã¨å‹•ã‹ãªã„らã—ã„ã®ã§å¯¾ç­– + // http://sourceforge.jp/ticket/browse.php?group_id=6158&tid=31929 + texNameEndAssignVar = texNameEndAssignVar.Normalize(NormalizationForm.FormKD); +#endif + result.texture_file_name = texNameEndAssignVar; + } + } + } else { + result.sphere_map_name=""; + result.texture_file_name=""; + } + if (string.IsNullOrEmpty(result.texture_file_name)) { + result.texture_file_name = ""; + } + return result; + } + + private PMDFormat.BoneList ReadBoneList() { + PMDFormat.BoneList result = new PMDFormat.BoneList(); + result.bone_count = binary_reader_.ReadUInt16(); + //Debug.Log("BoneCount:"+bone_count); + result.bone = new PMDFormat.Bone[result.bone_count]; + for (int i = 0; i < result.bone_count; i++) { + result.bone[i] = ReadBone(); + } + return result; + } + + private PMDFormat.Bone ReadBone() { + PMDFormat.Bone result = new PMDFormat.Bone(); + result.bone_name = ConvertByteToString(binary_reader_.ReadBytes(20), ""); + result.parent_bone_index = binary_reader_.ReadUInt16(); + result.tail_pos_bone_index = binary_reader_.ReadUInt16(); + result.bone_type = binary_reader_.ReadByte(); + result.ik_parent_bone_index = binary_reader_.ReadUInt16(); + result.bone_head_pos = ReadSinglesToVector3(binary_reader_); + return result; + } + + private PMDFormat.IKList ReadIKList() { + PMDFormat.IKList result = new PMDFormat.IKList(); + result.ik_data_count = binary_reader_.ReadUInt16(); + //Debug.Log("IKDataCount:"+ik_data_count); + result.ik_data = new PMDFormat.IK[result.ik_data_count]; + for (int i = 0; i < result.ik_data_count; i++) { + result.ik_data[i] = ReadIK(); + } + return result; + } + + private PMDFormat.IK ReadIK() { + PMDFormat.IK result = new PMDFormat.IK(); + result.ik_bone_index = binary_reader_.ReadUInt16(); + result.ik_target_bone_index = binary_reader_.ReadUInt16(); + result.ik_chain_length = binary_reader_.ReadByte(); + result.iterations = binary_reader_.ReadUInt16(); + result.control_weight = binary_reader_.ReadSingle(); + result.ik_child_bone_index = ReadUInt16s(binary_reader_, result.ik_chain_length); + return result; + } + + private PMDFormat.SkinList ReadSkinList() { + PMDFormat.SkinList result = new PMDFormat.SkinList(); + result.skin_count = binary_reader_.ReadUInt16(); + //Debug.Log("SkinCount:"+skin_count); + result.skin_data = new PMDFormat.SkinData[result.skin_count]; + for (int i = 0; i < result.skin_count; i++) { + result.skin_data[i] = ReadSkinData(); + } + return result; + } + + private PMDFormat.SkinData ReadSkinData() { + PMDFormat.SkinData result = new PMDFormat.SkinData(); + result.skin_name = ConvertByteToString(binary_reader_.ReadBytes(20), ""); + result.skin_vert_count = binary_reader_.ReadUInt32(); + result.skin_type = binary_reader_.ReadByte(); + result.skin_vert_data = new PMDFormat.SkinVertexData[result.skin_vert_count]; + for (int i = 0; i < result.skin_vert_count; i++) { + result.skin_vert_data[i] = ReadSkinVertexData(); + } + return result; + } + + private PMDFormat.SkinVertexData ReadSkinVertexData() { + PMDFormat.SkinVertexData result = new PMDFormat.SkinVertexData(); + result.skin_vert_index = binary_reader_.ReadUInt32(); + result.skin_vert_pos = ReadSinglesToVector3(binary_reader_); + return result; + } + + + private PMDFormat.SkinNameList ReadSkinNameList() { + PMDFormat.SkinNameList result = new PMDFormat.SkinNameList(); + result.skin_disp_count = binary_reader_.ReadByte(); + result.skin_index = ReadUInt16s(binary_reader_, result.skin_disp_count); + return result; + } + + private PMDFormat.BoneNameList ReadBoneNameList() { + PMDFormat.BoneNameList result = new PMDFormat.BoneNameList(); + result.bone_disp_name_count = binary_reader_.ReadByte(); + result.disp_name = new string[result.bone_disp_name_count]; + for (int i = 0; i < result.bone_disp_name_count; i++) { + result.disp_name[i] = ConvertByteToString(binary_reader_.ReadBytes(50), ""); + } + return result; + } + + private PMDFormat.BoneDisplayList ReadBoneDisplayList() { + PMDFormat.BoneDisplayList result = new PMDFormat.BoneDisplayList(); + result.bone_disp_count = binary_reader_.ReadUInt32(); + result.bone_disp = new PMDFormat.BoneDisplay[result.bone_disp_count]; + for (int i = 0; i < result.bone_disp_count; i++) { + result.bone_disp[i] = ReadBoneDisplay(); + } + return result; + } + + private PMDFormat.BoneDisplay ReadBoneDisplay() { + PMDFormat.BoneDisplay result = new PMDFormat.BoneDisplay(); + result.bone_index = binary_reader_.ReadUInt16(); + result.bone_disp_frame_index = binary_reader_.ReadByte(); + return result; + } + + private PMDFormat.EnglishHeader ReadEnglishHeader() { + PMDFormat.EnglishHeader result = new PMDFormat.EnglishHeader(); + result.english_name_compatibility = binary_reader_.ReadByte(); + + if (result.english_name_compatibility != 0) { + // 英語å対応ã‚り + result.model_name_eg = ConvertByteToString(binary_reader_.ReadBytes(20), ""); + result.comment_eg = ConvertByteToString(binary_reader_.ReadBytes(256), System.Environment.NewLine); + } + return result; + } + + private PMDFormat.EnglishBoneNameList ReadEnglishBoneNameList(int boneCount) { + PMDFormat.EnglishBoneNameList result = new PMDFormat.EnglishBoneNameList(); + result.bone_name_eg = new string[boneCount]; + for (int i = 0; i < boneCount; i++) { + result.bone_name_eg[i] = ConvertByteToString(binary_reader_.ReadBytes(20), ""); + } + return result; + } + + private PMDFormat.EnglishSkinNameList ReadEnglishSkinNameList(int skinCount) { + PMDFormat.EnglishSkinNameList result = new PMDFormat.EnglishSkinNameList(); + result.skin_name_eg = new string[skinCount]; + for (int i = 0; i < skinCount - 1; i++) { + result.skin_name_eg[i] = ConvertByteToString(binary_reader_.ReadBytes(20), ""); + } + return result; + } + + private PMDFormat.EnglishBoneDisplayList ReadEnglishBoneDisplayList(int boneDispNameCount) { + PMDFormat.EnglishBoneDisplayList result = new PMDFormat.EnglishBoneDisplayList(); + result.disp_name_eg = new string[boneDispNameCount]; + for (int i = 0; i < boneDispNameCount; i++) { + result.disp_name_eg[i] = ConvertByteToString(binary_reader_.ReadBytes(50), ""); + } + return result; + } + + private PMDFormat.ToonTextureList ReadToonTextureList() { + PMDFormat.ToonTextureList result = new PMDFormat.ToonTextureList(); + result.toon_texture_file = new string[10]; + for (int i = 0; i < result.toon_texture_file.Length; i++) { + result.toon_texture_file[i] = ConvertByteToString(binary_reader_.ReadBytes(100), ""); + } + return result; + } + + private PMDFormat.RigidbodyList ReadRigidbodyList() { + PMDFormat.RigidbodyList result = new PMDFormat.RigidbodyList(); + result.rigidbody_count = binary_reader_.ReadUInt32(); + result.rigidbody = new PMDFormat.Rigidbody[result.rigidbody_count]; + for (int i = 0; i < result.rigidbody_count; i++) { + result.rigidbody[i] = ReadRigidbody(); + } + return result; + } + + private PMDFormat.Rigidbody ReadRigidbody() { + PMDFormat.Rigidbody result = new PMDFormat.Rigidbody(); + result.rigidbody_name = ConvertByteToString(binary_reader_.ReadBytes(20), ""); + result.rigidbody_rel_bone_index = binary_reader_.ReadUInt16(); + result.rigidbody_group_index = binary_reader_.ReadByte(); + result.rigidbody_group_target = binary_reader_.ReadUInt16(); + result.shape_type = binary_reader_.ReadByte(); + result.shape_w = binary_reader_.ReadSingle(); + result.shape_h = binary_reader_.ReadSingle(); + result.shape_d = binary_reader_.ReadSingle(); + result.pos_pos = ReadSinglesToVector3(binary_reader_); + result.pos_rot = ReadSinglesToVector3(binary_reader_); + result.rigidbody_weight = binary_reader_.ReadSingle(); + result.rigidbody_pos_dim = binary_reader_.ReadSingle(); + result.rigidbody_rot_dim = binary_reader_.ReadSingle(); + result.rigidbody_recoil = binary_reader_.ReadSingle(); + result.rigidbody_friction = binary_reader_.ReadSingle(); + result.rigidbody_type = binary_reader_.ReadByte(); + return result; + } + + private PMDFormat.RigidbodyJointList ReadRigidbodyJointList() { + PMDFormat.RigidbodyJointList result = new PMDFormat.RigidbodyJointList(); + result.joint_count = binary_reader_.ReadUInt32(); + result.joint = new PMDFormat.Joint[result.joint_count]; + for (int i = 0; i < result.joint_count; i++) { + result.joint[i] = ReadJoint(); + } + return result; + } + + private PMDFormat.Joint ReadJoint() { + PMDFormat.Joint result = new PMDFormat.Joint(); + result.joint_name = ConvertByteToString(binary_reader_.ReadBytes(20), ""); + result.joint_rigidbody_a = binary_reader_.ReadUInt32(); + result.joint_rigidbody_b = binary_reader_.ReadUInt32(); + result.joint_pos = ReadSinglesToVector3(binary_reader_); + result.joint_rot = ReadSinglesToVector3(binary_reader_); + result.constrain_pos_1 = ReadSinglesToVector3(binary_reader_); + result.constrain_pos_2 = ReadSinglesToVector3(binary_reader_); + result.constrain_rot_1 = ReadSinglesToVector3(binary_reader_); + result.constrain_rot_2 = ReadSinglesToVector3(binary_reader_); + result.spring_pos = ReadSinglesToVector3(binary_reader_); + result.spring_rot = ReadSinglesToVector3(binary_reader_); + return result; + } + + // ShiftJISã‹ã‚‰UTF-8ã«å¤‰æ›ã—ã¦stringã§è¿”ã™ + private static string ConvertByteToString(byte[] bytes, string line_feed_code = null) + { + // ãƒ‘ãƒ‡ã‚£ãƒ³ã‚°ã®æ¶ˆåŽ», 文字を詰ã‚ã‚‹ + if (bytes[0] == 0) return ""; + int count; + for (count = 0; count < bytes.Length; count++) if (bytes[count] == 0) break; + byte[] buf = new byte[count]; // NULL文字をå«ã‚ã‚‹ã¨ã†ã¾ã行ã‹ãªã„ + for (int i = 0; i < count; i++) { + buf[i] = bytes[i]; + } + +#if UNITY_STANDALONE_OSX + buf = Encoding.Convert(Encoding.GetEncoding(932), Encoding.UTF8, buf); +#else + buf = Encoding.Convert(Encoding.GetEncoding(0), Encoding.UTF8, buf); +#endif + string result = Encoding.UTF8.GetString(buf); + if (null != line_feed_code) { + //改行コード統一(ã‚‚ã—ãã¯é™¤åŽ») + result = result.Replace("\r\n", "\n").Replace('\r', '\n').Replace("\n", line_feed_code); + } + return result; + } + + private static Vector3 ReadSinglesToVector3(BinaryReader bin) + { + const int count = 3; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = bin.ReadSingle(); + if (float.IsNaN(result[i])) result[i] = 0.0f; //éžæ•°å€¤ãªã‚‰å›žé¿ + } + return new Vector3(result[0], result[1], result[2]); + } + + private static Vector2 ReadSinglesToVector2(BinaryReader bin) + { + const int count = 2; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = bin.ReadSingle(); + if (float.IsNaN(result[i])) result[i] = 0.0f; //éžæ•°å€¤ãªã‚‰å›žé¿ + } + return new Vector2(result[0], result[1]); + } + + private static Color ReadSinglesToColor(BinaryReader bin) + { + const int count = 4; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = bin.ReadSingle(); + } + return new Color(result[0], result[1], result[2], result[3]); + } + + private static Color ReadSinglesToColor(BinaryReader bin, float fix_alpha) + { + const int count = 3; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = bin.ReadSingle(); + } + return new Color(result[0], result[1], result[2], fix_alpha); + } + + private static ushort[] ReadUInt16s(BinaryReader bin, uint count) + { + ushort[] result = new ushort[count]; + for (uint i = 0; i < count; i++) + { + result[i] = bin.ReadUInt16(); + } + return result; + } + + string file_path_; + BinaryReader binary_reader_; + PMDFormat format_; +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXConverter.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXConverter.cs new file mode 100644 index 000000000..69928c9d3 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXConverter.cs @@ -0,0 +1,2033 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Linq; +using MMD.PMX; + +namespace MMD +{ + public class PMXConverter : System.IDisposable + { + /// + /// アニメーションタイプ + /// + public enum AnimationType { + GenericMecanim, //汎用アãƒã‚¿ãƒ¼ã§ã®Mecanim + HumanMecanim, //人型アãƒã‚¿ãƒ¼ã§ã®Mecanim + LegacyAnimation, //æ—§å¼ã‚¢ãƒ‹ãƒ¡ãƒ¼ã‚·ãƒ§ãƒ³ + } + + /// + /// GameObjectを作æˆã™ã‚‹ + /// + /// 内部形å¼ãƒ‡ãƒ¼ã‚¿ + /// 剛体を使用ã™ã‚‹ã‹ + /// アニメーションタイプ + /// IKを使用ã™ã‚‹ã‹ + /// スケール + public static GameObject CreateGameObject(PMXFormat format, bool use_rigidbody, AnimationType animation_type, bool use_ik, float scale) { + GameObject result; + using (PMXConverter converter = new PMXConverter()) { + result = converter.CreateGameObject_(format, use_rigidbody, animation_type, use_ik, scale); + } + return result; + } + + /// + /// デフォルトコンストラクタ + /// + /// + /// ユーザーã«ä¾ã‚‹ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ä½œæˆã‚’ç¦æ­¢ã™ã‚‹ + /// + private PMXConverter() {} + + /// + /// Disposeインターフェース + /// + public void Dispose() + { + if (null != alpha_readable_texture_) { + alpha_readable_texture_.Dispose(); + } + } + + /// + /// GameObjectを作æˆã™ã‚‹ + /// + /// 内部形å¼ãƒ‡ãƒ¼ã‚¿ + /// 剛体を使用ã™ã‚‹ã‹ + /// アニメーションタイプ + /// IKを使用ã™ã‚‹ã‹ + /// スケール + private GameObject CreateGameObject_(PMXFormat format, bool use_rigidbody, AnimationType animation_type, bool use_ik, float scale) { + format_ = format; + use_ik_ = use_ik; + scale_ = scale; + root_game_object_ = new GameObject(format_.meta_header.name); + MMDEngine engine = root_game_object_.AddComponent(); //MMDEngine追加 + //スケール・エッジ幅 + engine.scale = scale_; + engine.outline_width = 1.0f; + engine.material_outline_widths = format.material_list.material.Select(x=>x.edge_size).ToArray(); + engine.enable_render_queue = false; //åˆæœŸå€¤ç„¡åй + const int c_render_queue_transparent = 3000; + engine.render_queue_value = c_render_queue_transparent; + + MeshCreationInfo[] creation_info = CreateMeshCreationInfo(); // メッシュを作æˆã™ã‚‹ç‚ºã®æƒ…å ±ã‚’ä½œæˆ + Mesh[] mesh = CreateMesh(creation_info); // メッシュã®ç”Ÿæˆãƒ»è¨­å®š + Material[][] materials = CreateMaterials(creation_info); // マテリアルã®ç”Ÿæˆãƒ»è¨­å®š + GameObject[] bones = CreateBones(); // ボーンã®ç”Ÿæˆãƒ»è¨­å®š + SkinnedMeshRenderer[] renderers = BuildingBindpose(mesh, materials, bones); // ãƒã‚¤ãƒ³ãƒ‰ãƒãƒ¼ã‚ºã®ä½œæˆ + CreateMorph(mesh, materials, bones, renderers, creation_info); // モーフã®ç”Ÿæˆãƒ»è¨­å®š + + + // BoneController・IKã®ç™»éŒ²(use_ik_を使ã£ãŸåˆ¤å®šã¯EntryBoneController()ã®ä¸­ã§è¡Œã†) + { + engine.bone_controllers = EntryBoneController(bones); + engine.ik_list = engine.bone_controllers.Where(x=>null != x.ik_solver) + .Select(x=>x.ik_solver) + .ToArray(); + } + + // 剛体関連 + if (use_rigidbody) { + GameObject[] rigids = CreateRigids(); + AssignRigidbodyToBone(bones, rigids); + SetRigidsSettings(bones, rigids); + GameObject[] joints = CreateJoints(rigids); + GlobalizeRigidbody(joints); + + // éžè¡çªã‚°ãƒ«ãƒ¼ãƒ— + List[] ignoreGroups = SettingIgnoreRigidGroups(rigids); + int[] groupTarget = GetRigidbodyGroupTargets(rigids); + + MMDEngine.Initialize(engine, groupTarget, ignoreGroups, rigids); + } + + // Mecanim設定 + if (AnimationType.LegacyAnimation != animation_type) { + //アニメーター追加 + AvatarSettingScript avatar_setting = new AvatarSettingScript(root_game_object_, bones); + switch (animation_type) { + case AnimationType.GenericMecanim: //汎用アãƒã‚¿ãƒ¼ã§ã®Mecanim + avatar_setting.SettingGenericAvatar(); + break; + case AnimationType.HumanMecanim: //人型アãƒã‚¿ãƒ¼ã§ã®Mecanim + avatar_setting.SettingHumanAvatar(); + break; + default: + throw new System.ArgumentException(); + } + + string path = format_.meta_header.folder + "/"; + string name = GetFilePathString(format_.meta_header.name); + string file_name = path + name + ".avatar.asset"; + avatar_setting.CreateAsset(file_name); + } else { + root_game_object_.AddComponent(); // アニメーション追加 + } + + return root_game_object_; + } + + /// + /// メッシュを作æˆã™ã‚‹æ™‚ã«å‚ç…§ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ã®çºã‚ + /// + class MeshCreationInfo { + public class Pack { + public uint material_index; //マテリアル + public uint[] plane_indices; //é¢ + public uint[] vertices; //頂点 + } + public Pack[] value; + public uint[] all_vertices; //ç·é ‚点 + public Dictionary reassign_dictionary; //頂点リアサインインデックス用辞書 + } + + /// + /// メッシュを作æˆã™ã‚‹ç‚ºã®æƒ…å ±ã‚’ä½œæˆ + /// + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ± + MeshCreationInfo[] CreateMeshCreationInfo() + { + // 1メッシュã§åŽã¾ã‚‹å ´åˆã§ã‚‚-Multi()を使ã£ã¦ã‚‚å•題ã¯èµ·ãç„¡ã„ãŒã€ + // -Multi()ã§ã¯é ‚点数計測をマテリアルå˜ä½ã§è¡Œã†é–¢ä¿‚上ã€é ‚点数ãŒå¤šã見ç©ã‚‚られる(概算値)。 + // (1頂点を複数ã®ãƒžãƒ†ãƒªã‚¢ãƒ«ãŒå‚ç…§ã—ã¦ã„ã‚‹å ´åˆã«å‚ç…§ã—ã¦ã„る分ã ã‘計上ã—ã¦ã—ã¾ã†ã€‚) + // ä¾ã£ã¦ä¸Šé™ä»˜è¿‘ã§ã¯æœ¬æ¥1メッシュã§åŽã¾ã‚‹ç‰©ãŒè¤‡æ•°ãƒ¡ãƒƒã‚·ãƒ¥ã«åˆ†å‰²ã•れã¦ã—ã¾ã†äº‹ãŒæœ‰ã‚‹ã®ã§æ³¨æ„。 + // + // -Multi()を使ã£ã¦ã‚‚最終的ã«ã¯é ‚点数を最é©åŒ–ã™ã‚‹ã®ã§ã€ + // 1メッシュã«åŽã¾ã£ã¦ã—ã¾ãˆã°-Single()ã¨åŒã˜é ‚点数ã«ç‚ºã‚‹(確定値)。 + // + // å˜ç´”ã«-Single()ã®æ–¹ãŒè§£æžãŒå°‘ãªã„分早ã„。 + + MeshCreationInfo[] result; + if (format_.vertex_list.vertex.Length < c_max_vertex_count_in_mesh) { + //1メッシュã§åŽã¾ã‚‹ãªã‚‰ + result = CreateMeshCreationInfoSingle(); + } else { + //1メッシュã§åŽã¾ã‚‰ãšã€è¤‡æ•°ãƒ¡ãƒƒã‚·ãƒ¥ã«åˆ†å‰²ã™ã‚‹ãªã‚‰ + result = CreateMeshCreationInfoMulti(); + } + return result; + } + + /// + /// メッシュを作æˆã™ã‚‹ç‚ºã®æƒ…報を作æˆ(å˜ä½“メッシュ版) + /// + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ± + MeshCreationInfo[] CreateMeshCreationInfoSingle() + { + MeshCreationInfo[] result = new[]{new MeshCreationInfo()}; + //全マテリアルを設定 + result[0].value = CreateMeshCreationInfoPacks(); + //全頂点を設定 + result[0].all_vertices = Enumerable.Range(0, format_.vertex_list.vertex.Length).Select(x=>(uint)x).ToArray(); + //é ‚ç‚¹ãƒªã‚¢ã‚µã‚¤ãƒ³ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ç”¨è¾žæ›¸ä½œæˆ + result[0].reassign_dictionary = new Dictionary(result[0].all_vertices.Length); + for (uint i = 0, i_max = (uint)result[0].all_vertices.Length; i < i_max; ++i) { + result[0].reassign_dictionary[i] = i; + } + return result; + } + + /// + /// å…¨ãƒžãƒ†ãƒªã‚¢ãƒ«ã‚’ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ±ã®ãƒžãƒ†ãƒªã‚¢ãƒ«ãƒ‘ックã¨ã—ã¦è¿”ã™ + /// + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ±ã®ãƒžãƒ†ãƒªã‚¢ãƒ«ãƒ‘ック + MeshCreationInfo.Pack[] CreateMeshCreationInfoPacks() + { + uint plane_start = 0; + //マテリアルå˜ä½ã®MeshCreationInfo.Packを作æˆã™ã‚‹ + return Enumerable.Range(0, format_.material_list.material.Length) + .Select(x=>{ + MeshCreationInfo.Pack pack = new MeshCreationInfo.Pack(); + pack.material_index = (uint)x; + uint plane_count = format_.material_list.material[x].face_vert_count; + pack.plane_indices = format_.face_vertex_list.face_vert_index.Skip((int)plane_start) + .Take((int)plane_count) + .ToArray(); + pack.vertices = pack.plane_indices.Distinct() //é‡è¤‡å‰Šé™¤ + .ToArray(); + plane_start += plane_count; + return pack; + }) + .ToArray(); + } + + /// + /// メッシュを作æˆã™ã‚‹ç‚ºã®æƒ…報を作æˆ(複数メッシュ版) + /// + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ± + MeshCreationInfo[] CreateMeshCreationInfoMulti() + { + //マテリアルå˜ä½ã®MeshCreationInfo.Packを作æˆã™ã‚‹ + MeshCreationInfo.Pack[] packs = CreateMeshCreationInfoPacks(); + //マテリアル細分化 + packs = SplitSubMesh(packs); + //頂点数ã®å¤šã„é †ã«ä¸¦ã¹ã‚‹(メッシュ分割アルゴリズム上ã€å¾ŒåŠã«è¡Œã程頂点数ãŒå°‘ãªã„æ–¹ãŒæ•·ãè©°ã‚効率ãŒè‰¯ã„) + System.Array.Sort(packs, (x,y)=>y.vertices.Length - x.vertices.Length); + + List result = new List(); + do { + uint vertex_sum = 0; + MeshCreationInfo info = new MeshCreationInfo(); + //ãƒžãƒ†ãƒªã‚¢ãƒ«ãƒ‘ãƒƒã‚¯ä½œæˆ + info.value = Enumerable.Range(0, packs.Length) + .Where(x=>null!=packs[x]) //有効ãªãƒžãƒ†ãƒªã‚¢ãƒ«ã«çµžã‚‹ + .Where(x=>{ //採用ã—ã¦ã‚‚頂点数ãŒé™ç•Œã‚’è¶…ãˆãªã„ãªã‚‰ + vertex_sum += (uint)packs[x].vertices.Length; + return vertex_sum < c_max_vertex_count_in_mesh; + }) + .Select(x=>{ //ãƒžãƒ†ãƒªã‚¢ãƒ«ã®æŽ¡ç”¨ã¨ç„¡åŠ¹åŒ– + var pack = packs[x]; + packs[x] = null; + return pack; + }) + .ToArray(); + //マテリアルインデックスã«ä¸¦ã¹ã‚‹(メッシュã®é¸å®šãŒçµ‚ã‚ã£ãŸã®ã§è¦‹æ˜“ã„æ§˜ã«ä¸¦ã³ã‚’戻ã™) + System.Array.Sort(info.value, (x,y)=>((x.material_index>y.material_index)? 1: (x.material_indexx.vertices).Distinct().ToArray(); + System.Array.Sort(info.all_vertices); + //é ‚ç‚¹ãƒªã‚¢ã‚µã‚¤ãƒ³ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ç”¨è¾žæ›¸ä½œæˆ + info.reassign_dictionary = new Dictionary(); + uint reassign_index = 0; + foreach (var i in info.all_vertices) { + info.reassign_dictionary[i] = reassign_index++; + } + //戻り値ã«è¿½åŠ  + result.Add(info); + } while (packs.Any(x=>null!=x)); //使用ã—ã¦ã„ãªã„マテリアルãŒç‚ºã‚‹ãªã‚‰ãƒ«ãƒ¼ãƒ— + return result.ToArray(); + } + + /// + /// 1マテリアルã®é ‚点数ãŒ1メッシュã§è¡¨ç¾å‡ºæ¥ãªã„å ´åˆã«åˆ†å‰²ã™ã‚‹ + /// + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ±ã®ãƒžãƒ†ãƒªã‚¢ãƒ«ãƒ‘ック + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ±ã®ãƒžãƒ†ãƒªã‚¢ãƒ«ãƒ‘ック + MeshCreationInfo.Pack[] SplitSubMesh(MeshCreationInfo.Pack[] packs) + { + MeshCreationInfo.Pack[] result = packs; + if (packs.Any(x=>c_max_vertex_count_in_mesh<=x.vertices.Length)) { + //1メッシュã«åŽã¾ã‚‰ãªã„ãƒžãƒ†ãƒªã‚¢ãƒ«ãŒæœ‰ã‚‹ãªã‚‰ + List result_list = new List(); + foreach (var pack in packs) { + if (c_max_vertex_count_in_mesh <= pack.vertices.Length) { + //1メッシュã«åŽã¾ã‚‰ãªã„ãªã‚‰ + //分離 + var split_pack = SplitSubMesh(pack); + foreach (var i in split_pack) { + result_list.Add(i); + } + } else { + //1メッシュã«åŽã¾ã‚‹ãªã‚‰ + //素通㗠+ result_list.Add(pack); + } + } + result = result_list.ToArray(); + } + return result; + } + + /// + /// 1マテリアルã®é ‚点数ãŒ1メッシュã§è¡¨ç¾å‡ºæ¥ãªã„ã®ã§åˆ†å‰²ã™ã‚‹ + /// + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ±ã®ãƒžãƒ†ãƒªã‚¢ãƒ«ãƒ‘ック + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ±ã®ãƒžãƒ†ãƒªã‚¢ãƒ«ãƒ‘ック + List SplitSubMesh(MeshCreationInfo.Pack pack) + { + List result = new List(); + //1メッシュã«åŽã¾ã‚‰ãªã„ãªã‚‰ + uint plane_end = (uint)pack.plane_indices.Length; + uint plane_start = 0; + while (plane_start < plane_end) { + //ã¾ã é¢ãŒæœ‰ã‚‹ãªã‚‰ + uint plane_count = 0; + uint vertex_count = 0; + while (true) { + //ç¾åœ¨ã®é ‚点数ã‹ã‚‰è€ƒãˆã‚‹ã¨ã€ä½™è£•分ã®1/3è¿„ã®æ•°ã®é¢ã¯å®‰å®šã—ã¦å…¥ã‚‹ + //ã¯ã¿å‡ºã¦æ¬²ã—ã„ã‹ã‚‰æ›´ã«1é¢(3頂点)を足㙠+ plane_count += (c_max_vertex_count_in_mesh - vertex_count) / 3 * 3 + 3; + vertex_count = (uint)pack.plane_indices.Skip((int)plane_start) //é¢é ‚点インデックスå–り出ã—(先頭) + .Take((int)plane_count) //é¢é ‚点インデックスå–り出ã—(末尾) + .Distinct() //é‡è¤‡å‰Šé™¤ + .Count(); //個数å–å¾— + if (c_max_vertex_count_in_mesh <= vertex_count) { + //1メッシュを超ãˆã¦ã„ã‚‹ãªã‚‰ + //此処ã§ã®ãƒ¡ãƒƒã‚·ãƒ¥è¶…ãˆã¯å¿…ãšc_max_vertex_count_in_meshãŽã‚ŠãŽã‚Šã§æœ‰ã‚Šã€1é¢(3頂点)ã‚’1ã¤å–れã°åŽã¾ã‚‹æ§˜ã«ãªã£ã¦ã„ã‚‹ + plane_count -= 3; + break; + } + if (plane_end <= (plane_start + plane_count)) { + //é¢ã®æœ€å¾Œãªã‚‰ + break; + } + } + //分離分を戻り値ã®è¿½åŠ  + MeshCreationInfo.Pack result_pack = new MeshCreationInfo.Pack();; + result_pack.material_index = pack.material_index; + result_pack.plane_indices = pack.plane_indices.Skip((int)plane_start) //é¢é ‚点インデックスå–り出ã—(先頭) + .Take((int)plane_count) //é¢é ‚点インデックスå–り出ã—(末尾) + .ToArray(); + result_pack.vertices = result_pack.plane_indices.Distinct() //é‡è¤‡å‰Šé™¤ + .ToArray(); + result.Add(result_pack); + //開始点を後ã‚ã« + plane_start += plane_count; + } + return result; + } + + /// + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆ + /// + /// メッシュ + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ± + Mesh[] CreateMesh(MeshCreationInfo[] creation_info) + { + Mesh[] result = new Mesh[creation_info.Length]; + for (int i = 0, i_max = creation_info.Length; i < i_max; ++i) { + Mesh mesh = new Mesh(); + EntryAttributesForMesh(mesh, creation_info[i]); + SetSubMesh(mesh, creation_info[i]); + CreateAssetForMesh(mesh, i); + result[i] = mesh; + } + return result; + } + + /// + /// メッシュã«åŸºæœ¬æƒ…å ±(頂点座標・法線・UV・ボーンウェイト)を登録ã™ã‚‹ + /// + /// 対象メッシュ + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ± + void EntryAttributesForMesh(Mesh mesh, MeshCreationInfo creation_info) + { + mesh.vertices = creation_info.all_vertices.Select(x=>format_.vertex_list.vertex[x].pos * scale_).ToArray(); + mesh.normals = creation_info.all_vertices.Select(x=>format_.vertex_list.vertex[x].normal_vec).ToArray(); + mesh.uv = creation_info.all_vertices.Select(x=>format_.vertex_list.vertex[x].uv).ToArray(); + if (0 < format_.header.additionalUV) { + //追加UVãŒ1ã¤ä»¥ä¸Šæœ‰ã‚Œã° + //1ã¤ç›®ã®ã¿ç™»éŒ² + mesh.uv2 = creation_info.all_vertices.Select(x=>new Vector2(format_.vertex_list.vertex[x].add_uv[0].x, format_.vertex_list.vertex[x].add_uv[0].y)).ToArray(); + } + if (1 < format_.header.additionalUV) + { + //追加UVãŒ1ã¤ä»¥ä¸Šæœ‰ã‚Œã° + //2ã¤ç›®ã®ã¿ç™»éŒ² + mesh.uv3 = creation_info.all_vertices.Select(x => new Vector2(format_.vertex_list.vertex[x].add_uv[1].x, format_.vertex_list.vertex[x].add_uv[1].y)).ToArray(); + } + if (2 < format_.header.additionalUV) + { + //追加UVãŒ1ã¤ä»¥ä¸Šæœ‰ã‚Œã° + //3ã¤ç›®ã®ã¿ç™»éŒ² + mesh.uv4 = creation_info.all_vertices.Select(x => new Vector2(format_.vertex_list.vertex[x].add_uv[2].x, format_.vertex_list.vertex[x].add_uv[2].y)).ToArray(); + } + mesh.boneWeights = creation_info.all_vertices.Select(x=>ConvertBoneWeight(format_.vertex_list.vertex[x].bone_weight)).ToArray(); + mesh.colors = creation_info.all_vertices.Select(x=>new Color(0.0f, 0.0f, 0.0f, format_.vertex_list.vertex[x].edge_magnification * 0.25f)).ToArray(); //ä¸é€æ˜Žåº¦ã«ã‚¨ãƒƒã‚¸å€çŽ‡ã‚’0.25å€ã—ãŸæƒ…報を仕込む(0~8è¿„ã¯è¡¨ã›ã‚‹) + } + + /// + /// ボーンウェイトをUnity用ã«å¤‰æ›ã™ã‚‹ + /// + /// Unity用ボーンウェイト + /// PMX用ボーンウェイト + BoneWeight ConvertBoneWeight(PMXFormat.BoneWeight bone_weight) + { + //HACK: å–り敢ãˆãšãƒœãƒ¼ãƒ³ã‚¦ã‚§ã‚¤ãƒˆã‚¿ã‚¤ãƒ—を考ãˆãšã«BDEFxç³»ã¨ã—ã¦ç™»éŒ²ã™ã‚‹ + BoneWeight result = new BoneWeight(); + switch (bone_weight.method) { + case PMXFormat.Vertex.WeightMethod.BDEF1: goto case PMXFormat.Vertex.WeightMethod.BDEF4; + case PMXFormat.Vertex.WeightMethod.BDEF2: goto case PMXFormat.Vertex.WeightMethod.BDEF4; + case PMXFormat.Vertex.WeightMethod.BDEF4: + //BDEF4ãªã‚‰ + result.boneIndex0 = (int)bone_weight.bone1_ref; + result.weight0 = bone_weight.bone1_weight; + result.boneIndex1 = (int)bone_weight.bone2_ref;; + result.weight1 = bone_weight.bone2_weight; + result.boneIndex2 = (int)bone_weight.bone3_ref; + result.weight2 = bone_weight.bone3_weight; + result.boneIndex3 = (int)bone_weight.bone4_ref; + result.weight3 = bone_weight.bone4_weight; + break; + case PMXFormat.Vertex.WeightMethod.SDEF: + //SDEFãªã‚‰ + //HACK: BDEF4ã¨åŒã˜å¯¾å¿œ + goto case PMXFormat.Vertex.WeightMethod.BDEF4; + case PMXFormat.Vertex.WeightMethod.QDEF: + //QDEFãªã‚‰ + //HACK: BDEF4ã¨åŒã˜å¯¾å¿œ + goto case PMXFormat.Vertex.WeightMethod.BDEF4; + default: + throw new System.ArgumentOutOfRangeException(); + } + return result; + } + + /// + /// メッシュã«ã‚µãƒ–メッシュを登録ã™ã‚‹ + /// + /// 対象メッシュ + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ± + void SetSubMesh(Mesh mesh, MeshCreationInfo creation_info) + { + // マテリアル対サブメッシュ + // サブメッシュã¨ã¯ãƒžãƒ†ãƒªã‚¢ãƒ«ã«é©ç”¨ã—ãŸã„é¢é ‚点データã®ã“㨠+ // é¢ã”ã¨ã«è¨­å®šã™ã‚‹ãƒžãƒ†ãƒªã‚¢ãƒ«ã¯ã“ã“ + mesh.subMeshCount = creation_info.value.Length; + for (int i = 0, i_max = creation_info.value.Length; i < i_max; ++i) { + //format_.face_vertex_list.face_vert_indexã‚’[start](å«ã‚€)ã‹ã‚‰[start+count](å«ã¾ãš)è¿„å–り出㗠+ int[] indices = creation_info.value[i].plane_indices.Select(x=>(int)creation_info.reassign_dictionary[x]) //é ‚ç‚¹ãƒªã‚¢ã‚µã‚¤ãƒ³ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹å¤‰æ› + .ToArray(); + mesh.SetTriangles(indices, i); + } + } + + /// + /// メッシュをProjectã«ç™»éŒ²ã™ã‚‹ + /// + /// 対象メッシュ + /// メッシュインデックス + void CreateAssetForMesh(Mesh mesh, int index) + { + string path = format_.meta_header.folder + "/Meshes/"; + if (!System.IO.Directory.Exists(path)) { + AssetDatabase.CreateFolder(format_.meta_header.folder, "Meshes"); + } + + string name = GetFilePathString(format_.meta_header.name); + string file_name = path + index.ToString() + "_" + name + ".asset"; + AssetDatabase.CreateAsset(mesh, file_name); + } + + /// + /// ãƒžãƒ†ãƒªã‚¢ãƒ«ä½œæˆ + /// + /// マテリアル + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ± + Material[][] CreateMaterials(MeshCreationInfo[] creation_info) + { + // é©å½“ãªãƒ•ã‚©ãƒ«ãƒ€ã«æŠ•ã’ã‚‹ + string path = format_.meta_header.folder + "/Materials/"; + if (!System.IO.Directory.Exists(path)) { + AssetDatabase.CreateFolder(format_.meta_header.folder, "Materials"); + } + + //å…¨ãƒžãƒ†ãƒªã‚¢ãƒ«ã‚’ä½œæˆ + Material[] materials = EntryAttributesForMaterials(); + CreateAssetForMaterials(materials); + + //メッシュå˜ä½ã¸æŒ¯ã‚Šåˆ†ã‘ + Material[][] result = new Material[creation_info.Length][]; + for (int i = 0, i_max = creation_info.Length; i < i_max; ++i) { + result[i] = creation_info[i].value.Select(x=>materials[x.material_index]).ToArray(); + } + + return result; + } + + /// + /// マテリアルã«åŸºæœ¬æƒ…å ±(シェーダー・カラー・テクスãƒãƒ£)を登録ã™ã‚‹ + /// + /// マテリアル + Material[] EntryAttributesForMaterials() + { + //æè³ªãƒ¢ãƒ¼ãƒ•ãŒé€éŽã‚’è¦æœ›ã™ã‚‹ã‹ + bool[] is_transparent_by_material = IsTransparentByMaterial(); //æè³ª + bool[] is_transparent_by_material_morph = IsTransparentByMaterialMorph(); //æè³ªãƒ¢ãƒ¼ãƒ• + bool[] is_transparent_by_texture_alpha = IsTransparentByTextureAlpha(); //テクスãƒãƒ£ã®ã‚¢ãƒ«ãƒ•ァ値(UV考慮済ã¿) + + return Enumerable.Range(0, format_.material_list.material.Length) + .Select(x=>new {material_index = (uint)x + , is_transparent = is_transparent_by_material[x] || is_transparent_by_material_morph[x] || is_transparent_by_texture_alpha[x] + } + ) + .Select(x=>ConvertMaterial(x.material_index, x.is_transparent)) + .ToArray(); + } + + /// + /// æè³ªã«ä¾ã‚‹é€éŽç¢ºèª + /// + /// é€éŽã‹ã®é…列(true:é€éŽ, false:ä¸é€æ˜Ž) + bool[] IsTransparentByMaterial() + { + //拡散色ã¨ã‚¨ãƒƒã‚¸è‰²ã®é€éŽç¢ºèª + bool[] result = format_.material_list.material.Select(x=>(x.diffuse_color.a < 1.0f) || (x.edge_color.a < 1.0f)) + .ToArray(); + return result; + } + + /// + /// æè³ªãƒ¢ãƒ¼ãƒ•ã«ä¾ã‚‹é€éŽç¢ºèª + /// + /// é€éŽã‹ã®é…列(true:é€éŽ, false:ä¸é€æ˜Ž) + bool[] IsTransparentByMaterialMorph() + { + bool[] result = Enumerable.Repeat(false, format_.material_list.material.Length) + .ToArray(); + var transparent_material_indices = format_.morph_list.morph_data.Where(x=>PMXFormat.MorphData.MorphType.Material==x.morph_type) //æè³ªãƒ¢ãƒ¼ãƒ•ãªã‚‰ + .SelectMany(x=>x.morph_offset) //æè³ªãƒ¢ãƒ¼ãƒ•オフセットå–å¾— + .Select(x=>(PMXFormat.MaterialMorphOffset)x) //æè³ªãƒ¢ãƒ¼ãƒ•オフセットã«ã‚­ãƒ£ã‚¹ãƒˆ + .Where(x=>(PMXFormat.MaterialMorphOffset.OffsetMethod.Mul==x.offset_method)&&((x.diffuse.a < 1.0f)||(x.edge_color.a < 1.0f))) //拡散色ã‹ã‚¨ãƒƒã‚¸è‰²ãŒé€éŽã«ç‚ºã‚‹ãªã‚‰ + .Select(x=>x.material_index) //マテリアルインデックスå–å¾— + .Distinct(); //é‡è¤‡é™¤åŽ» + foreach (uint material_index in transparent_material_indices) { + //æè³ªãƒ¢ãƒ¼ãƒ•ã«ä¾ã£ã¦é€éŽãŒè¦æœ›ã•れã¦ã„ã‚‹ãªã‚‰ + //é€éŽæ‰±ã„ã«ã™ã‚‹ + if (material_index < (uint)format_.material_list.material.Length) { + //å˜ä½“モーフã®ãƒžãƒ†ãƒªã‚¢ãƒ«ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãªã‚‰ + //対象マテリアルã ã‘é€éŽæ‰±ã„ + result[material_index] = true; + } else { + //全対象モーフã®ãƒžãƒ†ãƒªã‚¢ãƒ«ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãªã‚‰ + //å…¨ã¦é€éŽæ‰±ã„ + result = Enumerable.Repeat(true, result.Length).ToArray(); + break; + } + } + return result; + } + + /// + /// テクスãƒãƒ£ã®ã‚¢ãƒ«ãƒ•ァ値ã«ä¾ã‚‹é€éŽç¢ºèª + /// + /// é€éŽã‹ã®é…列(true:é€éŽ, false:ä¸é€æ˜Ž) + bool[] IsTransparentByTextureAlpha() + { + Texture2D[] textures = GetTextureList(); + Vector2[][] uvs = GetUvList(); + bool[] result = Enumerable.Range(0, format_.material_list.material.Length) + .Select(x=>((null != textures[x]) + ? IsTransparentByTextureAlphaWithUv(textures[x], uvs[x]) + : false + )) + .ToArray(); + return result; + } + + /// + /// テクスãƒãƒ£ã®å–å¾— + /// + /// テクスãƒãƒ£é…列 + Texture2D[] GetTextureList() + { + string[] texture_path = format_.material_list.material.Select(x=>x.usually_texture_index) //æè³ªãŒä½¿ç”¨ã—ã¦ã„るテクスãƒãƒ£ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’å–å¾— + .Select(x=>((x + /// UVã®å–å¾— + /// + /// UVé…列 + /// + /// UVモーフã«ã¦æ”¹å¤‰ã•れる場åˆã¯æœªé©å¿œ(0.0f)ã¨å…¨é©å¿œ(1.0f)ã®2段階ã®ã¿ã‚’扱ã„ã€ä¸­é–“é©å¿œã¯è€ƒæ…®ã—ãªã„。 + /// 複数ã®UVモーフãŒåŒä¸€é ‚ç‚¹ã«æŽ›ã‹ã‚‹å ´åˆã«å¤šé‡é©å¿œã™ã‚‹ã¨å˜ä½“ã§ã¯å‚照出æ¥ç„¡ã„領域迄å‚照出æ¥ã‚‹æ§˜ã«ç‚ºã‚‹ãŒã€ã“れã¯è€ƒæ…®ã—ãªã„。 + /// åŒæ§˜ã«ã‚°ãƒ«ãƒ¼ãƒ—モーフã«ä¾ã‚‹1.0fè¶…ãˆã‚‚考慮ã—ãªã„。 + /// + Vector2[][] GetUvList() + { + uint[][] vertex_list = CreateMeshCreationInfoPacks().Select(x=>x.plane_indices).ToArray(); + + Dictionary[] uv_morphs = format_.morph_list.morph_data + .Where(x=>PMXFormat.MorphData.MorphType.Uv==x.morph_type) //UVモーフãªã‚‰ + .Select(x=>x.morph_offset.Select(y=>(PMXFormat.UVMorphOffset)y) + .ToDictionary(z=>z.vertex_index, z=>z.uv_offset) //頂点インデックスã§ãƒ‡ã‚£ã‚¯ã‚·ãƒ§ãƒŠãƒªåŒ– + ) //UVモーフオフセットå–å¾— + .ToArray(); + + List[] result = vertex_list.Select(x=>x.Select(y=>format_.vertex_list.vertex[y].uv).ToList()).ToArray(); + + //æè³ªèµ°æŸ» + bool is_cancel = false; + for (int material_index = 0, material_index_max = result.Length; material_index < material_index_max; ++material_index) { + //UVモーフ走査 + for (int uv_morph_index = 0, uv_morph_index_max = uv_morphs.Length; uv_morph_index < uv_morph_index_max; ++uv_morph_index) { + var uv_morph = uv_morphs[uv_morph_index]; + //ブログレスパー更新 + is_cancel = EditorUtility.DisplayCancelableProgressBar("Create UV Area Infomation" + , "Material:[" + material_index + "|" + material_index_max + "]" + + format_.material_list.material[material_index].name + + "\t" + + "UV Morph:[" + uv_morph_index + "|" + uv_morph_index_max + "]" + + format_.morph_list.morph_data.Where(x=>PMXFormat.MorphData.MorphType.Uv==x.morph_type).Skip(uv_morph_index).First().morph_name + , ((((float)uv_morph_index / (float)uv_morph_index_max) + (float)material_index) / (float)material_index_max) + ); + if (is_cancel) { + break; + } + + //先行UVモーフ対象確èª(三角形構æˆã‚’無視ã—ã¦å…¨é ‚点をUVモーフå‚ç…§) + var vertex_dictionary = vertex_list[material_index].Distinct().ToDictionary(x=>x, x=>true); //(UVモーフã«è¨­å®šã•れã¦ã„る頂点数ä¾ã‚Šã‚‚三角形構æˆé ‚ç‚¹ã®æ–¹ãŒå¤šã„ã¨æ€ã†ã®ã§ã€ãã¡ã‚‰å´ã‚’logNã«ã™ã‚‹ç‚ºã«è¾žæ›¸ä½œæˆ) + if (uv_morph.Keys.Any(x=>vertex_dictionary.ContainsKey(x))) { + //UVモーフ対象ãªã‚‰ + //頂点走査(三角形構æˆé ‚点走査) + for (int vertex_index = 0, vertex_index_max = vertex_list[material_index].Length; vertex_index < vertex_index_max; vertex_index+=3) { + //三角形構æˆé ‚点インデックスå–り出㗠+ uint[] tri_vertices = new []{vertex_list[material_index][vertex_index+0] + , vertex_list[material_index][vertex_index+1] + , vertex_list[material_index][vertex_index+2] + }; + //UVãƒ¢ãƒ¼ãƒ•å¯¾è±¡ç¢ºèª + if (tri_vertices.Any(x=>uv_morph.ContainsKey(x))) { + //UVモーフ対象ãªã‚‰ + //é©å¿œã—ãŸUVå€¤ã‚’ä½œæˆ + var tri_uv = tri_vertices.Select(x=>new{original_uv = format_.vertex_list.vertex[x].uv + , add_uv = ((uv_morph.ContainsKey(x))? uv_morph[x]: Vector4.zero) + } + ) + .Select(x=>new Vector2(x.original_uv.x + x.add_uv.x, x.original_uv.y + x.add_uv.y)); + //追加 + result[material_index].AddRange(tri_uv); + } + } + } + } + if (is_cancel) { + break; + } + } + EditorUtility.ClearProgressBar(); + + return result.Select(x=>x.ToArray()).ToArray(); + } + + /// + /// UV値を考慮ã—ãŸã€ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®ã‚¢ãƒ«ãƒ•ァ値ã«ä¾ã‚‹é€éŽç¢ºèª + /// + /// é€éŽã‹(true:é€éŽ, false:ä¸é€æ˜Ž) + /// テクスãƒãƒ£ + /// UV値(3ã¤å˜ä½ã§ä¸‰è§’形を構æˆã™ã‚‹) + static bool IsTransparentByTextureAlphaWithUv(Texture2D texture, Vector2[] uvs) + { + bool result = true; + if (TextureFormat.Alpha8 == texture.format) { + //ファイルãŒDDS以外ãªã‚‰(AlphaReadableTextureDirectoryImporterã«ä¾ã£ã¦DDS以外ã¯Alpha8ã«ç‚ºã‚‹) + //alphaIsTransparencyを確èªã™ã‚‹ + result = texture.alphaIsTransparency; //アルファ値をæŒãŸãªã„ãªã‚‰é€éŽãƒ•ラグãŒç«‹ã£ã¦ã„ãªã„ + } + if (result) { + //アルファ値をæŒã¤ãªã‚‰ + //è©³ç´°ç¢ºèª + result = Enumerable.Range(0, uvs.Length / 3) //3ã¤å˜ä½ã§å–り出ã™ç‚ºã®å…ƒã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ + .Select(x=>x*3) //3ã¤é–“éš”ã«å¤‰æ› + .Any(x=>IsTransparentByTextureAlphaWithUv(texture, uvs[x+0],uvs[x+1],uvs[x+2])); //三角形をé€éŽç¢ºèªã€ã©ã‚Œã‹ãŒé€éŽã—ã¦ã„ãŸã‚‰é€éŽã¨ã™ã‚‹ + } + return result; + } + + /// + /// UV値を考慮ã—ãŸã€ãƒ†ã‚¯ã‚¹ãƒãƒ£ã®ã‚¢ãƒ«ãƒ•ァ値ã«ä¾ã‚‹é€éŽç¢ºèª + /// + /// é€éŽã‹(true:é€éŽ, false:ä¸é€æ˜Ž) + /// テクスãƒãƒ£ + /// 三角形頂点ã®UV値 + /// 三角形頂点ã®UV値 + /// 三角形頂点ã®UV値 + /// + /// ç†æƒ³ãªã‚‰ã°å…¨ãƒ†ã‚¯ã‚»ãƒ«ã‚’確èªã—ãªã‘れã°ãªã‚‰ãªã„ãŒã€ + /// ç¾åœ¨ã®å®Ÿè£…ã§ã¯ä¸‰è§’形を構æˆã™ã‚‹å„頂点ã®UV・é‡å¿ƒãƒ»å„辺ã®ä¸­å¿ƒç‚¹ã®7点ã®ãƒ†ã‚¯ã‚»ãƒ«ã—ã‹ç¢ºèªã—ã¦ã„ãªã„ + /// + static bool IsTransparentByTextureAlphaWithUv(Texture2D texture, Vector2 uv1, Vector2 uv2, Vector2 uv3) + { + bool result = true; //é€éŽ + do { + //座標系ãŒç›¸é•ã—ã¦ã„ã‚‹ã®ã§è£œæ­£ + uv1.Set(uv1.x, 1.0f - uv1.y - (1.0f / texture.height)); + uv2.Set(uv2.x, 1.0f - uv2.y - (1.0f / texture.height)); + uv3.Set(uv3.x, 1.0f - uv3.y - (1.0f / texture.height)); + + const float c_threshold = 253.0f / 255.0f; //253程度迄ã¯ä¸é€æ˜Žã¨ã—ã¦è¦‹é€ƒã™ + + //頂点直下 + if (texture.GetPixelBilinear(uv1.x, uv1.y).a < c_threshold) { + break; + } + if (texture.GetPixelBilinear(uv2.x, uv2.y).a < c_threshold) { + break; + } + if (texture.GetPixelBilinear(uv3.x, uv3.y).a < c_threshold) { + break; + } + + //é‡å¿ƒ + Vector2 center = new Vector2((uv1.x + uv2.x + uv3.x) / 3.0f, (uv1.y + uv2.y + uv3.y) / 3.0f); + if (texture.GetPixelBilinear(center.x, center.y).a < c_threshold) { + break; + } + + //辺中央 + Vector2 uv12 = new Vector2((uv1.x + uv2.x) / 2.0f, (uv1.y + uv2.y) / 2.0f); + if (texture.GetPixelBilinear(uv12.x, uv12.y).a < c_threshold) { + break; + } + Vector2 uv23 = new Vector2((uv2.x + uv3.x) / 2.0f, (uv2.y + uv3.y) / 2.0f); + if (texture.GetPixelBilinear(uv23.x, uv23.y).a < c_threshold) { + break; + } + Vector2 uv31 = new Vector2((uv3.x + uv1.x) / 2.0f, (uv3.y + uv1.y) / 2.0f); + if (texture.GetPixelBilinear(uv31.x, uv31.y).a < c_threshold) { + break; + } + + //此処迄æ¥ãŸã‚‰ä¸é€æ˜Ž + result = false; + } while(false); + return result; + } + + /// + /// マテリアルをUnity用ã«å¤‰æ›ã™ã‚‹ + /// + /// Unity用マテリアル + /// PMX用マテリアルインデックス + /// é€éŽã‹ + Material ConvertMaterial(uint material_index, bool is_transparent) + { + PMXFormat.Material material = format_.material_list.material[material_index]; + + //å…ˆã«ãƒ†ã‚¯ã‚¹ãƒãƒ£æƒ…報を検索 + Texture2D main_texture = null; + if (material.usually_texture_index < format_.texture_list.texture_file.Length) { + string texture_file_name = format_.texture_list.texture_file[material.usually_texture_index]; + string path = format_.meta_header.folder + "/" + texture_file_name; + main_texture = (Texture2D)AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)); + } + + //マテリアルã«è¨­å®š + string shader_path = GetMmdShaderPath(material, main_texture, is_transparent); + Material result = new Material(Shader.Find(shader_path)); + + // シェーダã«ä¾ã£ã¦å€¤ãŒæœ‰ã£ãŸã‚Šç„¡ã‹ã£ãŸã‚Šã™ã‚‹ãŒã€è¨­å®šã—ã¦ã‚‚エラーã«ç‚ºã‚‰ãªã„様ãªã®ã§å…¨éƒ¨è¨­å®š + result.SetColor("_Color", material.diffuse_color); + result.SetColor("_AmbColor", material.ambient_color); + result.SetFloat("_Opacity", material.diffuse_color.a); + result.SetColor("_SpecularColor", material.specular_color); + result.SetFloat("_Shininess", material.specularity); + // エッジ + const float c_default_scale = 0.085f; //0.085fã®æ™‚ã«MMDã¨ä¸€è‡´ã™ã‚‹æ§˜ã«ã—ã¦ã„ã‚‹ã®ã§ã€ãれ以外ãªã‚‰è£œæ­£ + result.SetFloat("_OutlineWidth", material.edge_size * scale_ / c_default_scale); + result.SetColor("_OutlineColor", material.edge_color); + //カスタムレンダーキュー + { + MMDEngine engine = root_game_object_.GetComponent(); + if (engine.enable_render_queue && IsTransparentMaterial(is_transparent)) { + //ã‚«ã‚¹ã‚¿ãƒ ãƒ¬ãƒ³ãƒ€ãƒ¼ã‚­ãƒ¥ãƒ¼ãŒæœ‰åй ã‹ã¤ マテリアルãŒé€éŽãªã‚‰ + //マテリアル順ã«ä¸¦ã¹ã‚‹ + result.renderQueue = engine.render_queue_value + (int)material_index; + } else { + //éžé€æ˜Žãªã‚‰ + result.renderQueue = -1; + } + } + + // スフィアテクスãƒãƒ£ + if (material.sphere_texture_index < format_.texture_list.texture_file.Length) { + string sphere_texture_file_name = format_.texture_list.texture_file[material.sphere_texture_index]; + string path = format_.meta_header.folder + "/" + sphere_texture_file_name; + Texture2D sphere_texture = (Texture2D)UnityEditor.AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)); + + switch (material.sphere_mode) { + case PMXFormat.Material.SphereMode.AddSphere: // 加算 + result.SetTexture("_SphereAddTex", sphere_texture); + result.SetTextureScale("_SphereAddTex", new Vector2(1, -1)); + break; + case PMXFormat.Material.SphereMode.MulSphere: // ä¹—ç®— + result.SetTexture("_SphereMulTex", sphere_texture); + result.SetTextureScale("_SphereMulTex", new Vector2(1, -1)); + break; + case PMXFormat.Material.SphereMode.SubTexture: // サブテクスãƒãƒ£ + //サブテクスãƒãƒ£ç”¨ã‚·ã‚§ãƒ¼ãƒ€ãƒ¼ãŒç„¡ã„ã®ã§è¨­å®šã—ãªã„ + break; + default: + //empty. + break; + + } + } + + // トゥーンテクスãƒãƒ£ + { + string toon_texture_name = null; + string toon_texture_path = null; + if (0 < material.common_toon) { + //共通トゥーン + string resource_path = System.IO.Path.GetDirectoryName(UnityEditor.AssetDatabase.GetAssetPath(Shader.Find("MMD/HalfLambertOutline"))); + toon_texture_name = "toon" + material.common_toon.ToString("00") + ".bmp"; + toon_texture_path = System.IO.Path.Combine(resource_path, toon_texture_name); + } else if (material.toon_texture_index < format_.texture_list.texture_file.Length) { + //自å‰ãƒˆã‚¥ãƒ¼ãƒ³ + toon_texture_name = format_.texture_list.texture_file[material.toon_texture_index]; + toon_texture_path = System.IO.Path.Combine(format_.meta_header.folder, toon_texture_name); + } + if (!string.IsNullOrEmpty(toon_texture_path)) { + Texture2D toon_texture = (Texture2D)UnityEditor.AssetDatabase.LoadAssetAtPath(toon_texture_path, typeof(Texture2D)); + result.SetTexture("_ToonTex", toon_texture); + result.SetTextureScale("_ToonTex", new Vector2(1, -1)); + } + } + + // テクスãƒãƒ£ãŒç©ºã§ãªã‘れã°ç™»éŒ² + if (null != main_texture) { + result.mainTexture = main_texture; + result.mainTextureScale = new Vector2(1, -1); + } + + return result; + } + + /// + /// MMDシェーダーパスã®å–å¾— + /// + /// MMDシェーダーパス + /// シェーダーを設定ã™ã‚‹ãƒžãƒ†ãƒªã‚¢ãƒ« + /// シェーダーã«è¨­å®šã™ã‚‹ãƒ¡ã‚¤ãƒ³ãƒ†ã‚¯ã‚¹ãƒãƒ£ + /// é€éŽã‹ + string GetMmdShaderPath(PMXFormat.Material material, Texture2D texture, bool is_transparent) { + string result = "MMD/"; + if (IsTransparentMaterial(is_transparent)) { + result += "Transparent/"; + } + result += "PMDMaterial"; + if (IsEdgeMaterial(material)) { + result += "-with-Outline"; + } + if (IsCullBackMaterial(material)) { + result += "-CullBack"; + } + if (IsNoCastShadowMaterial(material)) { + result += "-NoCastShadow"; + } +#if MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER //å½±å—ã‘ç„¡ã—ã®ã‚·ã‚§ãƒ¼ãƒ€ã¯ã¾ã ç„¡ã„ã®ã§ç„¡åŠ¹åŒ– + if (IsNoReceiveShadowMaterial(material)) { + result += "-NoReceiveShadow"; + } +#endif //MFU_ENABLE_NO_RECEIVE_SHADOW_SHADER + return result; + } + + /// + /// é€éŽãƒžãƒ†ãƒªã‚¢ãƒ«ç¢ºèª + /// + /// true:é€éŽ, false:ä¸é€æ˜Ž + /// é€éŽã‹ + bool IsTransparentMaterial(bool is_transparent) { + return is_transparent; + } + + /// + /// ã‚¨ãƒƒã‚¸ãƒžãƒ†ãƒªã‚¢ãƒ«ç¢ºèª + /// + /// true:エッジ有り, false:無エッジ + /// シェーダーを設定ã™ã‚‹ãƒžãƒ†ãƒªã‚¢ãƒ« + bool IsEdgeMaterial(PMXFormat.Material material) { + bool result; + if (0 != (PMXFormat.Material.Flag.Edge & material.flag)) { + //エッジ有りãªã‚‰ + result = true; + } else { + //エッジ無㗠+ result = false; + } + return result; + } + + /// + /// 背é¢ã‚«ãƒªãƒ³ã‚°ãƒžãƒ†ãƒªã‚¢ãƒ«ç¢ºèª + /// + /// true:背é¢ã‚«ãƒªãƒ³ã‚°ã™ã‚‹, false:背é¢ã‚«ãƒªãƒ³ã‚°ã—ãªã„ + /// シェーダーを設定ã™ã‚‹ãƒžãƒ†ãƒªã‚¢ãƒ« + bool IsCullBackMaterial(PMXFormat.Material material) { + bool result; + if (0 != (PMXFormat.Material.Flag.Reversible & material.flag)) { + //ä¸¡é¢æç”»ãªã‚‰ + //背é¢ã‚«ãƒªãƒ³ã‚°ã—ãªã„ + result = false; + } else { + //ä¸¡é¢æç”»ã§ç„¡ã„ãªã‚‰ + //背é¢ã‚«ãƒªãƒ³ã‚°ã™ã‚‹ + result = true; + } + return result; + } + + /// + /// ç„¡å½±ãƒžãƒ†ãƒªã‚¢ãƒ«ç¢ºèª + /// + /// true:ç„¡å½±, false:影放㡠+ /// シェーダーを設定ã™ã‚‹ãƒžãƒ†ãƒªã‚¢ãƒ« + bool IsNoCastShadowMaterial(PMXFormat.Material material) { + bool result; + if (0 != (PMXFormat.Material.Flag.CastShadow & material.flag)) { + //影放㡠+ result = false; + } else { + //ç„¡å½± + result = true; + } + return result; + } + + /// + /// å½±å—ã‘ç„¡ã—ãƒžãƒ†ãƒªã‚¢ãƒ«ç¢ºèª + /// + /// true:å½±å—ã‘ç„¡ã—, false:å½±å—ã‘ + /// シェーダーを設定ã™ã‚‹ãƒžãƒ†ãƒªã‚¢ãƒ« + bool IsNoReceiveShadowMaterial(PMXFormat.Material material) { + bool result; + if (0 != (PMXFormat.Material.Flag.ReceiveSelfShadow & material.flag)) { + //å½±å—ã‘ + result = false; + } else { + //å½±å—ã‘ç„¡ã— + result = true; + } + return result; + } + + /// + /// マテリアルをProjectã«ç™»éŒ²ã™ã‚‹ + /// + /// 対象マテリアル + void CreateAssetForMaterials(Material[] materials) { + string path = format_.meta_header.folder + "/Materials/"; + + for (int i = 0, i_max = materials.Length; i < i_max; ++i) { + string name = GetFilePathString(format_.material_list.material[i].name); + string file_name = path + i.ToString() + "_" + name + ".asset"; + AssetDatabase.CreateAsset(materials[i], file_name); + } + } + + /// + /// ãƒœãƒ¼ãƒ³ä½œæˆ + /// + /// ボーンã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + GameObject[] CreateBones() + { + GameObject[] bones = EntryAttributeForBones(); + AttachParentsForBone(bones); + return bones; + } + + /// + /// ボーンã«åŸºæœ¬æƒ…å ±(åå‰ãƒ»ä½ç½®)を登録ã™ã‚‹ + /// + /// ボーンã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + GameObject[] EntryAttributeForBones() + { + return format_.bone_list.bone.Select(x=>{ + GameObject game_object = new GameObject(x.bone_name); + game_object.transform.position = x.bone_position * scale_; + return game_object; + }).ToArray(); + } + + /// + /// 親å­é–¢ä¿‚ã®æ§‹ç¯‰ + /// + /// ボーンã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + void AttachParentsForBone(GameObject[] bones) + { + //モデルルートを生æˆã—ã¦ãƒ«ãƒ¼ãƒˆã®å­ä¾›ã«ä»˜ã‘ã‚‹ + Transform model_root_transform = (new GameObject("Model")).transform; + model_root_transform.parent = root_game_object_.transform; + + for (int i = 0, i_max = format_.bone_list.bone.Length; i < i_max; ++i) { + uint parent_bone_index = format_.bone_list.bone[i].parent_bone_index; + if (parent_bone_index < (uint)bones.Length) { + //親ã®ãƒœãƒ¼ãƒ³ãŒæœ‰ã‚‹ãªã‚‰ + //ãれã®å­ã«ç‚ºã‚‹ + bones[i].transform.parent = bones[parent_bone_index].transform; + } else { + //親ã®ãƒœãƒ¼ãƒ³ãŒç„¡ã„ãªã‚‰ + //モデルルートã®å­ã«ç‚ºã‚‹ + bones[i].transform.parent = model_root_transform; + } + } + } + + /// + /// ãƒ¢ãƒ¼ãƒ•ä½œæˆ + /// + /// 対象メッシュ + /// 対象マテリアル + /// 対象ボーン + /// 対象レンダラー + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ± + void CreateMorph(Mesh[] mesh, Material[][] materials, GameObject[] bones, SkinnedMeshRenderer[] renderers, MeshCreationInfo[] creation_info) + { + //表情ルートを生æˆã—ã¦ãƒ«ãƒ¼ãƒˆã®å­ä¾›ã«ä»˜ã‘ã‚‹ + GameObject expression_root = new GameObject("Expression"); + Transform expression_root_transform = expression_root.transform; + expression_root_transform.parent = root_game_object_.transform; + + //表情マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ + MorphManager morph_manager = expression_root.AddComponent(); + morph_manager.uv_morph = new MorphManager.UvMorphPack[1 + format_.header.additionalUV]; //UVモーフ数設定 + + //å€‹åˆ¥ãƒ¢ãƒ¼ãƒ•ã‚¹ã‚¯ãƒªãƒ—ãƒˆä½œæˆ + GameObject[] morphs = new GameObject[format_.morph_list.morph_data.Length]; + for (int i = 0, i_max = format_.morph_list.morph_data.Length; i < i_max; ++i) { + morphs[i] = new GameObject(format_.morph_list.morph_data[i].morph_name); + // 表情を親ボーンã«ä»˜ã‘ã‚‹ + morphs[i].transform.parent = expression_root_transform; + } + + //ã‚°ãƒ«ãƒ¼ãƒ—ãƒ¢ãƒ¼ãƒ•ä½œæˆ + CreateGroupMorph(morph_manager, morphs); + //ボーンモーフ + morph_manager.bones = bones.Select(x=>x.transform).ToArray(); + CreateBoneMorph(morph_manager, morphs); + //é ‚ç‚¹ãƒ¢ãƒ¼ãƒ•ä½œæˆ + CreateVertexMorph(morph_manager, morphs, creation_info); + //UV・追加UVãƒ¢ãƒ¼ãƒ•ä½œæˆ + CreateUvMorph(morph_manager, morphs, creation_info); + //æè³ªãƒ¢ãƒ¼ãƒ•ä½œæˆ + CreateMaterialMorph(morph_manager, morphs, creation_info); + //モーフ一覧設定(モーフコンãƒãƒ¼ãƒãƒ³ãƒˆã®æƒ…報を拾ã†ç‚ºã€æœ€å¾Œã«è¨­å®šã™ã‚‹) + morph_manager.morphs = morphs.Select(x=>x.GetComponent()).ToArray(); + + //メッシュ・マテリアル設定 + morph_manager.renderers = renderers; + morph_manager.mesh = mesh; + morph_manager.materials = materials; + } + + /// + /// ã‚°ãƒ«ãƒ¼ãƒ—ãƒ¢ãƒ¼ãƒ•ä½œæˆ + /// + /// 表情マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ + /// モーフã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + void CreateGroupMorph(MorphManager morph_manager, GameObject[] morphs) + { + //インデックスã¨å…ƒãƒ‡ãƒ¼ã‚¿ã®ä½œæˆ + List original_indices = format_.morph_list.morph_data.Where(x=>(PMXFormat.MorphData.MorphType.Group == x.morph_type)) //該当モーフã«çµžã‚‹ + .SelectMany(x=>x.morph_offset.Select(y=>((PMXFormat.GroupMorphOffset)y).morph_index)) //インデックスã®å–り出ã—ã¨é€£çµ + .Distinct() //é‡è¤‡ã—ãŸã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®å‰Šé™¤ + .ToList(); //ソートã«å‘ã‘ã¦ä¸€æ—¦ãƒªã‚¹ãƒˆåŒ– + original_indices.Sort(); //ソート + int[] indices = original_indices.Select(x=>(int)x).ToArray(); + float[] source = Enumerable.Repeat(0.0f, indices.Length) //インデックスを用ã„ã¦ã€å…ƒãƒ‡ãƒ¼ã‚¿ã‚’パック + .ToArray(); + + //インデックス逆引ã用辞書ã®ä½œæˆ + Dictionary index_reverse_dictionary = new Dictionary(); + for (uint i = 0, i_max = (uint)indices.Length; i < i_max; ++i) { + index_reverse_dictionary.Add((uint)indices[i], i); + } + + //個別モーフスクリプトã®ä½œæˆ + GroupMorph[] script = Enumerable.Range(0, format_.morph_list.morph_data.Length) + .Where(x=>PMXFormat.MorphData.MorphType.Group == format_.morph_list.morph_data[x].morph_type) //該当モーフã«çµžã‚‹ + .Select(x=>AssignGroupMorph(morphs[x], format_.morph_list.morph_data[x], index_reverse_dictionary)) + .ToArray(); + + //表情マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã«ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãƒ»å…ƒãƒ‡ãƒ¼ã‚¿ãƒ»ã‚¹ã‚¯ãƒªãƒ—トã®è¨­å®š + morph_manager.group_morph = new MorphManager.GroupMorphPack(indices, source, script); + } + + /// + /// グループモーフ設定 + /// + /// グループモーフスクリプト + /// モーフã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// PMX用モーフデータ + /// インデックス逆引ã用辞書 + GroupMorph AssignGroupMorph(GameObject morph, PMXFormat.MorphData data, Dictionary index_reverse_dictionary) + { + GroupMorph result = morph.AddComponent(); + result.panel = (MorphManager.PanelType)data.handle_panel; + result.indices = data.morph_offset.Select(x=>((PMXFormat.GroupMorphOffset)x).morph_index) //インデックスをå–り出㗠+ .Select(x=>(int)index_reverse_dictionary[x]) //逆変æ›ã‚’掛ã‘ã‚‹ + .ToArray(); + result.values = data.morph_offset.Select(x=>((PMXFormat.GroupMorphOffset)x).morph_rate).ToArray(); + return result; + } + + /// + /// ãƒœãƒ¼ãƒ³ãƒ¢ãƒ¼ãƒ•ä½œæˆ + /// + /// 表情マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ + /// モーフã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + void CreateBoneMorph(MorphManager morph_manager, GameObject[] morphs) + { + //インデックスã¨å…ƒãƒ‡ãƒ¼ã‚¿ã®ä½œæˆ + List original_indices = format_.morph_list.morph_data.Where(x=>(PMXFormat.MorphData.MorphType.Bone == x.morph_type)) //該当モーフã«çµžã‚‹ + .SelectMany(x=>x.morph_offset.Select(y=>((PMXFormat.BoneMorphOffset)y).bone_index)) //インデックスã®å–り出ã—ã¨é€£çµ + .Distinct() //é‡è¤‡ã—ãŸã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®å‰Šé™¤ + .ToList(); //ソートã«å‘ã‘ã¦ä¸€æ—¦ãƒªã‚¹ãƒˆåŒ– + original_indices.Sort(); //ソート + int[] indices = original_indices.Select(x=>(int)x).ToArray(); + BoneMorph.BoneMorphParameter[] source = indices.Where(x=>x{ //インデックスを用ã„ã¦ã€å…ƒãƒ‡ãƒ¼ã‚¿ã‚’パック + PMXFormat.Bone y = format_.bone_list.bone[x]; + BoneMorph.BoneMorphParameter result = new BoneMorph.BoneMorphParameter(); + result.position = y.bone_position; + if (y.parent_bone_index < (uint)format_.bone_list.bone.Length) { + //親ãŒå±…ãŸã‚‰ãƒ­ãƒ¼ã‚«ãƒ«åº§æ¨™åŒ– + result.position -= format_.bone_list.bone[y.parent_bone_index].bone_position; + } + result.position *= scale_; + result.rotation = Quaternion.identity; + return result; + }) + .ToArray(); + + //インデックス逆引ã用辞書ã®ä½œæˆ + Dictionary index_reverse_dictionary = new Dictionary(); + for (uint i = 0, i_max = (uint)indices.Length; i < i_max; ++i) { + index_reverse_dictionary.Add((uint)indices[i], i); + } + + //個別モーフスクリプトã®ä½œæˆ + BoneMorph[] script = Enumerable.Range(0, format_.morph_list.morph_data.Length) + .Where(x=>PMXFormat.MorphData.MorphType.Bone == format_.morph_list.morph_data[x].morph_type) //該当モーフã«çµžã‚‹ + .Select(x=>AssignBoneMorph(morphs[x], format_.morph_list.morph_data[x], index_reverse_dictionary)) + .ToArray(); + + //表情マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã«ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãƒ»å…ƒãƒ‡ãƒ¼ã‚¿ãƒ»ã‚¹ã‚¯ãƒªãƒ—トã®è¨­å®š + morph_manager.bone_morph = new MorphManager.BoneMorphPack(indices, source, script); + } + + /// + /// ボーンモーフ設定 + /// + /// ボーンモーフスクリプト + /// モーフã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// PMX用モーフデータ + /// インデックス逆引ã用辞書 + BoneMorph AssignBoneMorph(GameObject morph, PMXFormat.MorphData data, Dictionary index_reverse_dictionary) + { + BoneMorph result = morph.AddComponent(); + result.panel = (MorphManager.PanelType)data.handle_panel; + result.indices = data.morph_offset.Select(x=>((PMXFormat.BoneMorphOffset)x).bone_index) //インデックスをå–り出㗠+ .Select(x=>(int)index_reverse_dictionary[x]) //逆変æ›ã‚’掛ã‘ã‚‹ + .ToArray(); + result.values = data.morph_offset.Select(x=>{ + PMXFormat.BoneMorphOffset y = (PMXFormat.BoneMorphOffset)x; + BoneMorph.BoneMorphParameter param = new BoneMorph.BoneMorphParameter(); + param.position = y.move_value * scale_; + param.rotation = y.rotate_value; + return param; + }) + .ToArray(); + return result; + } + + /// + /// é ‚ç‚¹ãƒ¢ãƒ¼ãƒ•ä½œæˆ + /// + /// 表情マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ + /// モーフã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ± + void CreateVertexMorph(MorphManager morph_manager, GameObject[] morphs, MeshCreationInfo[] creation_info) + { + //インデックスã¨å…ƒãƒ‡ãƒ¼ã‚¿ã®ä½œæˆ + List original_indices = format_.morph_list.morph_data.Where(x=>(PMXFormat.MorphData.MorphType.Vertex == x.morph_type)) //該当モーフã«çµžã‚‹ + .SelectMany(x=>x.morph_offset.Select(y=>((PMXFormat.VertexMorphOffset)y).vertex_index)) //インデックスã®å–り出ã—ã¨é€£çµ + .Distinct() //é‡è¤‡ã—ãŸã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®å‰Šé™¤ + .ToList(); //ソートã«å‘ã‘ã¦ä¸€æ—¦ãƒªã‚¹ãƒˆåŒ– + original_indices.Sort(); //ソート + int[] indices = original_indices.Select(x=>(int)x).ToArray(); + Vector3[] source = indices.Select(x=>format_.vertex_list.vertex[x].pos * scale_) //インデックスを用ã„ã¦ã€å…ƒãƒ‡ãƒ¼ã‚¿ã‚’パック + .ToArray(); + + //インデックス逆引ã用辞書ã®ä½œæˆ + Dictionary index_reverse_dictionary = new Dictionary(); + for (uint i = 0, i_max = (uint)indices.Length; i < i_max; ++i) { + index_reverse_dictionary.Add((uint)indices[i], i); + } + + //個別モーフスクリプトã®ä½œæˆ + VertexMorph[] script = Enumerable.Range(0, format_.morph_list.morph_data.Length) + .Where(x=>PMXFormat.MorphData.MorphType.Vertex == format_.morph_list.morph_data[x].morph_type) //該当モーフã«çµžã‚‹ + .Select(x=>AssignVertexMorph(morphs[x], format_.morph_list.morph_data[x], index_reverse_dictionary)) + .ToArray(); + + //メッシュ別インデックスã®ä½œæˆ + int invalid_vertex_index = format_.vertex_list.vertex.Length; + MorphManager.VertexMorphPack.Meshes[] multi_indices = new MorphManager.VertexMorphPack.Meshes[creation_info.Length]; + for (int i = 0, i_max = creation_info.Length; i < i_max; ++i) { + multi_indices[i] = new MorphManager.VertexMorphPack.Meshes(); + multi_indices[i].indices = new int[indices.Length]; + for (int k = 0, k_max = indices.Length; k < k_max; ++k) { + if (creation_info[i].reassign_dictionary.ContainsKey((uint)indices[k])) { + //ã“ã®ãƒ¡ãƒƒã‚·ãƒ¥ã§æœ‰åйãªã‚‰ + multi_indices[i].indices[k] = (int)creation_info[i].reassign_dictionary[(uint)indices[k]]; + } else { + //ã“ã®ãƒ¡ãƒƒã‚·ãƒ¥ã§ã¯ç„¡åйãªã‚‰ + multi_indices[i].indices[k] = invalid_vertex_index; //最大頂点数を設定(uint.MaxValueã§ã¯ç„¡ã„ã®ã§æ³¨æ„) + } + } + } + + //表情マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã«ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãƒ»å…ƒãƒ‡ãƒ¼ã‚¿ãƒ»ã‚¹ã‚¯ãƒªãƒ—トã®è¨­å®š + morph_manager.vertex_morph = new MorphManager.VertexMorphPack(multi_indices, source, script); + } + + /// + /// 頂点モーフ設定 + /// + /// 頂点モーフスクリプト + /// モーフã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// PMX用モーフデータ + /// インデックス逆引ã用辞書 + VertexMorph AssignVertexMorph(GameObject morph, PMXFormat.MorphData data, Dictionary index_reverse_dictionary) + { + VertexMorph result = morph.AddComponent(); + result.panel = (MorphManager.PanelType)data.handle_panel; + result.indices = data.morph_offset.Select(x=>((PMXFormat.VertexMorphOffset)x).vertex_index) //インデックスをå–り出㗠+ .Select(x=>(int)index_reverse_dictionary[x]) //逆変æ›ã‚’掛ã‘ã‚‹ + .ToArray(); + result.values = data.morph_offset.Select(x=>((PMXFormat.VertexMorphOffset)x).position_offset * scale_).ToArray(); + return result; + } + + /// + /// UV・追加UVãƒ¢ãƒ¼ãƒ•ä½œæˆ + /// + /// 表情マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ + /// モーフã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ± + void CreateUvMorph(MorphManager morph_manager, GameObject[] morphs, MeshCreationInfo[] creation_info) + { + for (int morph_type_index = 0, morph_type_index_max = 1 + format_.header.additionalUV; morph_type_index < morph_type_index_max; ++morph_type_index) { + //モーフタイプ + PMXFormat.MorphData.MorphType morph_type; + switch (morph_type_index) { + case 0: morph_type = PMXFormat.MorphData.MorphType.Uv; break; + case 1: morph_type = PMXFormat.MorphData.MorphType.Adduv1; break; + case 2: morph_type = PMXFormat.MorphData.MorphType.Adduv2; break; + case 3: morph_type = PMXFormat.MorphData.MorphType.Adduv3; break; + case 4: morph_type = PMXFormat.MorphData.MorphType.Adduv4; break; + default: throw new System.ArgumentOutOfRangeException(); + } + + //インデックスã¨å…ƒãƒ‡ãƒ¼ã‚¿ã®ä½œæˆ + List original_indices = format_.morph_list.morph_data.Where(x=>(morph_type == x.morph_type)) //該当モーフã«çµžã‚‹ + .SelectMany(x=>x.morph_offset.Select(y=>((PMXFormat.UVMorphOffset)y).vertex_index)) //インデックスã®å–り出ã—ã¨é€£çµ + .Distinct() //é‡è¤‡ã—ãŸã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®å‰Šé™¤ + .ToList(); //ソートã«å‘ã‘ã¦ä¸€æ—¦ãƒªã‚¹ãƒˆåŒ– + original_indices.Sort(); //ソート + int[] indices = original_indices.Select(x=>(int)x).ToArray(); + Vector2[] source; + if (0 == morph_type_index) { + //通常UV + source = indices.Select(x=>format_.vertex_list.vertex[x].uv) //インデックスを用ã„ã¦ã€å…ƒãƒ‡ãƒ¼ã‚¿ã‚’パック + .Select(x=>new Vector2(x.x, x.y)) + .ToArray(); + } else { + //追加UV + source = indices.Select(x=>format_.vertex_list.vertex[x].add_uv[morph_type_index - 1]) //インデックスを用ã„ã¦ã€å…ƒãƒ‡ãƒ¼ã‚¿ã‚’パック + .Select(x=>new Vector2(x.x, x.y)) + .ToArray(); + } + + //インデックス逆引ã用辞書ã®ä½œæˆ + Dictionary index_reverse_dictionary = new Dictionary(); + for (uint i = 0, i_max = (uint)indices.Length; i < i_max; ++i) { + index_reverse_dictionary.Add((uint)indices[i], i); + } + + //個別モーフスクリプトã®ä½œæˆ + UvMorph[] script = Enumerable.Range(0, format_.morph_list.morph_data.Length) + .Where(x=>morph_type == format_.morph_list.morph_data[x].morph_type) //該当モーフã«çµžã‚‹ + .Select(x=>AssignUvMorph(morphs[x], format_.morph_list.morph_data[x], index_reverse_dictionary)) + .ToArray(); + + //メッシュ別インデックスã®ä½œæˆ + int invalid_vertex_index = format_.vertex_list.vertex.Length; + MorphManager.UvMorphPack.Meshes[] multi_indices = new MorphManager.UvMorphPack.Meshes[creation_info.Length]; + for (int i = 0, i_max = creation_info.Length; i < i_max; ++i) { + multi_indices[i] = new MorphManager.UvMorphPack.Meshes(); + multi_indices[i].indices = new int[indices.Length]; + for (int k = 0, k_max = indices.Length; k < k_max; ++k) { + if (creation_info[i].reassign_dictionary.ContainsKey((uint)indices[k])) { + //ã“ã®ãƒ¡ãƒƒã‚·ãƒ¥ã§æœ‰åйãªã‚‰ + multi_indices[i].indices[k] = (int)creation_info[i].reassign_dictionary[(uint)indices[k]]; + } else { + //ã“ã®ãƒ¡ãƒƒã‚·ãƒ¥ã§ã¯ç„¡åйãªã‚‰ + multi_indices[i].indices[k] = invalid_vertex_index; //最大頂点数を設定(uint.MaxValueã§ã¯ç„¡ã„ã®ã§æ³¨æ„) + } + } + } + + //表情マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã«ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãƒ»å…ƒãƒ‡ãƒ¼ã‚¿ãƒ»ã‚¹ã‚¯ãƒªãƒ—トã®è¨­å®š + morph_manager.uv_morph[morph_type_index] = new MorphManager.UvMorphPack(multi_indices, source, script); + } + } + + /// + /// UV・追加UVモーフ設定 + /// + /// UVモーフスクリプト + /// モーフã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// PMX用モーフデータ + /// インデックス逆引ã用辞書 + UvMorph AssignUvMorph(GameObject morph, PMXFormat.MorphData data, Dictionary index_reverse_dictionary) + { + UvMorph result = morph.AddComponent(); + result.panel = (MorphManager.PanelType)data.handle_panel; + result.indices = data.morph_offset.Select(x=>((PMXFormat.UVMorphOffset)x).vertex_index) //インデックスをå–り出㗠+ .Select(x=>(int)index_reverse_dictionary[x]) //逆変æ›ã‚’掛ã‘ã‚‹ + .ToArray(); + result.values = data.morph_offset.Select(x=>((PMXFormat.UVMorphOffset)x).uv_offset) + .Select(x=>new Vector2(x.x, x.y)) + .ToArray(); + return result; + } + + /// + /// æè³ªãƒ¢ãƒ¼ãƒ•ä½œæˆ + /// + /// 表情マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ + /// モーフã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// ãƒ¡ãƒƒã‚·ãƒ¥ä½œæˆæƒ…å ± + void CreateMaterialMorph(MorphManager morph_manager, GameObject[] morphs, MeshCreationInfo[] creation_info) + { + //インデックスã¨å…ƒãƒ‡ãƒ¼ã‚¿ã®ä½œæˆ + List original_indices = format_.morph_list.morph_data.Where(x=>(PMXFormat.MorphData.MorphType.Material == x.morph_type)) //該当モーフã«çµžã‚‹ + .SelectMany(x=>x.morph_offset.Select(y=>((PMXFormat.MaterialMorphOffset)y).material_index)) //インデックスã®å–り出ã—ã¨é€£çµ + .Distinct() //é‡è¤‡ã—ãŸã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®å‰Šé™¤ + .ToList(); //ソートã«å‘ã‘ã¦ä¸€æ—¦ãƒªã‚¹ãƒˆåŒ– + original_indices.Sort(); //ソート + if (uint.MaxValue == original_indices.LastOrDefault()) { + //最後㌠uint.MaxValue(≒-1) ãªã‚‰ + //å…¨æè³ªå¯¾è±¡ãŒå­˜åœ¨ã™ã‚‹ã®ã§å…¨ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’å–å¾— + original_indices = Enumerable.Range(0, format_.material_list.material.Length + 1).Select(x=>(uint)x).ToList(); + original_indices[format_.material_list.material.Length] = uint.MaxValue; //uint.MaxValueを忘れãªã„ + } + int[] indices = original_indices.Select(x=>(int)x).ToArray(); + MaterialMorph.MaterialMorphParameter[] source = indices.Where(x=>x{ //インデックスを用ã„ã¦ã€å…ƒãƒ‡ãƒ¼ã‚¿ã‚’パック + MaterialMorph.MaterialMorphParameter result = new MaterialMorph.MaterialMorphParameter(); + if (0 <= x) { + //-1(å…¨æè³ªå¯¾è±¡)ã§ç„¡ã„ãªã‚‰ + //元データをå–å¾— + PMXFormat.Material y = format_.material_list.material[x]; + result.color = y.diffuse_color; + result.specular = new Color(y.specular_color.r, y.specular_color.g, y.specular_color.b, y.specularity); + result.ambient = y.ambient_color; + result.outline_color = y.edge_color; + result.outline_width = y.edge_size; + result.texture_color = Color.white; + result.sphere_color = Color.white; + result.toon_color = Color.white; + } else { + //-1(å…¨æè³ªå¯¾è±¡)ãªã‚‰ + //é©å½“ã«ã§ã£ã¡ä¸Šã’ã‚‹ + result = MaterialMorph.MaterialMorphParameter.zero; + } + return result; + }) + .ToArray(); + + //インデックス逆引ã用辞書ã®ä½œæˆ + Dictionary index_reverse_dictionary = new Dictionary(); + for (uint i = 0, i_max = (uint)indices.Length; i < i_max; ++i) { + index_reverse_dictionary.Add((uint)indices[i], i); + } + + //個別モーフスクリプトã®ä½œæˆ + MaterialMorph[] script = Enumerable.Range(0, format_.morph_list.morph_data.Length) + .Where(x=>PMXFormat.MorphData.MorphType.Material == format_.morph_list.morph_data[x].morph_type) //該当モーフã«çµžã‚‹ + .Select(x=>AssignMaterialMorph(morphs[x], format_.morph_list.morph_data[x], index_reverse_dictionary)) + .ToArray(); + + //æè³ªãƒªã‚¢ã‚µã‚¤ãƒ³è¾žæ›¸ã®ä½œæˆ + Dictionary[] material_reassign_dictionary = new Dictionary[creation_info.Length + 1]; + for (int i = 0, i_max = creation_info.Length; i < i_max; ++i) { + material_reassign_dictionary[i] = new Dictionary(); + for (uint k = 0, k_max = (uint)creation_info[i].value.Length; k < k_max; ++k) { + material_reassign_dictionary[i][creation_info[i].value[k].material_index] = k; + } + if (-1 == indices.LastOrDefault()) { + //indices ã®æœ€å¾ŒãŒ -1(≒uint.MaxValue) ãªã‚‰ + //å…¨æè³ªå¯¾è±¡ãŒå­˜åœ¨ã™ã‚‹ã®ã§æè³ªãƒªã‚¢ã‚µã‚¤ãƒ³è¾žæ›¸ã«è¿½åŠ  + material_reassign_dictionary[i][uint.MaxValue] = uint.MaxValue; + } + } + + //メッシュ別インデックスã®ä½œæˆ + int invalid_material_index = format_.material_list.material.Length; + MorphManager.MaterialMorphPack.Meshes[] multi_indices = new MorphManager.MaterialMorphPack.Meshes[creation_info.Length]; + for (int i = 0, i_max = creation_info.Length; i < i_max; ++i) { + multi_indices[i] = new MorphManager.MaterialMorphPack.Meshes(); + multi_indices[i].indices = new int[indices.Length]; + for (int k = 0, k_max = indices.Length; k < k_max; ++k) { + if (material_reassign_dictionary[i].ContainsKey((uint)indices[k])) { + //ã“ã®æè³ªã§æœ‰åйãªã‚‰ + multi_indices[i].indices[k] = (int)material_reassign_dictionary[i][(uint)indices[k]]; + } else { + //ã“ã®æè³ªã§ã¯ç„¡åйãªã‚‰ + multi_indices[i].indices[k] = invalid_material_index; //最大æè³ªæ•°ã‚’設定(uint.MaxValueã§ã¯ç„¡ã„ã®ã§æ³¨æ„) + } + } + } + + //表情マãƒãƒ¼ã‚¸ãƒ£ãƒ¼ã«ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ãƒ»å…ƒãƒ‡ãƒ¼ã‚¿ãƒ»ã‚¹ã‚¯ãƒªãƒ—トã®è¨­å®š + morph_manager.material_morph = new MorphManager.MaterialMorphPack(multi_indices, source, script); + } + + /// + /// æè³ªãƒ¢ãƒ¼ãƒ•設定 + /// + /// æè³ªãƒ¢ãƒ¼ãƒ•スクリプト + /// モーフã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// PMX用モーフデータ + /// インデックス逆引ã用辞書 + MaterialMorph AssignMaterialMorph(GameObject morph, PMXFormat.MorphData data, Dictionary index_reverse_dictionary) + { + MaterialMorph result = morph.AddComponent(); + result.panel = (MorphManager.PanelType)data.handle_panel; + result.indices = data.morph_offset.Select(x=>((PMXFormat.MaterialMorphOffset)x).material_index) //インデックスをå–り出㗠+ .Select(x=>(int)index_reverse_dictionary[x]) //逆変æ›ã‚’掛ã‘ã‚‹ + .ToArray(); + result.values = data.morph_offset.Select(x=>{ + PMXFormat.MaterialMorphOffset y = (PMXFormat.MaterialMorphOffset)x; + MaterialMorph.MaterialMorphParameter param = new MaterialMorph.MaterialMorphParameter(); + param.color = y.diffuse; + param.specular = new Color(y.specular.r, y.specular.g, y.specular.b, y.specularity); + param.ambient = y.ambient; + param.outline_color = y.edge_color; + param.outline_width = y.edge_size; + param.texture_color = y.texture_coefficient; + param.sphere_color = y.sphere_texture_coefficient; + param.toon_color = y.toon_texture_coefficient; + return param; + }) + .ToArray(); + result.operation = data.morph_offset.Select(x=>(MaterialMorph.OperationType)((PMXFormat.MaterialMorphOffset)x).offset_method) + .ToArray(); + return result; + } + + /// + /// ãƒã‚¤ãƒ³ãƒ‰ãƒãƒ¼ã‚ºã®ä½œæˆ + /// + /// レンダラー + /// 対象メッシュ + /// 設定ã™ã‚‹ãƒžãƒ†ãƒªã‚¢ãƒ« + /// 設定ã™ã‚‹ãƒœãƒ¼ãƒ³ + SkinnedMeshRenderer[] BuildingBindpose(Mesh[] mesh, Material[][] materials, GameObject[] bones) + { + // メッシュルートを生æˆã—ã¦ãƒ«ãƒ¼ãƒˆã®å­ä¾›ã«ä»˜ã‘ã‚‹ + Transform mesh_root_transform = (new GameObject("Mesh")).transform; + mesh_root_transform.parent = root_game_object_.transform; + + //モデルルートå–å¾— + Transform model_root_transform = root_game_object_.transform.Find("Model"); + //ボーン共通データ + Matrix4x4[] bindposes = bones.Select(x=>x.transform.worldToLocalMatrix).ToArray(); + Transform[] bones_transform = bones.Select(x=>x.transform).ToArray(); + + //レンダー設定 + SkinnedMeshRenderer[] result = new SkinnedMeshRenderer[mesh.Length]; + for (int i = 0, i_max = mesh.Length; i < i_max; ++i) { + Transform mesh_transform = (new GameObject("Mesh" + i.ToString())).transform; + mesh_transform.parent = mesh_root_transform; + SkinnedMeshRenderer smr = mesh_transform.gameObject.AddComponent(); + mesh[i].bindposes = bindposes; + smr.sharedMesh = mesh[i]; + smr.bones = bones_transform; + smr.materials = materials[i]; + smr.rootBone = model_root_transform; + smr.receiveShadows = false; //影をå—ã‘ãªã„ + + result[i] = smr; + } + return result; + } + + /// + /// IKä½œæˆ + /// + /// ボーンコントローラースクリプト + /// ボーンã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + BoneController[] EntryBoneController(GameObject[] bones) + { + //BoneControllerãŒä»–ã®BoneControllerã‚’å‚ç…§ã™ã‚‹ã®ã§å…ˆã«å…¨ãƒœãƒ¼ãƒ³ã«ä»˜ä¸Ž + foreach (var bone in bones) { + bone.AddComponent(); + } + BoneController[] result = Enumerable.Range(0, format_.bone_list.bone.Length) + .OrderBy(x=>(int)(PMXFormat.Bone.Flag.PhysicsTransform & format_.bone_list.bone[x].bone_flag)) //物ç†å¾Œå¤‰å½¢ã‚’後方㸠+ .ThenBy(x=>format_.bone_list.bone[x].transform_level) //変形階層ã§å®‰å®šã‚½ãƒ¼ãƒˆ + .Select(x=>ConvertBoneController(format_.bone_list.bone[x], x, bones)) //ConvertIk()を呼ã³å‡ºã™ + .ToArray(); + return result; + } + + /// + /// ボーンをボーンコントローラースクリプトã«å¤‰æ›ã™ã‚‹ + /// + /// ボーンコントローラースクリプト + /// PMX用ボーンデータ + /// 該当IKデータã®ãƒœãƒ¼ãƒ³é€šã—インデックス + /// ボーンã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + BoneController ConvertBoneController(PMXFormat.Bone bone, int bone_index, GameObject[] bones) + { + BoneController result = bones[bone_index].GetComponent(); + if (0.0f != bone.additional_rate) { + //ä»˜ä¸Žè¦ªãŒæœ‰ã‚‹ãªã‚‰ + result.additive_parent = bones[bone.additional_parent_index].GetComponent(); + result.additive_rate = bone.additional_rate; + result.add_local = (0 != (PMXFormat.Bone.Flag.AddLocal & bone.bone_flag)); + result.add_move = (0 != (PMXFormat.Bone.Flag.AddMove & bone.bone_flag)); + result.add_rotate = (0 != (PMXFormat.Bone.Flag.AddRotation & bone.bone_flag)); + } + if (use_ik_) { + //IKを使用ã™ã‚‹ãªã‚‰ + if (0 != (PMXFormat.Bone.Flag.IkFlag & bone.bone_flag)) { + //IKãŒæœ‰ã‚‹ãªã‚‰ + result.ik_solver = bones[bone_index].AddComponent(); + result.ik_solver.target = bones[bone.ik_data.ik_bone_index].transform; + result.ik_solver.controll_weight = bone.ik_data.limit_angle / 4; //HACK: CCDIKSolverå´ã§4å€ã—ã¦ã„る様ãªã®ã§æ­¤å‡¦ã§é€†è£œæ­£ + result.ik_solver.iterations = (int)bone.ik_data.iterations; + result.ik_solver.chains = bone.ik_data.ik_link.Select(x=>x.target_bone_index).Select(x=>bones[x].transform).ToArray(); + //IK制御下ã®BoneController登録 + result.ik_solver_targets = Enumerable.Repeat(result.ik_solver.target, 1) + .Concat(result.ik_solver.chains) + .Select(x=>x.GetComponent()) + .ToArray(); + + //IK制御先ã®ãƒœãƒ¼ãƒ³ã«ã¤ã„ã¦ã€ç‰©ç†æ¼”ç®—ã®æŒ™å‹•を調ã¹ã‚‹ + var operation_types = Enumerable.Repeat(bone.ik_data.ik_bone_index, 1) //IK対象先をEnumerable化 + .Concat(bone.ik_data.ik_link.Select(x=>x.target_bone_index)) //IK制御下を追加 + .Join(format_.rigidbody_list.rigidbody, x=>x, y=>y.rel_bone_index, (x,y)=>y.operation_type); //剛体リストã‹ã‚‰é–¢é€£ãƒœãƒ¼ãƒ³ã«IK対象先・IK制御下ã¨åŒã˜ãƒœãƒ¼ãƒ³ã‚’æŒã¤ç‰©ã‚’列挙ã—ã€å‰›ä½“タイプを返㙠+ foreach (var operation_type in operation_types) { + if (PMXFormat.Rigidbody.OperationType.Static != operation_type) { + //ボーン追従ã§ç„¡ã„(â‰’ç‰©ç†æ¼”ç®—)ãªã‚‰ + //IK制御ã®ç„¡åŠ¹åŒ– + result.ik_solver.enabled = false; + break; + } + } + } + } + return result; + } + + /// + /// å‰›ä½“ä½œæˆ + /// + /// 剛体 + GameObject[] CreateRigids() + { + if (!System.IO.Directory.Exists(System.IO.Path.Combine(format_.meta_header.folder, "Physics"))) { + AssetDatabase.CreateFolder(format_.meta_header.folder, "Physics"); + } + + // 剛体ã®ç™»éŒ² + GameObject[] result = format_.rigidbody_list.rigidbody.Select(x=>ConvertRigidbody(x)).ToArray(); + for (uint i = 0, i_max = (uint)result.Length; i < i_max; ++i) { + // マテリアルã®è¨­å®š + result[i].GetComponent().material = CreatePhysicMaterial(format_.rigidbody_list.rigidbody, i); + + } + + return result; + } + + /// + /// 剛体をUnity用ã«å¤‰æ›ã™ã‚‹ + /// + /// Unity用剛体ゲームオブジェクト + /// PMX用剛体データ + GameObject ConvertRigidbody(PMXFormat.Rigidbody rigidbody) + { + GameObject result = new GameObject("r_" + rigidbody.name); + //result.AddComponent(); // 1ã¤ã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクトã«è¤‡æ•°ã®å‰›ä½“ãŒä»˜ãäº‹ãŒæœ‰ã‚‹ã®ã§æœ¬ä½“ã«ã¯rigidbodyã‚’é©ç”¨ã—ãªã„ + + //ä½ç½®ãƒ»å›žè»¢ã®è¨­å®š + result.transform.position = rigidbody.collider_position * scale_; + result.transform.rotation = Quaternion.Euler(rigidbody.collider_rotation * Mathf.Rad2Deg); + + // Colliderã®è¨­å®š + switch (rigidbody.shape_type) { + case PMXFormat.Rigidbody.ShapeType.Sphere: + EntrySphereCollider(rigidbody, result); + break; + case PMXFormat.Rigidbody.ShapeType.Box: + EntryBoxCollider(rigidbody, result); + break; + case PMXFormat.Rigidbody.ShapeType.Capsule: + EntryCapsuleCollider(rigidbody, result); + break; + default: + throw new System.ArgumentException(); + } + return result; + } + + /// + /// Sphere Colliderã®è¨­å®š + /// + /// PMX用剛体データ + /// Unity用剛体ゲームオブジェクト + void EntrySphereCollider(PMXFormat.Rigidbody rigidbody, GameObject obj) + { + SphereCollider collider = obj.AddComponent(); + collider.radius = rigidbody.shape_size.x * scale_; + } + + /// + /// Box Colliderã®è¨­å®š + /// + /// PMX用剛体データ + /// Unity用剛体ゲームオブジェクト + void EntryBoxCollider(PMXFormat.Rigidbody rigidbody, GameObject obj) + { + BoxCollider collider = obj.AddComponent(); + collider.size = rigidbody.shape_size * 2.0f * scale_; + } + + /// + /// Capsule Colliderã®è¨­å®š + /// + /// PMX用剛体データ + /// Unity用剛体ゲームオブジェクト + void EntryCapsuleCollider(PMXFormat.Rigidbody rigidbody, GameObject obj) + { + CapsuleCollider collider = obj.AddComponent(); + collider.radius = rigidbody.shape_size.x * scale_; + collider.height = (rigidbody.shape_size.y + rigidbody.shape_size.x * 2.0f) * scale_; + } + + /// + /// 物ç†ç´ æã®ä½œæˆ + /// + /// 物ç†ç´ æ + /// PMX用剛体データ + /// 剛体インデックス + PhysicsMaterial CreatePhysicMaterial(PMXFormat.Rigidbody[] rigidbodys, uint index) + { + PMXFormat.Rigidbody rigidbody = rigidbodys[index]; + PhysicsMaterial material = new PhysicsMaterial(format_.meta_header.name + "_r_" + rigidbody.name); + material.bounciness = rigidbody.recoil; + material.staticFriction = rigidbody.friction; + material.dynamicFriction = rigidbody.friction; + + string name = GetFilePathString(rigidbody.name); + string file_name = format_.meta_header.folder + "/Physics/" + index.ToString() + "_" + name + ".asset"; + AssetDatabase.CreateAsset(material, file_name); + return material; + } + + /// + /// 剛体ã¨ãƒœãƒ¼ãƒ³ã‚’接続ã™ã‚‹ + /// + /// ボーンã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// 剛体ã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + void AssignRigidbodyToBone(GameObject[] bones, GameObject[] rigids) + { + // ç‰©ç†æ¼”算ルートを生æˆã—ã¦ãƒ«ãƒ¼ãƒˆã®å­ä¾›ã«ä»˜ã‘ã‚‹ + Transform physics_root_transform = (new GameObject("Physics", typeof(PhysicsManager))).transform; + physics_root_transform.parent = root_game_object_.transform; + + // å‰›ä½“ã®æ•°ã ã‘回㙠+ for (uint i = 0, i_max = (uint)rigids.Length; i < i_max; ++i) { + // å‰›ä½“ã‚’è¦ªãƒœãƒ¼ãƒ³ã«æ ¼ç´ + uint rel_bone_index = GetRelBoneIndexFromNearbyRigidbody(i); + if (rel_bone_index < bones.Length) { + //親ã¨ç‚ºã‚‹ãƒœãƒ¼ãƒ³ãŒæœ‰ã‚Œã° + //ãれã®å­ã¨ç‚ºã‚‹ + rigids[i].transform.parent = bones[rel_bone_index].transform; + } else { + //親ã¨ç‚ºã‚‹ãƒœãƒ¼ãƒ³ãŒç„¡ã‘れ㰠+ //ç‰©ç†æ¼”算ルートã®å­ã¨ç‚ºã‚‹ + rigids[i].transform.parent = physics_root_transform; + } + } + } + + /// + /// 剛体ã¨ãƒœãƒ¼ãƒ³ã‚’接続ã™ã‚‹ + /// + /// ボーンã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// 剛体ã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + uint GetRelBoneIndexFromNearbyRigidbody(uint rigidbody_index) + { + uint bone_count = (uint)format_.bone_list.bone.Length; + //関連ボーンを探㙠+ uint result = format_.rigidbody_list.rigidbody[rigidbody_index].rel_bone_index; + if (result < bone_count) { + //é–¢é€£ãƒœãƒ¼ãƒ³ãŒæœ‰ã‚Œã° + return result; + } + Debug.Log(string.Format("No matching bone found for rigidbody: {0}", rigidbody_index)); + //ãれã§ã‚‚ç„¡ã‘れ㰠+ //諦ã‚ã‚‹ + result = uint.MaxValue; + return result; + } + + /// + /// 剛体ã®å€¤ã‚’設定ã™ã‚‹ + /// + /// ボーンã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// 剛体ã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + void SetRigidsSettings(GameObject[] bones, GameObject[] rigid) + { + uint bone_count = (uint)format_.bone_list.bone.Length; + for (uint i = 0, i_max = (uint)format_.rigidbody_list.rigidbody.Length; i < i_max; ++i) { + PMXFormat.Rigidbody rigidbody = format_.rigidbody_list.rigidbody[i]; + GameObject target; + if (rigidbody.rel_bone_index < bone_count) { + //é–¢é€£ãƒœãƒ¼ãƒ³ãŒæœ‰ã‚‹ãªã‚‰ + //関連ボーンã«ä»˜ä¸Žã™ã‚‹ + target = bones[rigidbody.rel_bone_index]; + } else { + //関連ボーンãŒç„¡ã„ãªã‚‰ + //剛体ã«ä»˜ä¸Žã™ã‚‹ + target = rigid[i]; + } + UnityRigidbodySetting(rigidbody, target); + } + } + + /// + /// Unityå´ã®Rigidbodyã®è¨­å®šã‚’行ㆠ+ /// + /// PMX用剛体データ + /// 設定対象ã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + void UnityRigidbodySetting(PMXFormat.Rigidbody pmx_rigidbody, GameObject target) + { + Rigidbody rigidbody = target.GetComponent(); + if (null != rigidbody) { + //減衰値ã¯å¹³å‡ã‚’å–ã‚‹ + float totMass = rigidbody.mass + pmx_rigidbody.weight; + rigidbody.linearDamping = (rigidbody.linearDamping * rigidbody.mass + pmx_rigidbody.position_dim * pmx_rigidbody.weight) / totMass; + rigidbody.angularDamping = (rigidbody.angularDamping * rigidbody.mass + pmx_rigidbody.rotation_dim * pmx_rigidbody.weight) / totMass; + //æ—¢ã«RigidbodyãŒä»˜ä¸Žã•れã¦ã„ã‚‹ãªã‚‰ + //質é‡ã¯åˆç®—ã™ã‚‹ + rigidbody.mass = totMass; + } + else { + //ã¾ã RigidbodyãŒä»˜ä¸Žã•れã¦ã„ãªã„ãªã‚‰ + rigidbody = target.AddComponent(); + rigidbody.isKinematic = (PMXFormat.Rigidbody.OperationType.Static == pmx_rigidbody.operation_type); + rigidbody.mass = Mathf.Max(float.Epsilon, pmx_rigidbody.weight); + rigidbody.linearDamping = pmx_rigidbody.position_dim; + rigidbody.angularDamping = pmx_rigidbody.rotation_dim; + } + } + + /// + /// ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆä½œæˆ + /// + /// ジョイントã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// 剛体ã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + GameObject[] CreateJoints(GameObject[] rigids) + { + // ConfigurableJointã®è¨­å®š + GameObject[] joints = SetupConfigurableJoint(rigids); + return joints; + } + + /// + /// ConfigurableJointã®è¨­å®š + /// + /// + /// å…ˆã«è¨­å®šã—ã¦ã‹ã‚‰FixedJointを設定ã™ã‚‹ + /// + /// ジョイントã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + /// 剛体ã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + GameObject[] SetupConfigurableJoint(GameObject[] rigids) + { + List result_list = new List(); + foreach (PMXFormat.Joint joint in format_.rigidbody_joint_list.joint) { + //相互接続ã™ã‚‹å‰›ä½“ã®å–å¾— + Transform transform_a = rigids[joint.rigidbody_a].transform; + Rigidbody rigidbody_a = transform_a.GetComponent(); + if (null == rigidbody_a) { + rigidbody_a = transform_a.parent.GetComponent(); + } + Transform transform_b = rigids[joint.rigidbody_b].transform; + Rigidbody rigidbody_b = transform_b.GetComponent(); + if (null == rigidbody_b) { + rigidbody_b = transform_b.parent.GetComponent(); + } + if (rigidbody_a != rigidbody_b) { + //接続ã™ã‚‹å‰›ä½“ãŒåŒã˜å‰›ä½“を指ã•ãªã„ãªã‚‰ + //(本æ¥ãªã‚‰PMDã®è¨­å®šãŒé–“é•ã£ã¦ã„ãªã„é™ã‚ŠåŒä¸€ã‚’指ã™äº‹ã¯ç„¡ã„) + //ジョイント設定 + ConfigurableJoint config_joint = rigidbody_b.gameObject.AddComponent(); + config_joint.connectedBody = rigidbody_a; + SetAttributeConfigurableJoint(joint, config_joint); + + result_list.Add(config_joint.gameObject); + } + } + return result_list.ToArray(); + } + + /// + /// ConfigurableJointã®å€¤ã‚’設定ã™ã‚‹ + /// + /// PMX用ジョイントデータ + /// Unity用ジョイント + void SetAttributeConfigurableJoint(PMXFormat.Joint joint, ConfigurableJoint conf) + { + SetMotionAngularLock(joint, conf); + SetDrive(joint, conf); + } + + /// + /// ジョイントã«ç§»å‹•・回転制é™ã®ãƒ‘ラメータを設定ã™ã‚‹ + /// + /// PMX用ジョイントデータ + /// Unity用ジョイント + void SetMotionAngularLock(PMXFormat.Joint joint, ConfigurableJoint conf) + { + SoftJointLimit jlim; + + // Motionã®å›ºå®š + if (joint.constrain_pos_lower.x == 0.0f && joint.constrain_pos_upper.x == 0.0f) { + conf.xMotion = ConfigurableJointMotion.Locked; + } else { + conf.xMotion = ConfigurableJointMotion.Limited; + } + + if (joint.constrain_pos_lower.y == 0.0f && joint.constrain_pos_upper.y == 0.0f) { + conf.yMotion = ConfigurableJointMotion.Locked; + } else { + conf.yMotion = ConfigurableJointMotion.Limited; + } + + if (joint.constrain_pos_lower.z == 0.0f && joint.constrain_pos_upper.z == 0.0f) { + conf.zMotion = ConfigurableJointMotion.Locked; + } else { + conf.zMotion = ConfigurableJointMotion.Limited; + } + + // 角度ã®å›ºå®š + if (joint.constrain_rot_lower.x == 0.0f && joint.constrain_rot_upper.x == 0.0f) { + conf.angularXMotion = ConfigurableJointMotion.Locked; + } else { + conf.angularXMotion = ConfigurableJointMotion.Limited; + float hlim = Mathf.Max(-joint.constrain_rot_lower.x, -joint.constrain_rot_upper.x); //回転方å‘ãŒé€†ãªã®ã§è² æ•° + float llim = Mathf.Min(-joint.constrain_rot_lower.x, -joint.constrain_rot_upper.x); + SoftJointLimit jhlim = new SoftJointLimit(); + jhlim.limit = Mathf.Clamp(hlim * Mathf.Rad2Deg, -180.0f, 180.0f); + conf.highAngularXLimit = jhlim; + + SoftJointLimit jllim = new SoftJointLimit(); + jllim.limit = Mathf.Clamp(llim * Mathf.Rad2Deg, -180.0f, 180.0f); + conf.lowAngularXLimit = jllim; + } + + if (joint.constrain_rot_lower.y == 0.0f && joint.constrain_rot_upper.y == 0.0f) { + conf.angularYMotion = ConfigurableJointMotion.Locked; + } else { + // 値ãŒãƒžã‚¤ãƒŠã‚¹ã ã¨ã‚¨ãƒ©ãƒ¼ãŒå‡ºã‚‹ã®ã§æ³¨æ„ + conf.angularYMotion = ConfigurableJointMotion.Limited; + float lim = Mathf.Min(Mathf.Abs(joint.constrain_rot_lower.y), Mathf.Abs(joint.constrain_rot_upper.y));//絶対値ã®å°ã•ã„æ–¹ + jlim = new SoftJointLimit(); + jlim.limit = lim * Mathf.Clamp(Mathf.Rad2Deg, 0.0f, 180.0f); + conf.angularYLimit = jlim; + } + + if (joint.constrain_rot_lower.z == 0f && joint.constrain_rot_upper.z == 0f) { + conf.angularZMotion = ConfigurableJointMotion.Locked; + } else { + conf.angularZMotion = ConfigurableJointMotion.Limited; + float lim = Mathf.Min(Mathf.Abs(-joint.constrain_rot_lower.z), Mathf.Abs(-joint.constrain_rot_upper.z));//絶対値ã®å°ã•ã„æ–¹//回転方å‘ãŒé€†ãªã®ã§è² æ•° + jlim = new SoftJointLimit(); + jlim.limit = Mathf.Clamp(lim * Mathf.Rad2Deg, 0.0f, 180.0f); + conf.angularZLimit = jlim; + } + } + + /// + /// ジョイントã«ã°ã­ãªã©ã®ãƒ‘ラメータを設定ã™ã‚‹ + /// + /// PMX用ジョイントデータ + /// Unity用ジョイント + void SetDrive(PMXFormat.Joint joint, ConfigurableJoint conf) + { + JointDrive drive; + + // Position + if (joint.spring_position.x != 0.0f) { + drive = new JointDrive(); + drive.positionSpring = joint.spring_position.x * scale_; + conf.xDrive = drive; + } + if (joint.spring_position.y != 0.0f) { + drive = new JointDrive(); + drive.positionSpring = joint.spring_position.y * scale_; + conf.yDrive = drive; + } + if (joint.spring_position.z != 0.0f) { + drive = new JointDrive(); + drive.positionSpring = joint.spring_position.z * scale_; + conf.zDrive = drive; + } + + // Angular + if (joint.spring_rotation.x != 0.0f) { + drive = new JointDrive(); + drive.positionSpring = joint.spring_rotation.x; + conf.angularXDrive = drive; + } + if (joint.spring_rotation.y != 0.0f || joint.spring_rotation.z != 0.0f) { + drive = new JointDrive(); + drive.positionSpring = (joint.spring_rotation.y + joint.spring_rotation.z) * 0.5f; + conf.angularYZDrive = drive; + } + + conf.projectionMode = JointProjectionMode.PositionAndRotation; + } + + /// + /// 剛体ã®ã‚°ãƒ­ãƒ¼ãƒãƒ«åº§æ¨™åŒ– + /// + /// ジョイントã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + void GlobalizeRigidbody(GameObject[] joints) + { + Transform physics_root_transform = root_game_object_.transform.Find("Physics"); + PhysicsManager physics_manager = physics_root_transform.gameObject.GetComponent(); + + if ((null != joints) && (0 < joints.Length)) { + // PhysicsManagerã«ç§»å‹•å‰ã®çŠ¶æ…‹ã‚’è¦šãˆã•ã›ã‚‹(å¹¾ã¤ã‹é‡è¤‡ã—ã¦ã„ã‚‹ã®ã§é‡è¤‡ã¯å‰Šé™¤) + physics_manager.connect_bone_list = joints.Select(x=>x.gameObject) + .Distinct() + .Select(x=>new PhysicsManager.ConnectBone(x, x.transform.parent.gameObject)) + .ToArray(); + //isKinematicã§ç„¡ãConfigurableJointã‚’æŒã¤å ´åˆã¯ã‚°ãƒ­ãƒ¼ãƒãƒ«åº§æ¨™åŒ– + foreach (ConfigurableJoint joint in joints.Where(x=>!x.GetComponent().isKinematic) + .Select(x=>x.GetComponent())) { + joint.transform.parent = physics_root_transform; + } + } + } + + /// + /// éžè¡çªå‰›ä½“ã®è¨­å®š + /// + /// éžè¡çªå‰›ä½“ã®ãƒªã‚¹ãƒˆ + /// 剛体ã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + List[] SettingIgnoreRigidGroups(GameObject[] rigids) + { + // éžè¡çªã‚°ãƒ«ãƒ¼ãƒ—用リストã®åˆæœŸåŒ– + const int MaxGroup = 16; // ã‚°ãƒ«ãƒ¼ãƒ—ã®æœ€å¤§æ•° + List[] result = new List[MaxGroup]; + for (int i = 0, i_max = MaxGroup; i < i_max; ++i) { + result[i] = new List(); + } + + // ãれãžã‚Œã®å‰›ä½“ãŒæ‰€å±žã—ã¦ã„ã‚‹éžè¡çªã‚°ãƒ«ãƒ¼ãƒ—を追加ã—ã¦ã„ã + for (int i = 0, i_max = format_.rigidbody_list.rigidbody.Length; i < i_max; ++i) { + result[format_.rigidbody_list.rigidbody[i].group_index].Add(i); + } + return result; + } + + /// + /// グループターゲットã®å–å¾— + /// + /// グループターゲット + /// 剛体ã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクト + int[] GetRigidbodyGroupTargets(GameObject[] rigids) + { + return format_.rigidbody_list.rigidbody.Select(x=>(int)x.ignore_collision_group).ToArray(); + } + + /// + /// ファイルパス文字列ã®å–å¾— + /// + /// ファイルパスã«ä½¿ç”¨å¯èƒ½ãªæ–‡å­—列 + /// ファイルパスã«ä½¿ç”¨ã—ãŸã„文字列 + private static string GetFilePathString(string src) { + return src.Replace('\\', 'ï¼¼') + .Replace('/', 'ï¼') + .Replace(':', ':') + .Replace('*', '*') + .Replace('?', '?') + .Replace('"', 'â€') + .Replace('<', '<') + .Replace('>', '>') + .Replace('|', '|') + .Replace("\n", string.Empty) + .Replace("\r", string.Empty); + } + + const uint c_max_vertex_count_in_mesh = 65535; //meshã«å«ã¾ã‚Œã‚‹æœ€å¤§é ‚点数(Unity3Dçš„ã«ã¯65536è¿„å…¥ã‚‹ã¨æ€ã‚れるãŒã€ushort.MaxValueã¯ç‰¹åˆ¥ãªå€¤ã¨ã—ã¦ä½¿ã†ã®ã§ãã®åˆ†ã‚’除外) + + GameObject root_game_object_; + PMXFormat format_; + bool use_ik_; + float scale_; + AlphaReadableTexture alpha_readable_texture_ = null; + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXLoaderScript.PMD2PMX.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXLoaderScript.PMD2PMX.cs new file mode 100644 index 000000000..cadaaec9d --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXLoaderScript.PMD2PMX.cs @@ -0,0 +1,411 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Linq; +using MMD.PMX; +using MMD.PMD; + +public partial class PMXLoaderScript { + + /// + /// PMXファイルã®ãƒ˜ãƒƒãƒ€ãƒ¼å–å¾— + /// + /// PMDヘッダー + /// ヘッダー + public static PMXFormat.Header PMD2PMX(PMDFormat.Header pmd_header) { + PMXFormat.Header pmx_header = ConvertHeader(pmd_header, null, null); + return pmx_header; + } + + /// + /// PMXファイルã®å–å¾— + /// + /// PMDファイル + /// 内部形å¼ãƒ‡ãƒ¼ã‚¿ + public static PMXFormat PMD2PMX(PMDFormat pmd) { + PMXFormat result = new PMXFormat(); + result.meta_header = CreateMetaHeader(pmd); + result.header = ConvertHeader(pmd.head, pmd.eg_head, pmd); + result.vertex_list = ConvertVertexList(pmd); + result.face_vertex_list = ConvertFaceVertexList(pmd); + result.texture_list = ConvertTextureList(pmd); + result.material_list = ConvertMaterialList(pmd, x=>CreateTextureIndex(ref result.texture_list.texture_file, x)); + result.bone_list = ConvertBoneList(pmd); + result.morph_list = ConvertMorphList(pmd); + result.display_frame_list = ConvertDisplayFrameList(pmd); + result.rigidbody_list = ConvertRigidbodyList(pmd); + result.rigidbody_joint_list = ConvertRigidbodyJointList(pmd); + return result; + } + + /// + /// テクスãƒãƒ£ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹å–得用関数 + /// + /// テクスãƒãƒ£ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ + /// テクスãƒãƒ£ãƒªã‚¹ãƒˆ + /// 検索ã™ã‚‹ãƒ†ã‚¯ã‚¹ãƒãƒ£å + private static uint CreateTextureIndex(ref string[] list, string name) { + uint result = uint.MaxValue; + for (int i = 0, i_max = list.Length; i < i_max; ++i) { + if (name == list[i]) { + //発見ã—ãŸã‚‰ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã‚’返㙠+ result = (uint)i; + break; + } + } + if (uint.MaxValue == result) { + //未発見ãªã‚‰ + //末尾ã«ç™»éŒ²ã—ã¦è¿”ã™ + string[] new_list = new string[list.Length + 1]; + System.Array.Copy(list, new_list, list.Length); + new_list[list.Length] = name; //最後ã«è¿½åŠ  + result = (uint)list.Length; + list = new_list; + } + return result; + } + + private static PMXFormat.MetaHeader CreateMetaHeader(PMDFormat pmd) { + PMXFormat.MetaHeader result = new PMXFormat.MetaHeader(); + result.path = pmd.path; + result.name = pmd.name; + result.folder = pmd.folder; + return result; + } + + private static PMXFormat.Header ConvertHeader(PMDFormat.Header pmd_header, PMDFormat.EnglishHeader pmd_english_header, PMDFormat pmd) { + PMXFormat.Header result = new PMXFormat.Header(); + result.magic = pmd_header.magic; + result.version = pmd_header.version; + + result.dataSize = 0; + result.encodeMethod = PMXFormat.Header.StringCode.Utf16le; + result.additionalUV = 0; + result.vertexIndexSize = PMXFormat.Header.IndexSize.Byte1; + result.textureIndexSize = PMXFormat.Header.IndexSize.Byte1; + result.materialIndexSize = PMXFormat.Header.IndexSize.Byte1; + result.boneIndexSize = PMXFormat.Header.IndexSize.Byte1; + result.morphIndexSize = PMXFormat.Header.IndexSize.Byte1; + result.rigidbodyIndexSize = PMXFormat.Header.IndexSize.Byte1; + if (null != pmd) { + result.vertexIndexSize = GetIndexSize(pmd.vertex_list.vertex.Length); + result.textureIndexSize = GetIndexSize(pmd.toon_texture_list.toon_texture_file.Length); + result.materialIndexSize = GetIndexSize(pmd.material_list.material.Length); + result.boneIndexSize = GetIndexSize(pmd.bone_list.bone.Length); + result.morphIndexSize = GetIndexSize(pmd.skin_list.skin_data.Length); + result.rigidbodyIndexSize = GetIndexSize(pmd.rigidbody_list.rigidbody.Length); + } + + result.model_name = pmd_header.model_name; + result.comment = pmd_header.comment; + result.model_english_name = ""; + result.english_comment = ""; + if (null != pmd_english_header) { + result.model_english_name = pmd_english_header.model_name_eg; + result.english_comment = pmd_english_header.comment_eg; + } else if (null != pmd) { + result.model_english_name = pmd.eg_head.model_name_eg; + result.english_comment = pmd.eg_head.comment_eg; + } + return result; + } + + private static PMXFormat.Header.IndexSize GetIndexSize(int size) { + PMXFormat.Header.IndexSize result; + if ((int)ushort.MaxValue <= size) { + result = PMXFormat.Header.IndexSize.Byte4; + } else if ((int)byte.MaxValue <= size) { + result = PMXFormat.Header.IndexSize.Byte2; + } else { + result = PMXFormat.Header.IndexSize.Byte1; + } + return result; + } + + private static PMXFormat.VertexList ConvertVertexList(PMDFormat pmd) { + PMXFormat.VertexList result = new PMXFormat.VertexList(); + result.vertex = pmd.vertex_list.vertex.Select(x=>ConvertVertex(x)).ToArray(); + return result; + } + + private static PMXFormat.Vertex ConvertVertex(PMDFormat.Vertex pmd_vertex) { + PMXFormat.Vertex result = new PMXFormat.Vertex(); + result.pos = pmd_vertex.pos; + result.normal_vec = pmd_vertex.normal_vec; + result.uv = pmd_vertex.uv; + result.add_uv = new Vector4[0]; + if (100 == pmd_vertex.bone_weight) { + //1頂点 + PMXFormat.BDEF1 bone_weight = new PMXFormat.BDEF1(); + bone_weight.bone1_ref = pmd_vertex.bone_num[0]; + result.bone_weight = bone_weight; + } else { + //2頂点 + PMXFormat.BDEF2 bone_weight = new PMXFormat.BDEF2(); + bone_weight.bone1_ref = pmd_vertex.bone_num[0]; + bone_weight.bone2_ref = pmd_vertex.bone_num[1]; + bone_weight.bone1_weight = pmd_vertex.bone_weight / 100.0f; + result.bone_weight = bone_weight; + } + result.edge_magnification = (float)pmd_vertex.edge_flag; + return result; + } + + private static PMXFormat.FaceVertexList ConvertFaceVertexList(PMDFormat pmd) { + PMXFormat.FaceVertexList result = new PMXFormat.FaceVertexList(); + result.face_vert_index = pmd.face_vertex_list.face_vert_index.Select(x=>(uint)x).ToArray(); + return result; + } + + private static PMXFormat.TextureList ConvertTextureList(PMDFormat pmd) { + PMXFormat.TextureList result = new PMXFormat.TextureList(); + result.texture_file = pmd.toon_texture_list.toon_texture_file.ToArray(); //複製ã™ã‚‹ + return result; + } + + private static PMXFormat.MaterialList ConvertMaterialList(PMDFormat pmd, System.Func get_texture_index) { + PMXFormat.MaterialList result = new PMXFormat.MaterialList(); + result.material = new PMXFormat.Material[pmd.material_list.material.Length]; + for (int i = 0; i < result.material.Length; i++) { + result.material[i] = ConvertMaterial(pmd, i, get_texture_index); + } + return result; + } + + private static PMXFormat.Material ConvertMaterial(PMDFormat pmd, int material_index, System.Func get_texture_index) { + PMXFormat.Material result = new PMXFormat.Material(); + PMDFormat.Material pmd_material = pmd.material_list.material[material_index]; + + result.name = "æè³ª_" + material_index.ToString(); + result.english_name = "Material_" + material_index.ToString(); + result.diffuse_color = new Color(pmd_material.diffuse_color.r, pmd_material.diffuse_color.g, pmd_material.diffuse_color.b, pmd_material.alpha); + result.specularity = pmd_material.specularity; + result.specular_color = pmd_material.specular_color; + result.ambient_color = pmd_material.mirror_color; + result.flag = new PMXFormat.Material.Flag(); + if (pmd_material.alpha < 1.0f) { + result.flag |= PMXFormat.Material.Flag.Reversible; + } + if (0 != pmd_material.edge_flag) { + result.flag |= PMXFormat.Material.Flag.Edge | PMXFormat.Material.Flag.CastShadow | PMXFormat.Material.Flag.CastSelfShadow; + } + if (!(0.98f == pmd_material.alpha)) { //æµ®å‹•å°æ•°ç‚¹ã®æ¯”較ã ã‘ã©ã€0.98fã¨ã®åŒå€¤ç¢ºèªã§PMXエディタã®0.98ã¨ä¸€è‡´ã—ãŸã®ã§ä¸€æ—¦ã“れã§ã€‚ + result.flag |= PMXFormat.Material.Flag.ReceiveSelfShadow; + } + result.edge_color = Color.black; + result.edge_size = 1.0f; + result.usually_texture_index = uint.MaxValue; + if (!string.IsNullOrEmpty(pmd_material.texture_file_name)) { + result.usually_texture_index = get_texture_index(pmd_material.texture_file_name); + } + result.sphere_texture_index = uint.MaxValue; + result.sphere_mode = PMXFormat.Material.SphereMode.Null; + if (!string.IsNullOrEmpty(pmd_material.sphere_map_name)) { + result.sphere_texture_index = get_texture_index(pmd_material.sphere_map_name); + switch (System.IO.Path.GetExtension(pmd_material.sphere_map_name)) { + case ".sph": result.sphere_mode = PMXFormat.Material.SphereMode.MulSphere; break; + case ".spa": result.sphere_mode = PMXFormat.Material.SphereMode.AddSphere; break; + default: break; + } + } + result.common_toon = pmd_material.toon_index; + result.toon_texture_index = ((0 < pmd_material.toon_index)? pmd_material.toon_index: uint.MaxValue); + result.memo = ""; + result.face_vert_count = pmd_material.face_vert_count; + return result; + } + + private static PMXFormat.BoneList ConvertBoneList(PMDFormat pmd) { + PMXFormat.BoneList result = new PMXFormat.BoneList(); + result.bone = new PMXFormat.Bone[pmd.bone_list.bone.Length]; + for (int i = 0, i_max = pmd.bone_list.bone.Length; i < i_max; ++i) { + result.bone[i] = ConvertBone(pmd, i); + } + return result; + } + + private static PMXFormat.Bone ConvertBone(PMDFormat pmd, int bone_index) { + PMXFormat.Bone result = new PMXFormat.Bone(); + PMDFormat.Bone pmd_bone = pmd.bone_list.bone[bone_index]; + + result.bone_name = pmd_bone.bone_name; + result.bone_english_name = ((null != pmd.eg_bone_name_list)? pmd.eg_bone_name_list.bone_name_eg[bone_index]: null); + result.bone_position = pmd_bone.bone_head_pos; + result.parent_bone_index = ((ushort.MaxValue == pmd_bone.parent_bone_index)? uint.MaxValue: (uint)pmd_bone.parent_bone_index); + result.transform_level = 0; + switch (pmd_bone.bone_type) { + case 0: //回転 + result.bone_flag = PMXFormat.Bone.Flag.Movable | PMXFormat.Bone.Flag.DisplayFlag | PMXFormat.Bone.Flag.CanOperate; + break; + case 1: //回転ã¨ç§»å‹• + result.bone_flag = PMXFormat.Bone.Flag.Movable | PMXFormat.Bone.Flag.Rotatable | PMXFormat.Bone.Flag.DisplayFlag | PMXFormat.Bone.Flag.CanOperate; + break; + case 2: //IK + result.bone_flag = PMXFormat.Bone.Flag.IkFlag | PMXFormat.Bone.Flag.DisplayFlag | PMXFormat.Bone.Flag.CanOperate; + break; + case 3: //䏿˜Ž + goto default; + case 4: //IK影響下 + goto default; + case 5: //回転影響下 + goto default; //付与親ã«å¤‰æ›ã—ãªã„ã¨ã„ã‘ãªã„ã®ã‹ã‚‚ + case 6: //IK接続先 + goto default; + case 7: //éžè¡¨ç¤º + goto default; + case 8: //æ»ã‚Š + goto default; + case 9: //回転é‹å‹• + goto default; + default: + result.bone_flag = new PMXFormat.Bone.Flag(); + break; + } + result.position_offset = Vector3.zero; + result.connection_index = 0; + result.additional_parent_index = 0; + result.additional_rate = 0.0f; + result.axis_vector = Vector3.zero; + result.x_axis_vector = Vector3.zero; + result.z_axis_vector = Vector3.zero; + result.key_value = 0; + result.ik_data = ConvertIKData(pmd.ik_list.ik_data.Where(x=>x.ik_bone_index==bone_index).FirstOrDefault()); + return result; + } + + private static PMXFormat.IK_Data ConvertIKData(PMDFormat.IK pmd_ik) { + PMXFormat.IK_Data result = null; + if (null != pmd_ik) { + result = new PMXFormat.IK_Data(); + result.ik_bone_index = pmd_ik.ik_target_bone_index; + result.iterations = pmd_ik.iterations; + result.limit_angle = pmd_ik.control_weight * 4.0f; //PMXConverterå´ã§4å€ã•れるã®ã§é€†è£œæ­£ + result.ik_link = pmd_ik.ik_child_bone_index.Select(x=>ConvertIKLink(x)).ToArray(); + } + return result; + } + + private static PMXFormat.IK_Link ConvertIKLink(ushort ik_child_bone_index) { + PMXFormat.IK_Link result = new PMXFormat.IK_Link(); + result.target_bone_index = ik_child_bone_index; + return result; + } + + private static PMXFormat.MorphList ConvertMorphList(PMDFormat pmd) { + PMXFormat.MorphList result = new PMXFormat.MorphList(); + //頂点インデックス用辞書ã®ä½œæˆ + PMDFormat.SkinData pmd_skin_data_base = pmd.skin_list.skin_data.Where(x=>0==x.skin_type).First(); + Dictionary morph_vertex_index_dictionary = new Dictionary(pmd_skin_data_base.skin_vert_data.Length); + for (uint i = 0, i_max = (uint)pmd_skin_data_base.skin_vert_data.Length; i < i_max; ++i) { + morph_vertex_index_dictionary.Add(i, pmd_skin_data_base.skin_vert_data[i].skin_vert_index); + } + //base以外ã®å¤‰æ› + result.morph_data = new PMXFormat.MorphData[pmd.skin_list.skin_data.Where(x=>0!=x.skin_type).Count()]; //base分を除外 + int morph_data_count = 0; + for (int i = 0, i_max = pmd.skin_list.skin_data.Length; i < i_max; ++i) { + if (0 != pmd.skin_list.skin_data[i].skin_type) { + //base以外ãªã‚‰ + string eg_skin_name = (((null != pmd.eg_skin_name_list) && (1 <= i))? pmd.eg_skin_name_list.skin_name_eg[i - 1]: null); + result.morph_data[morph_data_count++] = ConvertMorphData(pmd.skin_list.skin_data[i], eg_skin_name, morph_vertex_index_dictionary); + } + } + return result; + } + + private static PMXFormat.MorphData ConvertMorphData(PMDFormat.SkinData pmd_skin, string pmd_eg_skin_name, Dictionary morph_vertex_index_dictionary) { + PMXFormat.MorphData result = new PMXFormat.MorphData(); + result.morph_name = pmd_skin.skin_name; + result.morph_english_name = pmd_eg_skin_name; + result.handle_panel = (PMXFormat.MorphData.Panel)pmd_skin.skin_type; + result.morph_type = PMXFormat.MorphData.MorphType.Vertex; + result.morph_offset = pmd_skin.skin_vert_data.Select(x=>ConvertVertexMorphOffset(x, morph_vertex_index_dictionary)).ToArray(); + return result; + } + + private static PMXFormat.VertexMorphOffset ConvertVertexMorphOffset(PMDFormat.SkinVertexData pmd_skin_vertex_data, Dictionary morph_vertex_index_dictionary) { + PMXFormat.VertexMorphOffset result = new PMXFormat.VertexMorphOffset(); + result.vertex_index = morph_vertex_index_dictionary[pmd_skin_vertex_data.skin_vert_index]; + result.position_offset = pmd_skin_vertex_data.skin_vert_pos; + return result; + } + + private static PMXFormat.DisplayFrameList ConvertDisplayFrameList(PMDFormat pmd) { + PMXFormat.DisplayFrameList result = new PMXFormat.DisplayFrameList(); + result.display_frame = new PMXFormat.DisplayFrame[pmd.bone_display_list.bone_disp.Length]; + for (int i = 0, i_max = result.display_frame.Length; i < i_max; ++i) { + result.display_frame[i] = ConvertDisplayFrame(pmd, i); + } + return result; + } + + private static PMXFormat.DisplayFrame ConvertDisplayFrame(PMDFormat pmd, int bone_display_index) { + PMXFormat.DisplayFrame result = new PMXFormat.DisplayFrame(); + PMDFormat.BoneDisplay pmd_bone_display = pmd.bone_display_list.bone_disp[bone_display_index]; + result.display_name = pmd.bone_name_list.disp_name[pmd_bone_display.bone_disp_frame_index - 1]; + result.display_english_name = ((null != pmd.eg_bone_display_list)? pmd.eg_bone_display_list.disp_name_eg[pmd_bone_display.bone_disp_frame_index - 1]: null); + result.special_frame_flag = new byte(); + result.display_element = new []{new PMXFormat.DisplayElement()}; + result.display_element[0].element_target = pmd_bone_display.bone_disp_frame_index; + result.display_element[0].element_target_index = pmd_bone_display.bone_index; + return result; + } + + private static PMXFormat.RigidbodyList ConvertRigidbodyList(PMDFormat pmd) { + PMXFormat.RigidbodyList result = new PMXFormat.RigidbodyList(); + result.rigidbody = new PMXFormat.Rigidbody[pmd.rigidbody_list.rigidbody.Length]; + for (int i = 0, i_max = result.rigidbody.Length; i < i_max; ++i) { + result.rigidbody[i] = ConvertRigidbody(pmd, i); + } + return result; + } + + private static PMXFormat.Rigidbody ConvertRigidbody(PMDFormat pmd, int rigidbody_index) { + PMXFormat.Rigidbody result = new PMXFormat.Rigidbody(); + PMDFormat.Rigidbody pmd_rigidbody = pmd.rigidbody_list.rigidbody[rigidbody_index]; + result.name = pmd_rigidbody.rigidbody_name; + result.english_name = ""; + result.rel_bone_index = (uint)pmd_rigidbody.rigidbody_rel_bone_index; + result.group_index = pmd_rigidbody.rigidbody_group_index; + result.ignore_collision_group = pmd_rigidbody.rigidbody_group_target; + result.shape_type = (PMXFormat.Rigidbody.ShapeType)pmd_rigidbody.shape_type; + result.shape_size = new Vector3(pmd_rigidbody.shape_w, pmd_rigidbody.shape_h, pmd_rigidbody.shape_d); + result.collider_position = pmd_rigidbody.pos_pos; + if (pmd_rigidbody.rigidbody_rel_bone_index < pmd.bone_list.bone.Length) { + result.collider_position += pmd.bone_list.bone[pmd_rigidbody.rigidbody_rel_bone_index].bone_head_pos; + } else { + result.collider_position += pmd.bone_list.bone[0].bone_head_pos; + } + result.collider_rotation = pmd_rigidbody.pos_rot; + result.weight = pmd_rigidbody.rigidbody_weight; + result.position_dim = pmd_rigidbody.rigidbody_pos_dim; + result.rotation_dim = pmd_rigidbody.rigidbody_rot_dim; + result.recoil = pmd_rigidbody.rigidbody_recoil; + result.friction = pmd_rigidbody.rigidbody_friction; + result.operation_type = (PMXFormat.Rigidbody.OperationType)pmd_rigidbody.rigidbody_type; + return result; + } + + private static PMXFormat.RigidbodyJointList ConvertRigidbodyJointList(PMDFormat pmx) { + PMXFormat.RigidbodyJointList result = new PMXFormat.RigidbodyJointList(); + result.joint = pmx.rigidbody_joint_list.joint.Select(x=>ConvertJoint(x)).ToArray(); + return result; + } + + private static PMXFormat.Joint ConvertJoint(PMDFormat.Joint pmd_joint) { + PMXFormat.Joint result = new PMXFormat.Joint(); + result.name = pmd_joint.joint_name; + result.english_name = ""; + result.operation_type = PMXFormat.Joint.OperationType.Spring6DOF; + result.rigidbody_a = pmd_joint.joint_rigidbody_a; + result.rigidbody_b = pmd_joint.joint_rigidbody_b; + result.position = pmd_joint.joint_pos; + result.rotation = pmd_joint.joint_rot; + result.constrain_pos_lower = pmd_joint.constrain_pos_1; + result.constrain_pos_upper = pmd_joint.constrain_pos_2; + result.constrain_rot_lower = pmd_joint.constrain_rot_1; + result.constrain_rot_upper = pmd_joint.constrain_rot_2; + result.spring_position = pmd_joint.spring_pos; + result.spring_rotation = pmd_joint.spring_rot; + return result; + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXLoaderScript.PMX2PMD.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXLoaderScript.PMX2PMD.cs new file mode 100644 index 000000000..eadba1191 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXLoaderScript.PMX2PMD.cs @@ -0,0 +1,453 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Linq; +using MMD.PMX; +using MMD.PMD; + +public partial class PMXLoaderScript { + + /// + /// PMDファイルã®ãƒ˜ãƒƒãƒ€ãƒ¼å–å¾— + /// + /// PMXヘッダー + /// ヘッダー + public static PMDFormat.Header PMX2PMD(PMXFormat.Header pmx_header) { + PMDFormat.Header pmd_header = ConvertHeader(pmx_header); + return pmd_header; + } + + /// + /// PMDファイルã®å–å¾— + /// + /// PMXファイル + /// 内部形å¼ãƒ‡ãƒ¼ã‚¿ + public static PMDFormat PMX2PMD(PMXFormat pmx) { + PMDFormat result = new PMDFormat(); + ConvertPathes(result, pmx); + result.head = ConvertHeader(pmx.header); + result.vertex_list = ConvertVertexList(pmx); + result.face_vertex_list = ConvertFaceVertexList(pmx); + result.material_list = ConvertMaterialList(pmx); + result.bone_list = ConvertBoneList(pmx); + result.ik_list = ConvertIKList(pmx); + result.skin_list = ConvertSkinList(pmx); + result.skin_name_list = ConvertSkinNameList(pmx); + result.bone_name_list = ConvertBoneNameList(pmx); + result.bone_display_list = ConvertBoneDisplayList(pmx); + result.eg_head = ConvertEnglishHeader(pmx); + result.eg_bone_name_list = ConvertEnglishBoneNameList(pmx); + result.eg_skin_name_list = ConvertEnglishSkinNameList(pmx); + result.eg_bone_display_list = ConvertEnglishBoneDisplayList(pmx); + result.toon_texture_list = ConvertToonTextureList(pmx); + result.rigidbody_list = ConvertRigidbodyList(pmx); + result.rigidbody_joint_list = ConvertRigidbodyJointList(pmx); + return result; + } + + private static void ConvertPathes(PMDFormat pmd, PMXFormat pmx) { + pmd.path = pmx.meta_header.path; + pmd.name = pmx.meta_header.name; + pmd.folder = pmx.meta_header.folder; + } + + private static PMDFormat.Header ConvertHeader(PMXFormat.Header pmx_header) { + PMDFormat.Header result = new PMDFormat.Header(); + result.magic = pmx_header.magic; + result.version = pmx_header.version; + result.model_name = pmx_header.model_name; + result.comment = pmx_header.comment; + return result; + } + + private static PMDFormat.VertexList ConvertVertexList(PMXFormat pmx) { + PMDFormat.VertexList result = new PMDFormat.VertexList(); + result.vert_count = (uint)pmx.vertex_list.vertex.Length; + result.vertex = new PMDFormat.Vertex[result.vert_count]; + for (int i = 0; i < result.vert_count; i++) { + result.vertex[i] = ConvertVertex(pmx, i); + } + return result; + } + + private static PMDFormat.Vertex ConvertVertex(PMXFormat pmx, int vertex_index) { + PMDFormat.Vertex result = new PMDFormat.Vertex(); + PMXFormat.Vertex pmx_vertex = pmx.vertex_list.vertex[vertex_index]; + result.pos = pmx_vertex.pos; + result.normal_vec = pmx_vertex.normal_vec; + result.uv = pmx_vertex.uv; + switch (pmx_vertex.bone_weight.method) { + case PMXFormat.Vertex.WeightMethod.BDEF1: goto case PMXFormat.Vertex.WeightMethod.BDEF2; + case PMXFormat.Vertex.WeightMethod.BDEF2: + //BDEF1,BDEF2ãªã‚‰ + //å®Œå…¨äº’æ› + result.bone_num = new ushort[]{(ushort)pmx_vertex.bone_weight.bone1_ref, (ushort)pmx_vertex.bone_weight.bone2_ref}; + result.bone_weight = (byte)(pmx_vertex.bone_weight.bone1_weight * 100.0f + 0.5f); + break; + case PMXFormat.Vertex.WeightMethod.BDEF4: + //BDEF4ãªã‚‰ + //ボーン3,4ã®æƒ…報をæ¨ã¦ã‚‹ + result.bone_num = new ushort[]{(ushort)pmx_vertex.bone_weight.bone1_ref, (ushort)pmx_vertex.bone_weight.bone2_ref}; + float bone1_weight = pmx_vertex.bone_weight.bone1_weight / (pmx_vertex.bone_weight.bone1_weight + pmx_vertex.bone_weight.bone2_weight); + result.bone_weight = (byte)(bone1_weight * 100.0f + 0.5f); + break; + case PMXFormat.Vertex.WeightMethod.SDEF: + //SDEFãªã‚‰ + //SDEFã®æƒ…報をæ¨ã¦ã¦BDEF2扱ㄠ+ goto case PMXFormat.Vertex.WeightMethod.BDEF2; + case PMXFormat.Vertex.WeightMethod.QDEF: + //QDEFãªã‚‰ + //BDEF4ã¨åŒã˜å¯¾å¿œ + goto case PMXFormat.Vertex.WeightMethod.BDEF4; + default: + throw new System.ArgumentOutOfRangeException(); + } + result.edge_flag = (byte)((0.5f <= pmx_vertex.edge_magnification)? 1: 0); + return result; + } + + private static PMDFormat.FaceVertexList ConvertFaceVertexList(PMXFormat pmx) { + PMDFormat.FaceVertexList result = new PMDFormat.FaceVertexList(); + result.face_vert_count = (uint)pmx.face_vertex_list.face_vert_index.Length; + result.face_vert_index = pmx.face_vertex_list.face_vert_index.Select(x=>(ushort)x).ToArray(); + return result; + } + + private static PMDFormat.MaterialList ConvertMaterialList(PMXFormat pmx) { + PMDFormat.MaterialList result = new PMDFormat.MaterialList(); + result.material_count = (uint)pmx.material_list.material.Length; + result.material = new PMDFormat.Material[result.material_count]; + for (int i = 0; i < result.material_count; i++) { + result.material[i] = ConvertMaterial(pmx, i); + } + return result; + } + + private static PMDFormat.Material ConvertMaterial(PMXFormat pmx, int material_index) { + PMDFormat.Material result = new PMDFormat.Material(); + PMXFormat.Material pmx_material = pmx.material_list.material[material_index]; + result.diffuse_color = pmx_material.diffuse_color; + result.alpha = result.diffuse_color.a; + result.diffuse_color.a = 1.0f; + result.specularity = pmx_material.specularity; + result.specular_color = pmx_material.specular_color; + result.mirror_color = pmx_material.ambient_color; + if (0 < pmx_material.common_toon) { + //共通トゥーン + string toon_name = "toon" + pmx_material.common_toon.ToString("00") + ".bmp"; + int toon_name_index = -1; + for (int i = 0, i_max = pmx.texture_list.texture_file.Length; i < i_max; ++i) { + if (toon_name == pmx.texture_list.texture_file[i]) { + //既存㮠pmx.texture_list.texture_file ã«æœ‰ã‚Œã° + //使ㆠ+ toon_name_index = i; + break; + } + } + if (toon_name_index < 0) { + //既存㮠pmx.texture_list.texture_file ã«ãªã‘れ㰠+ //後ã‚ã«è¿½åŠ ã™ã‚‹ + string[] texture_file = new string[pmx.texture_list.texture_file.Length + 1]; + System.Array.Copy(pmx.texture_list.texture_file, texture_file, pmx.texture_list.texture_file.Length); + texture_file[pmx.texture_list.texture_file.Length] = toon_name; //最後ã«è¿½åŠ  + toon_name_index = pmx.texture_list.texture_file.Length; + pmx.texture_list.texture_file = texture_file; + } + result.toon_index = (byte)toon_name_index; + } else { + //自å‰ãƒˆã‚¥ãƒ¼ãƒ³ + result.toon_index = (byte)pmx_material.toon_texture_index; + } + result.edge_flag = (byte)((0 != ((int)pmx_material.flag & (int)PMXFormat.Material.Flag.Edge))? 1: 0); + result.face_vert_count = pmx_material.face_vert_count; + if (uint.MaxValue != pmx_material.sphere_texture_index) { + string tex = pmx.texture_list.texture_file[pmx_material.sphere_texture_index]; + result.sphere_map_name = ((0 == tex.IndexOf("./"))? tex.Substring(2): tex); //"./"é–‹å§‹ãªã‚‰é™¤åŽ» +#if MFU_PMX2PMD_SPHERE_MAP_NAME_ADD_EXTENSION_FOR_SPHERE_MODE //スフィアモードã®ç‚ºã«ã€æ‹¡å¼µå­ã‚’付加ã™ã‚‹(ファイルパスãŒå¤‰æ›´ã•れるã®ã§MMDConverterå´ã§2釿‹¡å¼µå­ã«å¯¾å¿œã™ã‚‹è¿„無効化) + switch (pmx_material.sphere_mode) { + case PMXFormat.Material.SphereMode.AddSphere: + result.sphere_map_name += ".spa"; + break; + case PMXFormat.Material.SphereMode.MulSphere: + result.sphere_map_name += ".sph"; + break; + default: + break; + } +#endif + } + if (uint.MaxValue != pmx_material.usually_texture_index) { + string tex = pmx.texture_list.texture_file[pmx_material.usually_texture_index]; + result.texture_file_name = ((0 == tex.IndexOf("./"))? tex.Substring(2): tex); //"./"é–‹å§‹ãªã‚‰é™¤åŽ» + } + return result; + } + + private static PMDFormat.BoneList ConvertBoneList(PMXFormat pmx) { + PMDFormat.BoneList result = new PMDFormat.BoneList(); + result.bone_count = (ushort)pmx.bone_list.bone.Length; + result.bone = new PMDFormat.Bone[result.bone_count]; + for (int i = 0; i < result.bone_count; i++) { + result.bone[i] = ConvertBone(pmx, i); + } + return result; + } + + private static PMDFormat.Bone ConvertBone(PMXFormat pmx, int bone_index) { + PMDFormat.Bone result = new PMDFormat.Bone(); + PMXFormat.Bone pmx_bone = pmx.bone_list.bone[bone_index]; + result.bone_name = pmx_bone.bone_name; + result.parent_bone_index = (ushort)((uint.MaxValue == pmx_bone.parent_bone_index)? ushort.MaxValue: pmx_bone.parent_bone_index); + result.tail_pos_bone_index = ushort.MaxValue; +#if false + //PMDå´ 0:回転 1:回転ã¨ç§»å‹• 2:IK 3:䏿˜Ž 4:IK影響下 5:回転影響下 6:IK接続先 7:éžè¡¨ç¤º 8:æ»ã‚Š 9:回転é‹å‹• + result.bone_type = pmx_bone.bone_flag; + //PMXå´ + public enum Flag { + Connection = 1<< 0, + Rotatable = 1<< 1, + Movable = 1<< 2, + DisplayFlag = 1<< 3, + CanOperate = 1<< 4, + IkFlag = 1<< 5, + AddRotation = 1<< 8, + AddMove = 1<< 9, + FixedAxis = 1<<10, + LocalAxis = 1<<11, + PhysicsTransform = 1<<12, + ExternalParentTransform = 1<<13, + } +#else + result.bone_type = 2; //TODO: ボーンタイプを入れる +#endif + if (null != pmx_bone.ik_data) { + result.ik_parent_bone_index = (ushort)pmx_bone.ik_data.ik_bone_index; + } + result.bone_head_pos = pmx_bone.bone_position; + return result; + } + + private static PMDFormat.IKList ConvertIKList(PMXFormat pmx) { + PMDFormat.IKList result = new PMDFormat.IKList(); + uint index = 0; + result.ik_data = pmx.bone_list.bone.Select(x=>new {data=x, index=index++}) //ボーン通ã—インデックスãŒè¦ã‚‹ã®ã§ãƒ‡ãƒ¼ã‚¿ã¨é€šã—インデックスをパック + .Where(x=>((0 != ((int)PMXFormat.Bone.Flag.IkFlag & (int)x.data.bone_flag)) && (null != x.data.ik_data))) //IkFlagãŒæœ‰åйã§ik_dataデータをæŒã¤ã‚‚ã®ã®ã¿ã«çµžã‚‹ + .Select(x=>ConvertIK(x.data.ik_data, x.index)) //ConvertIK()を呼ã³å‡ºã™ + .ToArray(); + result.ik_data_count = (ushort)result.ik_data.Length; + return result; + } + + private static PMDFormat.IK ConvertIK(PMXFormat.IK_Data pmx_ik_data, uint bone_index) { + PMDFormat.IK result = new PMDFormat.IK(); + result.ik_bone_index = (ushort)bone_index; + result.ik_target_bone_index = (ushort)pmx_ik_data.ik_bone_index; + result.ik_chain_length = (byte)pmx_ik_data.ik_link.Length; + result.iterations = (ushort)pmx_ik_data.iterations; + result.control_weight = pmx_ik_data.limit_angle / 4.0f; //MMDConverterå´ã§4å€ã•れるã®ã§é€†è£œæ­£ + result.ik_child_bone_index = pmx_ik_data.ik_link.Select(x=>(ushort)x.target_bone_index).ToArray(); + return result; + } + + private static PMDFormat.SkinList ConvertSkinList(PMXFormat pmx) { + PMDFormat.SkinList result = new PMDFormat.SkinList(); + result.skin_count = (ushort)pmx.morph_list.morph_data.Length; + result.skin_data = new PMDFormat.SkinData[result.skin_count + 1]; //base分ãŒå«ã¾ã‚Œã¦ã„ãªã„ã®ã§ç¢ºä¿ + //base設定 + PMDFormat.SkinData base_skin = CreateBaseSkinData(pmx); + result.skin_data[0] = base_skin; + //頂点インデックス逆引ã用辞書ã®ä½œæˆ + Dictionary skin_vertex_index_reverse_dictionary = new Dictionary((int)base_skin.skin_vert_count); + for (uint i = 0, i_max = base_skin.skin_vert_count; i < i_max; ++i) { + skin_vertex_index_reverse_dictionary.Add(base_skin.skin_vert_data[i].skin_vert_index, i); + } + //base以外ã®è¨­å®š + for (int i = 0; i < result.skin_count; i++) { + result.skin_data[i + 1] = ConvertSkinData(pmx, i, skin_vertex_index_reverse_dictionary); + } + return result; + } + + private static PMDFormat.SkinData ConvertSkinData(PMXFormat pmx, int skin_index, Dictionary skin_vertex_index_reverse_dictionary) { + PMDFormat.SkinData result = new PMDFormat.SkinData(); + PMXFormat.MorphData pmx_morph = pmx.morph_list.morph_data[skin_index]; + result.skin_name = pmx_morph.morph_name; + result.skin_vert_count = (uint)pmx_morph.morph_offset.Length; + result.skin_type = (byte)pmx_morph.handle_panel; + result.skin_vert_data = new PMDFormat.SkinVertexData[result.skin_vert_count]; + for (int i = 0; i < result.skin_vert_count; i++) { + result.skin_vert_data[i] = ConvertSkinVertexData(pmx, skin_index, i, skin_vertex_index_reverse_dictionary); + } + return result; + } + + private static PMDFormat.SkinVertexData ConvertSkinVertexData(PMXFormat pmx, int skin_index, int skin_vertex_index, Dictionary skin_vertex_index_reverse_dictionary) { + PMDFormat.SkinVertexData result = new PMDFormat.SkinVertexData(); + PMXFormat.MorphData pmx_morph = pmx.morph_list.morph_data[skin_index]; + PMXFormat.MorphOffset pmx_offset = pmx.morph_list.morph_data[skin_index].morph_offset[skin_vertex_index]; + switch (pmx_morph.morph_type) { + case PMXFormat.MorphData.MorphType.Vertex: //頂点変形モーフãªã‚‰ + PMXFormat.VertexMorphOffset vertex_pmx_offset = (PMXFormat.VertexMorphOffset)pmx_offset; + result.skin_vert_index = skin_vertex_index_reverse_dictionary[vertex_pmx_offset.vertex_index]; + result.skin_vert_pos = vertex_pmx_offset.position_offset; + break; + default: //頂点変形モーフ以外ãªã‚‰ + //å…¨ã¦ç„¡åŠ¹åŒ– + result.skin_vert_index = skin_vertex_index_reverse_dictionary.FirstOrDefault().Value; + result.skin_vert_pos = Vector3.zero; + break; + } + return result; + } + + private static PMDFormat.SkinData CreateBaseSkinData(PMXFormat pmx) { + PMDFormat.SkinData result = new PMDFormat.SkinData(); + result.skin_name = "base"; + result.skin_type = (byte)PMXFormat.MorphData.Panel.Base; + var all_vertex_index_list = pmx.morph_list.morph_data.Where(x=>(PMXFormat.MorphData.MorphType.Vertex == x.morph_type)) //頂点変形ボーンã«çµžã‚‹ + .SelectMany(x=>x.morph_offset.Select(y=>((PMXFormat.VertexMorphOffset)y).vertex_index)) //頂点インデックスã®å–り出ã—ã¨é€£çµ + .Distinct() //é‡è¤‡ã—ãŸé ‚点インデックスã®å‰Šé™¤ + .ToList(); //ソートã«å‘ã‘ã¦ä¸€æ—¦ãƒªã‚¹ãƒˆåŒ– + all_vertex_index_list.Sort(); //ソート + result.skin_vert_data = all_vertex_index_list.Select(x=>{ + PMDFormat.SkinVertexData skin_vertex_data = new PMDFormat.SkinVertexData(); + skin_vertex_data.skin_vert_index = x; + skin_vertex_data.skin_vert_pos = pmx.vertex_list.vertex[x].pos; + return skin_vertex_data; + }) //頂点インデックスを用ã„ã¦ã€å…ƒã®é ‚点座標をパック + .ToArray(); + result.skin_vert_count = (uint)result.skin_vert_data.Length; + return result; + } + + private static PMDFormat.SkinNameList ConvertSkinNameList(PMXFormat pmx) { + PMDFormat.SkinNameList result = new PMDFormat.SkinNameList(); + result.skin_disp_count = (byte)pmx.morph_list.morph_data.Length; + result.skin_index = new ushort[result.skin_disp_count]; + for (int i = 0, i_max = result.skin_index.Length; i < i_max; ++i) { + result.skin_index[i] = (ushort)i; + } + return result; + } + + private static PMDFormat.BoneNameList ConvertBoneNameList(PMXFormat pmx) { + PMDFormat.BoneNameList result = new PMDFormat.BoneNameList(); + result.bone_disp_name_count = (byte)pmx.bone_list.bone.Length; + result.disp_name = pmx.bone_list.bone.Select(x=>x.bone_name).ToArray(); + return result; + } + + private static PMDFormat.BoneDisplayList ConvertBoneDisplayList(PMXFormat pmx) { + PMDFormat.BoneDisplayList result = new PMDFormat.BoneDisplayList(); + result.bone_disp_count = (uint)pmx.bone_list.bone.Length; + result.bone_disp = new PMDFormat.BoneDisplay[result.bone_disp_count]; + for (int i = 0; i < result.bone_disp_count; i++) { + result.bone_disp[i] = ConvertBoneDisplay(pmx, i); + } + return result; + } + + private static PMDFormat.BoneDisplay ConvertBoneDisplay(PMXFormat pmx, int bone_index) { + PMDFormat.BoneDisplay result = new PMDFormat.BoneDisplay(); + result.bone_index = (ushort)bone_index; + result.bone_disp_frame_index = (byte)bone_index; + return result; + } + + private static PMDFormat.EnglishHeader ConvertEnglishHeader(PMXFormat pmx) { + PMDFormat.EnglishHeader result = new PMDFormat.EnglishHeader(); + result.english_name_compatibility = 1; + result.model_name_eg = pmx.header.model_english_name; + result.comment_eg = pmx.header.english_comment; + return result; + } + + private static PMDFormat.EnglishBoneNameList ConvertEnglishBoneNameList(PMXFormat pmx) { + PMDFormat.EnglishBoneNameList result = new PMDFormat.EnglishBoneNameList(); + result.bone_name_eg = pmx.bone_list.bone.Select(x=>x.bone_english_name).ToArray(); + return result; + } + + private static PMDFormat.EnglishSkinNameList ConvertEnglishSkinNameList(PMXFormat pmx) { + PMDFormat.EnglishSkinNameList result = new PMDFormat.EnglishSkinNameList(); + result.skin_name_eg = pmx.morph_list.morph_data.Select(x=>x.morph_english_name).ToArray(); + return result; + } + + private static PMDFormat.EnglishBoneDisplayList ConvertEnglishBoneDisplayList(PMXFormat pmx) { + PMDFormat.EnglishBoneDisplayList result = new PMDFormat.EnglishBoneDisplayList(); + result.disp_name_eg = pmx.display_frame_list.display_frame.Select(x=>x.display_english_name).ToArray(); + return result; + } + + private static PMDFormat.ToonTextureList ConvertToonTextureList(PMXFormat pmx) { + PMDFormat.ToonTextureList result = new PMDFormat.ToonTextureList(); + result.toon_texture_file = pmx.texture_list.texture_file.Select(x=>((0 == x.IndexOf("./"))? x.Substring(2): x)) //"./"é–‹å§‹ãªã‚‰é™¤åŽ» + .ToArray(); + return result; + } + + private static PMDFormat.RigidbodyList ConvertRigidbodyList(PMXFormat pmx) { + PMDFormat.RigidbodyList result = new PMDFormat.RigidbodyList(); + result.rigidbody_count = (uint)pmx.rigidbody_list.rigidbody.Length; + result.rigidbody = new PMDFormat.Rigidbody[result.rigidbody_count]; + for (int i = 0; i < result.rigidbody_count; i++) { + result.rigidbody[i] = ConvertRigidbody(pmx, i); + } + return result; + } + + private static PMDFormat.Rigidbody ConvertRigidbody(PMXFormat pmx, int rigidbody_index) { + PMDFormat.Rigidbody result = new PMDFormat.Rigidbody(); + PMXFormat.Rigidbody pmx_rigidbody = pmx.rigidbody_list.rigidbody[rigidbody_index]; + result.rigidbody_name = pmx_rigidbody.name; + result.rigidbody_rel_bone_index = (int)pmx_rigidbody.rel_bone_index; + result.rigidbody_group_index = pmx_rigidbody.group_index; + result.rigidbody_group_target = pmx_rigidbody.ignore_collision_group; + result.shape_type = (byte)pmx_rigidbody.shape_type; + result.shape_w = pmx_rigidbody.shape_size.x; + result.shape_h = pmx_rigidbody.shape_size.y; + result.shape_d = pmx_rigidbody.shape_size.z; + result.pos_pos = pmx_rigidbody.collider_position; + if (pmx_rigidbody.rel_bone_index < pmx.bone_list.bone.Length) { + result.pos_pos -= pmx.bone_list.bone[pmx_rigidbody.rel_bone_index].bone_position; + } else { + result.pos_pos -= pmx.bone_list.bone[0].bone_position; + } + result.pos_rot = pmx_rigidbody.collider_rotation; + result.rigidbody_weight = pmx_rigidbody.weight; + result.rigidbody_pos_dim = pmx_rigidbody.position_dim; + result.rigidbody_rot_dim = pmx_rigidbody.rotation_dim; + result.rigidbody_recoil = pmx_rigidbody.recoil; + result.rigidbody_friction = pmx_rigidbody.friction; + result.rigidbody_type = (byte)pmx_rigidbody.operation_type; + return result; + } + + private static PMDFormat.RigidbodyJointList ConvertRigidbodyJointList(PMXFormat pmx) { + PMDFormat.RigidbodyJointList result = new PMDFormat.RigidbodyJointList(); + result.joint_count = (uint)pmx.rigidbody_joint_list.joint.Length; + result.joint = new PMDFormat.Joint[result.joint_count]; + for (int i = 0; i < result.joint_count; i++) { + result.joint[i] = ConvertJoint(pmx, i); + } + return result; + } + + private static PMDFormat.Joint ConvertJoint(PMXFormat pmx, int joint_index) { + PMDFormat.Joint result = new PMDFormat.Joint(); + PMXFormat.Joint pmx_joint = pmx.rigidbody_joint_list.joint[joint_index]; + result.joint_name = pmx_joint.name; + result.joint_rigidbody_a = pmx_joint.rigidbody_a; + result.joint_rigidbody_b = pmx_joint.rigidbody_b; + result.joint_pos = pmx_joint.position; + result.joint_rot = pmx_joint.rotation; + result.constrain_pos_1 = pmx_joint.constrain_pos_lower; + result.constrain_pos_2 = pmx_joint.constrain_pos_upper; + result.constrain_rot_1 = pmx_joint.constrain_rot_lower; + result.constrain_rot_2 = pmx_joint.constrain_rot_upper; + result.spring_pos = pmx_joint.spring_position; + result.spring_rot = pmx_joint.spring_rotation; + return result; + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXLoaderScript.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXLoaderScript.cs new file mode 100644 index 000000000..10e77ced6 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/PMXLoaderScript.cs @@ -0,0 +1,639 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Text; +using System.IO; +using MMD.PMX; +using MMD.PMD; + +public partial class PMXLoaderScript { + + /// + /// PMXファイルã®ãƒ˜ãƒƒãƒ€ãƒ¼å–å¾— + /// + /// PMDファイルã®ãƒ‘ス + /// ヘッダー + public static PMXFormat.Header GetHeader(string file_path) { + PMXLoaderScript loader = new PMXLoaderScript(); + return loader.GetHeader_(file_path); + } + + /// + /// PMXファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ + /// + /// PMDファイルã®ãƒ‘ス + /// 内部形å¼ãƒ‡ãƒ¼ã‚¿ + public static PMXFormat Import(string file_path) { + PMXLoaderScript loader = new PMXLoaderScript(); + return loader.Import_(file_path); + } + + /// + /// デフォルトコンストラクタ + /// + /// + /// ユーザーã«ä¾ã‚‹ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ä½œæˆã‚’ç¦æ­¢ã™ã‚‹ + /// + private PMXLoaderScript() {} + + private PMXFormat.Header GetHeader_(string file_path) { + PMXFormat.Header result; + using (FileStream stream = new FileStream(file_path, FileMode.Open, FileAccess.Read)) + using (BinaryReader bin = new BinaryReader(stream)) { + file_path_ = null; + binary_reader_ = bin; + result = ReadHeader(); + } + return result; + } + + private PMXFormat Import_(string file_path) { + using (FileStream stream = new FileStream(file_path, FileMode.Open, FileAccess.Read)) + using (BinaryReader bin = new BinaryReader(stream)) { + file_path_ = file_path; + binary_reader_ = bin; + Read(); + } + return format_; + } + + private PMXFormat Read() { + format_ = new PMXFormat(); + format_.meta_header = CreateMetaHeader(); + format_.header = ReadHeader(); + format_.vertex_list = ReadVertexList(); + format_.face_vertex_list = ReadFaceVertexList(); + format_.texture_list = ReadTextureList(); + format_.material_list = ReadMaterialList(); + format_.bone_list = ReadBoneList(); + format_.morph_list = ReadMorphList(); + format_.display_frame_list = ReadDisplayFrameList(); + format_.rigidbody_list = ReadRigidbodyList(); + format_.rigidbody_joint_list = ReadRigidbodyJointList(); + return format_; + } + + private PMXFormat.MetaHeader CreateMetaHeader() { + PMXFormat.MetaHeader result = new PMXFormat.MetaHeader(); + result.path = file_path_; + result.name = Path.GetFileNameWithoutExtension(file_path_); // .pmdを抜ã‹ã™ + result.folder = Path.GetDirectoryName(file_path_); // PMDãŒæ ¼ç´ã•れã¦ã„るフォルダ + return result; + } + + private PMXFormat.Header ReadHeader() { + PMXFormat.Header result = new PMXFormat.Header(); + result.magic = binary_reader_.ReadBytes(4); + if (Encoding.ASCII.GetString(result.magic) != "PMX ") { + throw new System.FormatException(); + } + result.version = binary_reader_.ReadSingle(); + binary_reader_.ReadByte(); // Fixed at 8 for PMX 2.0 + result.encodeMethod = (PMXFormat.Header.StringCode)binary_reader_.ReadByte(); + result.additionalUV = binary_reader_.ReadByte(); + result.vertexIndexSize = (PMXFormat.Header.IndexSize)binary_reader_.ReadByte(); + result.textureIndexSize = (PMXFormat.Header.IndexSize)binary_reader_.ReadByte(); + result.materialIndexSize = (PMXFormat.Header.IndexSize)binary_reader_.ReadByte(); + result.boneIndexSize = (PMXFormat.Header.IndexSize)binary_reader_.ReadByte(); + result.morphIndexSize = (PMXFormat.Header.IndexSize)binary_reader_.ReadByte(); + result.rigidbodyIndexSize = (PMXFormat.Header.IndexSize)binary_reader_.ReadByte(); + + string_code_ = result.encodeMethod; + result.model_name = ReadString(); + result.model_english_name = ReadString(); + result.comment = ReadString(); + result.english_comment = ReadString(); + + return result; + } + + private PMXFormat.VertexList ReadVertexList() { + PMXFormat.VertexList result = new PMXFormat.VertexList(); + uint vert_count = binary_reader_.ReadUInt32(); + result.vertex = new PMXFormat.Vertex[vert_count]; + for (uint i = 0, i_max = (uint)result.vertex.Length; i < i_max; ++i) { + result.vertex[i] = ReadVertex(); + } + return result; + } + + private PMXFormat.Vertex ReadVertex() { + PMXFormat.Vertex result = new PMXFormat.Vertex(); + result.pos = ReadSinglesToVector3(binary_reader_); + result.normal_vec = ReadSinglesToVector3(binary_reader_); + result.uv = ReadSinglesToVector2(binary_reader_); + result.add_uv = new Vector4[format_.header.additionalUV]; + for (int i = 0; i < format_.header.additionalUV; i++) { + result.add_uv[i] = ReadSinglesToVector4(binary_reader_); + } + PMXFormat.Vertex.WeightMethod weight_method = (PMXFormat.Vertex.WeightMethod)binary_reader_.ReadByte(); + switch(weight_method) { + case PMXFormat.Vertex.WeightMethod.BDEF1: + result.bone_weight = ReadBoneWeightBDEF1(); + break; + case PMXFormat.Vertex.WeightMethod.BDEF2: + result.bone_weight = ReadBoneWeightBDEF2(); + break; + case PMXFormat.Vertex.WeightMethod.BDEF4: + result.bone_weight = ReadBoneWeightBDEF4(); + break; + case PMXFormat.Vertex.WeightMethod.SDEF: + result.bone_weight = ReadBoneWeightSDEF(); + break; + case PMXFormat.Vertex.WeightMethod.QDEF: + result.bone_weight = ReadBoneWeightQDEF(); + break; + default: + result.bone_weight = null; + throw new System.FormatException(); + } + result.edge_magnification = binary_reader_.ReadSingle(); + return result; + } + + private PMXFormat.BoneWeight ReadBoneWeightBDEF1() { + PMXFormat.BDEF1 result = new PMXFormat.BDEF1(); + result.bone1_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + return result; + } + private PMXFormat.BoneWeight ReadBoneWeightBDEF2() { + PMXFormat.BDEF2 result = new PMXFormat.BDEF2(); + result.bone1_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.bone2_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.bone1_weight = binary_reader_.ReadSingle(); + return result; + } + private PMXFormat.BoneWeight ReadBoneWeightBDEF4() { + PMXFormat.BDEF4 result = new PMXFormat.BDEF4(); + result.bone1_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.bone2_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.bone3_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.bone4_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.bone1_weight = binary_reader_.ReadSingle(); + result.bone2_weight = binary_reader_.ReadSingle(); + result.bone3_weight = binary_reader_.ReadSingle(); + result.bone4_weight = binary_reader_.ReadSingle(); + return result; + } + private PMXFormat.BoneWeight ReadBoneWeightSDEF() { + PMXFormat.SDEF result = new PMXFormat.SDEF(); + result.bone1_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.bone2_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.bone1_weight = binary_reader_.ReadSingle(); + result.c_value = ReadSinglesToVector3(binary_reader_); + result.r0_value = ReadSinglesToVector3(binary_reader_); + result.r1_value = ReadSinglesToVector3(binary_reader_); + return result; + } + private PMXFormat.BoneWeight ReadBoneWeightQDEF() { + PMXFormat.BDEF4 result = new PMXFormat.BDEF4(); + result.bone1_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.bone2_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.bone3_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.bone4_ref = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.bone1_weight = binary_reader_.ReadSingle(); + result.bone2_weight = binary_reader_.ReadSingle(); + result.bone3_weight = binary_reader_.ReadSingle(); + result.bone4_weight = binary_reader_.ReadSingle(); + return result; + } + + private PMXFormat.FaceVertexList ReadFaceVertexList() { + PMXFormat.FaceVertexList result = new PMXFormat.FaceVertexList(); + uint face_vert_count = binary_reader_.ReadUInt32(); + result.face_vert_index = new uint[face_vert_count]; + for (uint i = 0, i_max = (uint)result.face_vert_index.Length; i < i_max; ++i) { + result.face_vert_index[i] = CastIntRead(binary_reader_, format_.header.vertexIndexSize); + } + return result; + } + + private PMXFormat.TextureList ReadTextureList() { + PMXFormat.TextureList result = new PMXFormat.TextureList(); + uint texture_file_count = binary_reader_.ReadUInt32(); + result.texture_file = new string[texture_file_count]; + for (uint i = 0, i_max = (uint)result.texture_file.Length; i < i_max; ++i) { + result.texture_file[i] = ReadString(); + //"./"é–‹å§‹ãªã‚‰å‰Šé™¤ã™ã‚‹ + if (('.' == result.texture_file[i][0]) && (1 == result.texture_file[i].IndexOfAny(new[]{'/', '\\'}, 1, 1))) { + result.texture_file[i] = result.texture_file[i].Substring(2); + } + } + return result; + } + + private PMXFormat.MaterialList ReadMaterialList() { + PMXFormat.MaterialList result = new PMXFormat.MaterialList(); + uint material_count = binary_reader_.ReadUInt32(); + result.material = new PMXFormat.Material[material_count]; + for (uint i = 0, i_max = (uint)result.material.Length; i < i_max; ++i) { + result.material[i] = ReadMaterial(); + } + return result; + } + + private PMXFormat.Material ReadMaterial() { + PMXFormat.Material result = new PMXFormat.Material(); + result.name = ReadString(); + result.english_name = ReadString(); + result.diffuse_color = ReadSinglesToColor(binary_reader_); // dr, dg, db, da // 減衰色 + result.specular_color = ReadSinglesToColor(binary_reader_, 1); // sr, sg, sb // 光沢色 + result.specularity = binary_reader_.ReadSingle(); + result.ambient_color = ReadSinglesToColor(binary_reader_, 1); // mr, mg, mb // 環境色(ambient) + result.flag = (PMXFormat.Material.Flag)binary_reader_.ReadByte(); + result.edge_color = ReadSinglesToColor(binary_reader_); // r, g, b, a + result.edge_size = binary_reader_.ReadSingle(); + result.usually_texture_index = CastIntRead(binary_reader_, format_.header.textureIndexSize); + result.sphere_texture_index = CastIntRead(binary_reader_, format_.header.textureIndexSize); + result.sphere_mode = (PMXFormat.Material.SphereMode)binary_reader_.ReadByte(); + result.common_toon = binary_reader_.ReadByte(); + PMXFormat.Header.IndexSize texture_index_size = ((result.common_toon == 0)? format_.header.textureIndexSize: PMXFormat.Header.IndexSize.Byte1); + result.toon_texture_index = CastIntRead(binary_reader_, texture_index_size); + result.memo = ReadString(); + result.face_vert_count = binary_reader_.ReadUInt32(); // é¢é ‚点数 // インデックスã«å¤‰æ›ã™ã‚‹å ´åˆã¯ã€æè³ª0ã‹ã‚‰é †ã«åŠ ç®— + return result; + } + + private PMXFormat.BoneList ReadBoneList() { + PMXFormat.BoneList result = new PMXFormat.BoneList(); + uint bone_count = binary_reader_.ReadUInt32(); + result.bone = new PMXFormat.Bone[bone_count]; + for (uint i = 0, i_max = (uint)result.bone.Length; i < i_max; ++i) { + result.bone[i] = ReadBone(); + } + return result; + } + + private PMXFormat.Bone ReadBone() { + PMXFormat.Bone result = new PMXFormat.Bone(); + result.bone_name = ReadString(); + result.bone_english_name = ReadString(); + result.bone_position = ReadSinglesToVector3(binary_reader_); + result.parent_bone_index = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.transform_level = binary_reader_.ReadInt32(); + result.bone_flag = (PMXFormat.Bone.Flag)binary_reader_.ReadUInt16(); + + if ((result.bone_flag & PMXFormat.Bone.Flag.Connection) == 0) { + // åº§æ¨™ã‚ªãƒ•ã‚»ãƒƒãƒˆã§æŒ‡å®š + result.position_offset = ReadSinglesToVector3(binary_reader_); + } else { + // ãƒœãƒ¼ãƒ³ã§æŒ‡å®š + result.connection_index = CastIntRead(binary_reader_, format_.header.boneIndexSize); + } + if ((result.bone_flag & (PMXFormat.Bone.Flag.AddRotation | PMXFormat.Bone.Flag.AddMove)) != 0) { + result.additional_parent_index = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.additional_rate = binary_reader_.ReadSingle(); + } + if ((result.bone_flag & PMXFormat.Bone.Flag.FixedAxis) != 0) { + result.axis_vector = ReadSinglesToVector3(binary_reader_); + } + if ((result.bone_flag & PMXFormat.Bone.Flag.LocalAxis) != 0) { + result.x_axis_vector = ReadSinglesToVector3(binary_reader_); + result.z_axis_vector = ReadSinglesToVector3(binary_reader_); + } + if((result.bone_flag & PMXFormat.Bone.Flag.ExternalParentTransform) != 0) { + result.key_value = binary_reader_.ReadUInt32(); + } + if((result.bone_flag & PMXFormat.Bone.Flag.IkFlag) != 0) { + result.ik_data = ReadIkData(); + } + return result; + } + + private PMXFormat.IK_Data ReadIkData() { + PMXFormat.IK_Data result = new PMXFormat.IK_Data(); + result.ik_bone_index = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.iterations = binary_reader_.ReadUInt32(); + result.limit_angle = binary_reader_.ReadSingle(); + uint ik_link_count = binary_reader_.ReadUInt32(); + result.ik_link = new PMXFormat.IK_Link[ik_link_count]; + for (uint i = 0, i_max = (uint)result.ik_link.Length; i < i_max; ++i) { + result.ik_link[i] = ReadIkLink(); + } + return result; + } + + private PMXFormat.IK_Link ReadIkLink() { + PMXFormat.IK_Link result = new PMXFormat.IK_Link(); + result.target_bone_index = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.angle_limit = binary_reader_.ReadByte(); + if (result.angle_limit == 1) { + result.lower_limit = ReadSinglesToVector3(binary_reader_); + result.upper_limit = ReadSinglesToVector3(binary_reader_); + } + return result; + } + + private PMXFormat.MorphList ReadMorphList() { + PMXFormat.MorphList result = new PMXFormat.MorphList(); + uint morph_count = binary_reader_.ReadUInt32(); + result.morph_data = new PMXFormat.MorphData[morph_count]; + for (uint i = 0, i_max = (uint)result.morph_data.Length; i < i_max; ++i) { + result.morph_data[i] = ReadMorphData(); + } + return result; + } + + private PMXFormat.MorphData ReadMorphData() { + PMXFormat.MorphData result = new PMXFormat.MorphData(); + result.morph_name = ReadString(); + result.morph_english_name = ReadString(); + result.handle_panel = (PMXFormat.MorphData.Panel)binary_reader_.ReadByte(); + result.morph_type = (PMXFormat.MorphData.MorphType)binary_reader_.ReadByte(); + uint morph_offset_count = binary_reader_.ReadUInt32(); + result.morph_offset = new PMXFormat.MorphOffset[morph_offset_count]; + for (uint i = 0, i_max = (uint)result.morph_offset.Length; i < i_max; ++i) { + switch(result.morph_type) { + case PMXFormat.MorphData.MorphType.Group: + case PMXFormat.MorphData.MorphType.Flip: + result.morph_offset[i] = ReadGroupMorphOffset(); + break; + case PMXFormat.MorphData.MorphType.Vertex: + result.morph_offset[i] = ReadVertexMorphOffset(); + break; + case PMXFormat.MorphData.MorphType.Bone: + result.morph_offset[i] = ReadBoneMorphOffset(); + break; + case PMXFormat.MorphData.MorphType.Uv: + case PMXFormat.MorphData.MorphType.Adduv1: + case PMXFormat.MorphData.MorphType.Adduv2: + case PMXFormat.MorphData.MorphType.Adduv3: + case PMXFormat.MorphData.MorphType.Adduv4: + result.morph_offset[i] = ReadUVMorphOffset(); + break; + case PMXFormat.MorphData.MorphType.Material: + result.morph_offset[i] = ReadMaterialMorphOffset(); + break; + case PMXFormat.MorphData.MorphType.Impulse: + result.morph_offset[i] = ReadImpulseMorphOffset(); + break; + default: + throw new System.FormatException(); + } + } + return result; + } + private PMXFormat.MorphOffset ReadGroupMorphOffset() { + PMXFormat.GroupMorphOffset result = new PMXFormat.GroupMorphOffset(); + result.morph_index = CastIntRead(binary_reader_, format_.header.morphIndexSize); + result.morph_rate = binary_reader_.ReadSingle(); + return result; + } + private PMXFormat.MorphOffset ReadVertexMorphOffset() { + PMXFormat.VertexMorphOffset result = new PMXFormat.VertexMorphOffset(); + result.vertex_index = CastIntRead(binary_reader_, format_.header.vertexIndexSize); + result.position_offset = ReadSinglesToVector3(binary_reader_); + return result; + } + private PMXFormat.MorphOffset ReadBoneMorphOffset() { + PMXFormat.BoneMorphOffset result = new PMXFormat.BoneMorphOffset(); + result.bone_index = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.move_value = ReadSinglesToVector3(binary_reader_); + result.rotate_value = ReadSinglesToQuaternion(binary_reader_); + return result; + } + private PMXFormat.MorphOffset ReadUVMorphOffset() { + PMXFormat.UVMorphOffset result = new PMXFormat.UVMorphOffset(); + result.vertex_index = CastIntRead(binary_reader_, format_.header.vertexIndexSize); + result.uv_offset = ReadSinglesToVector4(binary_reader_); + return result; + } + private PMXFormat.MorphOffset ReadMaterialMorphOffset() { + PMXFormat.MaterialMorphOffset result = new PMXFormat.MaterialMorphOffset(); + result.material_index = CastIntRead(binary_reader_, format_.header.materialIndexSize); + result.offset_method = (PMXFormat.MaterialMorphOffset.OffsetMethod)binary_reader_.ReadByte(); + result.diffuse = ReadSinglesToColor(binary_reader_); + result.specular = ReadSinglesToColor(binary_reader_, 1); + result.specularity = binary_reader_.ReadSingle(); + result.ambient = ReadSinglesToColor(binary_reader_, 1); + result.edge_color = ReadSinglesToColor(binary_reader_); + result.edge_size = binary_reader_.ReadSingle(); + result.texture_coefficient = ReadSinglesToColor(binary_reader_); + result.sphere_texture_coefficient = ReadSinglesToColor(binary_reader_); + result.toon_texture_coefficient = ReadSinglesToColor(binary_reader_); + return result; + } + private PMXFormat.MorphOffset ReadImpulseMorphOffset() { + PMXFormat.ImpulseMorphOffset result = new PMXFormat.ImpulseMorphOffset(); + result.rigidbody_index = CastIntRead(binary_reader_, format_.header.morphIndexSize); + result.local_flag = binary_reader_.ReadByte(); + result.move_velocity = ReadSinglesToVector3(binary_reader_); + result.rotation_torque = ReadSinglesToVector3(binary_reader_); + return result; + } + + private PMXFormat.DisplayFrameList ReadDisplayFrameList() { + PMXFormat.DisplayFrameList result = new PMXFormat.DisplayFrameList(); + uint display_frame_count = binary_reader_.ReadUInt32(); + result.display_frame = new PMXFormat.DisplayFrame[display_frame_count]; + for (uint i = 0, i_max = (uint)result.display_frame.Length; i < i_max; ++i) { + result.display_frame[i] = ReadDisplayFrame(); + } + return result; + } + + + private PMXFormat.DisplayFrame ReadDisplayFrame() { + PMXFormat.DisplayFrame result = new PMXFormat.DisplayFrame(); + result.display_name = ReadString(); + result.display_english_name = ReadString(); + result.special_frame_flag = binary_reader_.ReadByte(); + uint display_element_count = binary_reader_.ReadUInt32(); + result.display_element = new PMXFormat.DisplayElement[display_element_count]; + for (uint i = 0, i_max = (uint)result.display_element.Length; i < i_max; ++i) { + result.display_element[i] = ReadDisplayElement(); + } + return result; + } + + private PMXFormat.DisplayElement ReadDisplayElement() { + PMXFormat.DisplayElement result = new PMXFormat.DisplayElement(); + result.element_target = binary_reader_.ReadByte(); + PMXFormat.Header.IndexSize element_target_index_size = ((result.element_target == 0) ? format_.header.boneIndexSize : format_.header.morphIndexSize); + result.element_target_index = CastIntRead(binary_reader_, element_target_index_size); + return result; + } + + private PMXFormat.RigidbodyList ReadRigidbodyList() { + PMXFormat.RigidbodyList result = new PMXFormat.RigidbodyList(); + uint rigidbody_count = binary_reader_.ReadUInt32(); + result.rigidbody = new PMXFormat.Rigidbody[rigidbody_count]; + for (uint i = 0, i_max = (uint)result.rigidbody.Length; i < i_max; ++i) { + result.rigidbody[i] = ReadRigidbody(); + } + return result; + } + + private PMXFormat.Rigidbody ReadRigidbody() { + PMXFormat.Rigidbody result = new PMXFormat.Rigidbody(); + result.name = ReadString(); + result.english_name = ReadString(); + result.rel_bone_index = CastIntRead(binary_reader_, format_.header.boneIndexSize); + result.group_index = binary_reader_.ReadByte(); + result.ignore_collision_group = binary_reader_.ReadUInt16(); + result.shape_type = (PMXFormat.Rigidbody.ShapeType)binary_reader_.ReadByte(); + result.shape_size = ReadSinglesToVector3(binary_reader_); + result.collider_position = ReadSinglesToVector3(binary_reader_); + result.collider_rotation = ReadSinglesToVector3(binary_reader_); + result.weight = binary_reader_.ReadSingle(); + result.position_dim = binary_reader_.ReadSingle(); + result.rotation_dim = binary_reader_.ReadSingle(); + result.recoil = binary_reader_.ReadSingle(); + result.friction = binary_reader_.ReadSingle(); + result.operation_type = (PMXFormat.Rigidbody.OperationType)binary_reader_.ReadByte(); + return result; + } + + private PMXFormat.RigidbodyJointList ReadRigidbodyJointList() { + PMXFormat.RigidbodyJointList result = new PMXFormat.RigidbodyJointList(); + uint joint_count = binary_reader_.ReadUInt32(); + result.joint = new PMXFormat.Joint[joint_count]; + for (uint i = 0, i_max = (uint)result.joint.Length; i < i_max; ++i) { + result.joint[i] = ReadJoint(); + } + return result; + } + + private PMXFormat.Joint ReadJoint() { + PMXFormat.Joint result = new PMXFormat.Joint(); + result.name = ReadString(); + result.english_name = ReadString(); + result.operation_type = (PMXFormat.Joint.OperationType)binary_reader_.ReadByte(); + switch (result.operation_type) { + case PMXFormat.Joint.OperationType.Spring6DOF: + result.rigidbody_a = CastIntRead(binary_reader_, format_.header.rigidbodyIndexSize); + result.rigidbody_b = CastIntRead(binary_reader_, format_.header.rigidbodyIndexSize); + result.position = ReadSinglesToVector3(binary_reader_); + result.rotation = ReadSinglesToVector3(binary_reader_); + result.constrain_pos_lower = ReadSinglesToVector3(binary_reader_); + result.constrain_pos_upper = ReadSinglesToVector3(binary_reader_); + result.constrain_rot_lower = ReadSinglesToVector3(binary_reader_); + result.constrain_rot_upper = ReadSinglesToVector3(binary_reader_); + result.spring_position = ReadSinglesToVector3(binary_reader_); + result.spring_rotation = ReadSinglesToVector3(binary_reader_); + break; + default: + //empty. + break; + } + return result; + } + + private string ReadString() + { + string result; + int stringLength = binary_reader_.ReadInt32(); + byte[] buf = binary_reader_.ReadBytes(stringLength); + switch (string_code_) { + case PMXFormat.Header.StringCode.Utf16le: + result = Encoding.UTF8.GetString(Encoding.Convert(Encoding.Unicode, Encoding.UTF8, buf)); + break; + case PMXFormat.Header.StringCode.Utf8: + result = Encoding.UTF8.GetString(buf); + break; + default: + throw new System.InvalidOperationException(); + } + return result; + } + + private uint CastIntRead(BinaryReader bin, PMXFormat.Header.IndexSize index_size) + { + uint result = 0; + switch(index_size) { + case PMXFormat.Header.IndexSize.Byte1: + result = (uint)binary_reader_.ReadByte(); + if (byte.MaxValue == result) { + result = uint.MaxValue; + } + break; + case PMXFormat.Header.IndexSize.Byte2: + result = (uint)binary_reader_.ReadUInt16(); + if (ushort.MaxValue == result) { + result = uint.MaxValue; + } + break; + case PMXFormat.Header.IndexSize.Byte4: + result = binary_reader_.ReadUInt32(); + break; + default: + throw new System.ArgumentOutOfRangeException(); + } + return result; + } + + private static Vector4 ReadSinglesToVector4(BinaryReader binary_reader_) + { + const int count = 4; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = binary_reader_.ReadSingle(); + if (float.IsNaN(result[i])) result[i] = 0.0f; //éžæ•°å€¤ãªã‚‰å›žé¿ + } + return new Vector4(result[0], result[1], result[2], result[3]); + } + + private static Vector3 ReadSinglesToVector3(BinaryReader binary_reader_) + { + const int count = 3; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = binary_reader_.ReadSingle(); + if (float.IsNaN(result[i])) result[i] = 0.0f; //éžæ•°å€¤ãªã‚‰å›žé¿ + } + return new Vector3(result[0], result[1], result[2]); + } + + private static Vector2 ReadSinglesToVector2(BinaryReader binary_reader_) + { + const int count = 2; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = binary_reader_.ReadSingle(); + if (float.IsNaN(result[i])) result[i] = 0.0f; //éžæ•°å€¤ãªã‚‰å›žé¿ + } + return new Vector2(result[0], result[1]); + } + + private static Color ReadSinglesToColor(BinaryReader binary_reader_) + { + const int count = 4; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = binary_reader_.ReadSingle(); + } + return new Color(result[0], result[1], result[2], result[3]); + } + + private static Color ReadSinglesToColor(BinaryReader binary_reader_, float fix_alpha) + { + const int count = 3; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = binary_reader_.ReadSingle(); + } + return new Color(result[0], result[1], result[2], fix_alpha); + } + + private Quaternion ReadSinglesToQuaternion(BinaryReader binary_reader_) + { + const int count = 4; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = binary_reader_.ReadSingle(); + if (float.IsNaN(result[i])) result[i] = 0.0f; //éžæ•°å€¤ãªã‚‰å›žé¿ + } + return new Quaternion(result[0], result[1], result[2], result[3]); + } + + string file_path_; + BinaryReader binary_reader_; + PMXFormat format_; + PMXFormat.Header.StringCode string_code_; +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/VMDConverter.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/VMDConverter.cs new file mode 100644 index 000000000..00093c1a1 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/VMDConverter.cs @@ -0,0 +1,559 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Linq; +using MMD.VMD; + +namespace MMD +{ + public class VMDConverter + { + /// + /// AnimationClipを作æˆã™ã‚‹ + /// + /// 内部形å¼ãƒ‡ãƒ¼ã‚¿ + /// 使用ã™ã‚‹PMDã®GameObject + /// 補完曲線å“質 + public static AnimationClip CreateAnimationClip(VMDFormat format, GameObject assign_pmd, int interpolationQuality) { + VMDConverter converter = new VMDConverter(); + return converter.CreateAnimationClip_(format, assign_pmd, interpolationQuality); + } + + /// + /// デフォルトコンストラクタ + /// + /// + /// ユーザーã«ä¾ã‚‹ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ä½œæˆã‚’ç¦æ­¢ã™ã‚‹ + /// + private VMDConverter() {} + + // クリップをアニメーションã«ç™»éŒ²ã™ã‚‹ + private AnimationClip CreateAnimationClip_(MMD.VMD.VMDFormat format, GameObject assign_pmd, int interpolationQuality) + { + //スケール設定 + scale_ = 1.0f; + if (!assign_pmd) + { + return null; + } + MMDEngine engine = assign_pmd.GetComponent(); + if (!engine) + { + return null; + } + scale_ = engine.scale; + + //Animation anim = assign_pmd.GetComponent(); + + // クリップã®ä½œæˆ + AnimationClip clip = new AnimationClip(); + clip.name = assign_pmd.name + "_" + format.name; + + Dictionary bone_path = new Dictionary(); + Dictionary gameobj = new Dictionary(); + GetGameObjects(gameobj, assign_pmd); // 親ボーン下ã®GameObjectã‚’å–å¾— + FullSearchBonePath(assign_pmd.transform, bone_path); + FullEntryBoneAnimation(format, clip, bone_path, gameobj, interpolationQuality); + + CreateKeysForSkin(format, clip); // 表情ã®è¿½åŠ  + + return clip; + } + + // ベジェãƒãƒ³ãƒ‰ãƒ«ã‚’å–å¾—ã™ã‚‹ + // 0~127ã®å€¤ã‚’ 0f~1fã¨ã—ã¦è¿”ã™ + static Vector2 GetBezierHandle(byte[] interpolation, int type, int ab) + { + // 0=X, 1=Y, 2=Z, 3=R + // abã¯a?ã‹b?ã®ã©ã¡ã‚‰ã‚’使ã„ãŸã„ã‹ + Vector2 bezierHandle = new Vector2((float)interpolation[ab*8+type], (float)interpolation[ab*8+4+type]); + return bezierHandle/127f; + } + // p0:(0f,0f),p3:(1f,1f)ã®ãƒ™ã‚¸ã‚§æ›²ç·šä¸Šã®ç‚¹ã‚’å–å¾—ã™ã‚‹ + // tã¯0~1ã®ç¯„囲 + static Vector2 SampleBezier(Vector2 bezierHandleA, Vector2 bezierHandleB, float t) + { + Vector2 p0 = Vector2.zero; + Vector2 p1 = bezierHandleA; + Vector2 p2 = bezierHandleB; + Vector2 p3 = new Vector2(1f,1f); + + Vector2 q0 = Vector2.Lerp(p0, p1, t); + Vector2 q1 = Vector2.Lerp(p1, p2, t); + Vector2 q2 = Vector2.Lerp(p2, p3, t); + + Vector2 r0 = Vector2.Lerp(q0, q1, t); + Vector2 r1 = Vector2.Lerp(q1, q2, t); + + Vector2 s0 = Vector2.Lerp(r0, r1, t); + return s0; + } + // 補間曲線ãŒç·šå½¢è£œé–“ã¨ç­‰ä¾¡ã‹ + static bool IsLinear(byte[] interpolation, int type) + { + byte ax=interpolation[0*8+type]; + byte ay=interpolation[0*8+4+type]; + byte bx=interpolation[1*8+type]; + byte by=interpolation[1*8+4+type]; + return (ax == ay) && (bx == by); + } + // 補間曲線ã®è¿‘ä¼¼ã®ãŸã‚ã«è¿½åŠ ã™ã‚‹ã‚­ãƒ¼ãƒ•レームをå«ã‚ãŸã‚­ãƒ¼ãƒ•レーム数をå–å¾—ã™ã‚‹ + int GetKeyframeCount(List mlist, int type, int interpolationQuality) + { + int count = 0; + for(int i = 0; i < mlist.Count; i++) + { + if(i>0 && !IsLinear(mlist[i].interpolation, type)) + { + count += interpolationQuality;//Interpolation Keyframes + } + else + { + count += 1;//Keyframe + } + } + return count; + } + //キーフレームãŒ1ã¤ã®æ™‚ã€ãƒ€ãƒŸãƒ¼ã‚­ãƒ¼ãƒ•レームを追加ã™ã‚‹ + void AddDummyKeyframe(ref Keyframe[] keyframes) + { + if(keyframes.Length==1) + { + Keyframe[] newKeyframes=new Keyframe[2]; + newKeyframes[0]=keyframes[0]; + newKeyframes[1]=keyframes[0]; + newKeyframes[1].time+=0.001f/60f;//1[ms] + newKeyframes[0].outTangent=0f; + newKeyframes[1].inTangent=0f; + keyframes=newKeyframes; + } + } + // ä»»æ„ã®åž‹ã®valueã‚’æŒã¤ã‚­ãƒ¼ãƒ•レーム + abstract class CustomKeyframe + { + public CustomKeyframe(float time,Type value) + { + this.time=time; + this.value=value; + } + public float time{ get; set; } + public Type value{ get; set; } + } + // floatåž‹ã®valueã‚’æŒã¤ã‚­ãƒ¼ãƒ•レーム + class FloatKeyframe:CustomKeyframe + { + public FloatKeyframe(float time,float value):base(time,value) + { + } + // 線形補間 + public static FloatKeyframe Lerp(FloatKeyframe from, FloatKeyframe to,Vector2 t) + { + return new FloatKeyframe( + Mathf.Lerp(from.time,to.time,t.x), + Mathf.Lerp(from.value,to.value,t.y) + ); + } + // ベジェを線形補間ã§è¿‘ä¼¼ã—ãŸã‚­ãƒ¼ãƒ•レームを追加ã™ã‚‹ + public static void AddBezierKeyframes(byte[] interpolation, int type, + FloatKeyframe prev_keyframe,FloatKeyframe cur_keyframe, int interpolationQuality, + ref FloatKeyframe[] keyframes,ref int index) + { + if(prev_keyframe==null || IsLinear(interpolation,type)) + { + keyframes[index++]=cur_keyframe; + } + else + { + Vector2 bezierHandleA=GetBezierHandle(interpolation,type,0); + Vector2 bezierHandleB=GetBezierHandle(interpolation,type,1); + int sampleCount = interpolationQuality; + for(int j = 0; j < sampleCount; j++) + { + float t = (j+1)/(float)sampleCount; + Vector2 sample = SampleBezier(bezierHandleA,bezierHandleB,t); + keyframes[index++] = FloatKeyframe.Lerp(prev_keyframe,cur_keyframe,sample); + } + } + } + } + // Quaternionåž‹ã®valueã‚’æŒã¤ã‚­ãƒ¼ãƒ•レーム + class QuaternionKeyframe:CustomKeyframe + { + public QuaternionKeyframe(float time,Quaternion value):base(time,value) + { + } + // 線形補間 + public static QuaternionKeyframe Lerp(QuaternionKeyframe from, QuaternionKeyframe to,Vector2 t) + { + return new QuaternionKeyframe( + Mathf.Lerp(from.time,to.time,t.x), + Quaternion.Slerp(from.value,to.value,t.y) + ); + } + // ベジェを線形補間ã§è¿‘ä¼¼ã—ãŸã‚­ãƒ¼ãƒ•レームを追加ã™ã‚‹ + public static void AddBezierKeyframes(byte[] interpolation, int type, + QuaternionKeyframe prev_keyframe,QuaternionKeyframe cur_keyframe, int interpolationQuality, + ref QuaternionKeyframe[] keyframes,ref int index) + { + if(prev_keyframe==null || IsLinear(interpolation,type)) + { + keyframes[index++]=cur_keyframe; + } + else + { + Vector2 bezierHandleA=GetBezierHandle(interpolation,type,0); + Vector2 bezierHandleB=GetBezierHandle(interpolation,type,1); + int sampleCount = interpolationQuality; + for(int j = 0; j < sampleCount; j++) + { + float t=(j+1)/(float)sampleCount; + Vector2 sample = SampleBezier(bezierHandleA,bezierHandleB,t); + keyframes[index++] = QuaternionKeyframe.Lerp(prev_keyframe,cur_keyframe,sample); + } + } + } + + } + + //移動ã®ç·šå½¢è£œé–“用tangentを求ã‚ã‚‹ + float GetLinearTangentForPosition(Keyframe from_keyframe,Keyframe to_keyframe) + { + return (to_keyframe.value-from_keyframe.value)/(to_keyframe.time-from_keyframe.time); + } + //-359~+359度ã®ç¯„囲を等価ãª0~359度ã¸å¤‰æ›ã™ã‚‹ã€‚ + float Mod360(float angle) + { + //剰余演算ã®ä»£ã‚りã«åŠ ç®—ã«ã™ã‚‹ + return (angle<0)?(angle+360f):(angle); + } + //回転ã®ç·šå½¢è£œé–“用tangentを求ã‚ã‚‹ + float GetLinearTangentForRotation(Keyframe from_keyframe,Keyframe to_keyframe) + { + float tv=Mod360(to_keyframe.value); + float fv=Mod360(from_keyframe.value); + float delta_value=Mod360(tv-fv); + //180度を越ãˆã‚‹å ´åˆã¯é€†å›žè»¢ + if(delta_value<180f) + { + return delta_value/(to_keyframe.time-from_keyframe.time); + } + else + { + return (delta_value-360f)/(to_keyframe.time-from_keyframe.time); + } + } + //アニメーションエディタã§BothLinearã‚’é¸æŠžã—ãŸã¨ãã®å€¤ + private const int TangentModeBothLinear=21; + + //Unityã®Keyframeã«å¤‰æ›ã™ã‚‹ï¼ˆå›žè»¢ç”¨ï¼‰ + void ToAnimationCurveForRotation(QuaternionKeyframe[] custom_keys, + out AnimationCurve curve_x, out AnimationCurve curve_y, out AnimationCurve curve_z) + { + Keyframe[] rx_keys = new Keyframe[custom_keys.Length]; + Keyframe[] ry_keys = new Keyframe[custom_keys.Length]; + Keyframe[] rz_keys = new Keyframe[custom_keys.Length]; + + for (int i = 0; i < custom_keys.Length; i++) + { + //オイラー角をå–り出㙠+ Vector3 eulerAngles=custom_keys[i].value.eulerAngles; + rx_keys[i]=new Keyframe(custom_keys[i].time,eulerAngles.x); + ry_keys[i]=new Keyframe(custom_keys[i].time,eulerAngles.y); + rz_keys[i]=new Keyframe(custom_keys[i].time,eulerAngles.z); + //線形補間ã™ã‚‹ + if (i > 0) + { + float tx = GetLinearTangentForRotation(rx_keys[i - 1], rx_keys[i]); + float ty = GetLinearTangentForRotation(ry_keys[i - 1], ry_keys[i]); + float tz = GetLinearTangentForRotation(rz_keys[i - 1], rz_keys[i]); + rx_keys[i - 1].outTangent = tx; + ry_keys[i - 1].outTangent = ty; + rz_keys[i - 1].outTangent = tz; + rx_keys[i].inTangent = tx; + ry_keys[i].inTangent = ty; + rz_keys[i].inTangent = tz; + } + } + AddDummyKeyframe(ref rx_keys); + AddDummyKeyframe(ref ry_keys); + AddDummyKeyframe(ref rz_keys); + + curve_x = new AnimationCurve(rx_keys); + curve_y = new AnimationCurve(ry_keys); + curve_z = new AnimationCurve(rz_keys); + + for (int i = 0; i < curve_x.keys.Length; i++) + { + AnimationUtility.SetKeyLeftTangentMode(curve_x, i, AnimationUtility.TangentMode.ClampedAuto); + AnimationUtility.SetKeyRightTangentMode(curve_x, i, AnimationUtility.TangentMode.ClampedAuto); + } + for (int i = 0; i < curve_y.keys.Length; i++) + { + AnimationUtility.SetKeyLeftTangentMode(curve_y, i, AnimationUtility.TangentMode.ClampedAuto); + AnimationUtility.SetKeyRightTangentMode(curve_y, i, AnimationUtility.TangentMode.ClampedAuto); + } + for (int i = 0; i < curve_z.keys.Length; i++) + { + AnimationUtility.SetKeyLeftTangentMode(curve_z, i, AnimationUtility.TangentMode.ClampedAuto); + AnimationUtility.SetKeyRightTangentMode(curve_z, i, AnimationUtility.TangentMode.ClampedAuto); + } + } + + + // ã‚るボーンã«å«ã¾ã‚Œã‚‹ã‚­ãƒ¼ãƒ•レを抽出 + // ã“れã¯å›žè»¢ã®ã¿ + void CreateKeysForRotation(MMD.VMD.VMDFormat format, AnimationClip clip, string current_bone, string bone_path, int interpolationQuality) + { + try + { + const float tick_time = 1.0f / VMD_FPS; + + List mlist = format.motion_list.motion[current_bone]; + int keyframeCount = GetKeyframeCount(mlist, 3, interpolationQuality); + + QuaternionKeyframe[] r_keys = new QuaternionKeyframe[keyframeCount]; + QuaternionKeyframe r_prev_key=null; + int ir=0; + for (int i = 0; i < mlist.Count; i++) + { + float tick = mlist[i].frame_no * tick_time; + + Quaternion rotation=mlist[i].rotation; + QuaternionKeyframe r_cur_key=new QuaternionKeyframe(tick,rotation); + QuaternionKeyframe.AddBezierKeyframes(mlist[i].interpolation,3,r_prev_key,r_cur_key,interpolationQuality,ref r_keys,ref ir); + r_prev_key=r_cur_key; + } + + AnimationCurve curve_x = null; + AnimationCurve curve_y = null; + AnimationCurve curve_z = null; + ToAnimationCurveForRotation(r_keys, out curve_x, out curve_y, out curve_z); + // ã“ã“ã§å›žè»¢ã‚ªã‚¤ãƒ©ãƒ¼è§’をセット(補間ã¯ã‚¯ã‚©ãƒ¼ã‚¿ãƒ‹ã‚ªãƒ³ï¼‰ + AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bone_path, typeof(Transform), "localEulerAngles.x"), curve_x); + AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bone_path, typeof(Transform), "localEulerAngles.y"), curve_y); + AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve(bone_path, typeof(Transform), "localEulerAngles.z"), curve_z); + } + catch (KeyNotFoundException) + { + Debug.LogError("äº’æ›æ€§ã®ãªã„ボーンãŒèª­ã¿è¾¼ã¾ã‚Œã¾ã—ãŸ:" + bone_path); + } + } + //Unityã®Keyframeã«å¤‰æ›ã™ã‚‹ï¼ˆç§»å‹•用) + AnimationCurve ToAnimationCurveForLocation(FloatKeyframe[] custom_keys) + { + Keyframe[] keys=new Keyframe[custom_keys.Length]; + for(int i = 0; i < custom_keys.Length; i++) + { + keys[i]=new Keyframe(custom_keys[i].time,custom_keys[i].value); + //線形補間ã™ã‚‹ + if (i > 0) + { + float t = GetLinearTangentForPosition(keys[i - 1], keys[i]); + keys[i - 1].outTangent = t; + keys[i].inTangent = t; + } + } + AddDummyKeyframe(ref keys); + + AnimationCurve retCurve = new AnimationCurve(keys); + for (int i = 0; i < retCurve.keys.Length; i++) + { + AnimationUtility.SetKeyLeftTangentMode(retCurve, i, AnimationUtility.TangentMode.ClampedAuto); + AnimationUtility.SetKeyRightTangentMode(retCurve, i, AnimationUtility.TangentMode.ClampedAuto); + } + + return retCurve; + } + // 移動ã®ã¿ã®æŠ½å‡º + void CreateKeysForLocation(MMD.VMD.VMDFormat format, AnimationClip clip, string current_bone, string bone_path, int interpolationQuality, GameObject current_obj = null) + { + try + { + const float tick_time = 1.0f / VMD_FPS; + + Vector3 default_position = Vector3.zero; + if(current_obj != null) + default_position = current_obj.transform.localPosition; + + List mlist = format.motion_list.motion[current_bone]; + + int keyframeCountX = GetKeyframeCount(mlist, 0, interpolationQuality); + int keyframeCountY = GetKeyframeCount(mlist, 1, interpolationQuality); + int keyframeCountZ = GetKeyframeCount(mlist, 2, interpolationQuality); + + FloatKeyframe[] lx_keys = new FloatKeyframe[keyframeCountX]; + FloatKeyframe[] ly_keys = new FloatKeyframe[keyframeCountY]; + FloatKeyframe[] lz_keys = new FloatKeyframe[keyframeCountZ]; + + FloatKeyframe lx_prev_key=null; + FloatKeyframe ly_prev_key=null; + FloatKeyframe lz_prev_key=null; + int ix=0; + int iy=0; + int iz=0; + for (int i = 0; i < mlist.Count; i++) + { + float tick = mlist[i].frame_no * tick_time; + + FloatKeyframe lx_cur_key=new FloatKeyframe(tick,mlist[i].location.x * scale_ + default_position.x); + FloatKeyframe ly_cur_key=new FloatKeyframe(tick,mlist[i].location.y * scale_ + default_position.y); + FloatKeyframe lz_cur_key=new FloatKeyframe(tick,mlist[i].location.z * scale_ + default_position.z); + + // å„軸別々ã«è£œé–“ãŒä»˜ã„ã¦ã‚‹ + FloatKeyframe.AddBezierKeyframes(mlist[i].interpolation,0,lx_prev_key,lx_cur_key,interpolationQuality,ref lx_keys,ref ix); + FloatKeyframe.AddBezierKeyframes(mlist[i].interpolation,1,ly_prev_key,ly_cur_key,interpolationQuality,ref ly_keys,ref iy); + FloatKeyframe.AddBezierKeyframes(mlist[i].interpolation,2,lz_prev_key,lz_cur_key,interpolationQuality,ref lz_keys,ref iz); + + lx_prev_key=lx_cur_key; + ly_prev_key=ly_cur_key; + lz_prev_key=lz_cur_key; + } + + // 回転ボーンã®å ´åˆã¯ãƒ‡ãƒ¼ã‚¿ãŒå…¥ã£ã¦ãªã„ã¯ãš + if (mlist.Count != 0) + { + AnimationCurve curve_x = ToAnimationCurveForLocation(lx_keys); + AnimationCurve curve_y = ToAnimationCurveForLocation(ly_keys); + AnimationCurve curve_z = ToAnimationCurveForLocation(lz_keys); + + AnimationUtility.SetEditorCurve(clip,EditorCurveBinding.FloatCurve(bone_path,typeof(Transform),"m_LocalPosition.x"),curve_x); + AnimationUtility.SetEditorCurve(clip,EditorCurveBinding.FloatCurve(bone_path,typeof(Transform),"m_LocalPosition.y"),curve_y); + AnimationUtility.SetEditorCurve(clip,EditorCurveBinding.FloatCurve(bone_path,typeof(Transform),"m_LocalPosition.z"),curve_z); + } + } + catch (KeyNotFoundException) + { + Debug.LogError("äº’æ›æ€§ã®ãªã„ボーンãŒèª­ã¿è¾¼ã¾ã‚Œã¾ã—ãŸ:" + current_bone); + } + } + + void CreateKeysForSkin(MMD.VMD.VMDFormat format, AnimationClip clip) + { + const float tick_time = 1f / 30f; + + // å…¨ã¦ã®è¡¨æƒ…ã«æ‰“ãŸã‚Œã¦ã„るキーフレームを探索 + List s; + + foreach (var skin in format.skin_list.skin) + { + s = skin.Value; + Keyframe[] keyframe = new Keyframe[skin.Value.Count]; + + // キーフレームã®ç™»éŒ²ã‚’行ㆠ+ for (int i = 0; i < skin.Value.Count; i++) + { + keyframe[i] = new Keyframe(s[i].frame_no * tick_time, s[i].weight); + //線形補間ã™ã‚‹ + if (i > 0) + { + float t = GetLinearTangentForPosition(keyframe[i - 1], keyframe[i]); + keyframe[i - 1].outTangent = t; + keyframe[i].inTangent = t; + } + } + AddDummyKeyframe(ref keyframe); + + // Z軸移動ã«ã‚­ãƒ¼ãƒ•レームを打㤠+ AnimationCurve curve = new AnimationCurve(keyframe); + for (int i = 0; i < curve.keys.Length; i++) + { + AnimationUtility.SetKeyLeftTangentMode(curve, i, AnimationUtility.TangentMode.Linear); + AnimationUtility.SetKeyRightTangentMode(curve, i, AnimationUtility.TangentMode.Linear); + } + + AnimationUtility.SetEditorCurve(clip,EditorCurveBinding.FloatCurve("Expression/" + skin.Key,typeof(Transform),"m_LocalPosition.z"),curve); + } + } + + // ボーンã®ãƒ‘スをå–å¾—ã™ã‚‹ + string GetBonePath(Transform transform) + { + string buf; + if (transform.parent == null) + return transform.name; + else + buf = GetBonePath(transform.parent); + return buf + "/" + transform.name; + } + + // ボーンã®å­ä¾›ã‚’å†å¸°çš„ã«èµ°æŸ» + void FullSearchBonePath(Transform transform, Dictionary dic) + { + int count = transform.childCount; + for (int i = 0; i < count; i++) + { + Transform t = transform.GetChild(i); + FullSearchBonePath(t, dic); + } + + // オブジェクトåãŒè¶³ã•れã¦ã—ã¾ã†ã®ã§æŠœã + string buf = ""; + string[] spl = GetBonePath(transform).Split('/'); + for (int i = 1; i < spl.Length-1; i++) + buf += spl[i] + "/"; + buf += spl[spl.Length-1]; + + try + { + dic.Add(transform.name, buf); + } + catch (System.ArgumentException arg) + { + Debug.Log(arg.Message); + Debug.Log("An element with the same key already exists in the dictionary. -> " + transform.name); + } + + // dicã«ã¯å…¨ã¦ã®ãƒœãƒ¼ãƒ³ã®åå‰, ボーンã®ãƒ‘スåãŒå…¥ã‚‹ + } + + // ç„¡é§„ãªã‚«ãƒ¼ãƒ–を登録ã—ã¦ã‚‹ã‘ã©ã©ã†ã™ã‚‹ã‹ + void FullEntryBoneAnimation(MMD.VMD.VMDFormat format, AnimationClip clip, Dictionary dic, Dictionary obj, int interpolationQuality) + { + foreach (KeyValuePair> p in format.motion_list.motion) + { + // 互ã„ã«åå‰ã®ä¸€è‡´ã™ã‚‹å ´åˆã«RigidbodyãŒå­˜åœ¨ã™ã‚‹ã‹èª¿ã¹ãŸã„ + GameObject current_obj = null; + string bonePath = null; + // keyã¯transformã®åå‰, valueã¯ãƒ‘ス + if (dic.TryGetValue(p.Key, out bonePath)){ + current_obj = obj[p.Key]; + + // RigidbodyãŒã‚ã‚‹å ´åˆã¯ã‚­ãƒ¼ãƒ•レã®ç™»éŒ²ã‚’無視ã™ã‚‹ + var rigid = current_obj.GetComponent(); + if (rigid != null && !rigid.isKinematic) + { + continue; + } + } + + // キーフレã®ç™»éŒ² + //CreateKeysForLocation(format, clip, p.Key, bonePath, interpolationQuality, current_obj); + CreateKeysForRotation(format, clip, p.Key, bonePath, interpolationQuality); + } + } + + // ã¨ã‚Šã‚ãˆãšå†å¸°çš„ã«å…¨ã¦ã®ã‚²ãƒ¼ãƒ ã‚ªãƒ–ジェクトをå–å¾—ã™ã‚‹ + void GetGameObjects(Dictionary obj, GameObject assign_pmd) + { + for (int i = 0; i < assign_pmd.transform.childCount; i++) + { + var transf = assign_pmd.transform.GetChild(i); + try + { + obj.Add(transf.name, transf.gameObject); + } + catch (System.ArgumentException arg) + { + Debug.Log(arg.Message); + Debug.Log("An element with the same key already exists in the dictionary. -> " + transf.name); + } + + if (transf == null) continue; // ストッパー + GetGameObjects(obj, transf.gameObject); + } + } + + private float scale_ = 1.0f; + private const float VMD_FPS = 30.0f; + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/VMDLoaderScript.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/VMDLoaderScript.cs new file mode 100644 index 000000000..99b1c3dad --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/Private/VMDLoaderScript.cs @@ -0,0 +1,326 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; +using System.Collections.Generic; +using System; +using System.IO; +using System.Text; +using MMD.VMD; + +public class VMDLoaderScript { + + /// + /// VMDファイルã®ãƒ˜ãƒƒãƒ€ãƒ¼å–å¾— + /// + /// VMDファイルã®ãƒ‘ス + /// ヘッダー + public static VMDFormat.Header GetHeader(string file_path) { + VMDLoaderScript loader = new VMDLoaderScript(); + return loader.GetHeader_(file_path); + } + + /// + /// VMDファイルã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆ + /// + /// VMDファイルã®ãƒ‘ス + /// 内部形å¼ãƒ‡ãƒ¼ã‚¿ + public static VMDFormat Import(string file_path) { + VMDLoaderScript loader = new VMDLoaderScript(); + return loader.Import_(file_path); + } + + /// + /// デフォルトコンストラクタ + /// + /// + /// ユーザーã«ä¾ã‚‹ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ä½œæˆã‚’ç¦æ­¢ã™ã‚‹ + /// + private VMDLoaderScript() {} + + private VMDFormat.Header GetHeader_(string file_path) { + VMDFormat.Header result; + using (FileStream stream = new FileStream(file_path, FileMode.Open, FileAccess.Read)) + using (BinaryReader bin = new BinaryReader(stream)) { + file_path_ = null; + binary_reader_ = bin; + result = ReadHeader(); + } + return result; + } + + private VMDFormat Import_(string file_path) { + using (FileStream stream = new FileStream(file_path, FileMode.Open, FileAccess.Read)) + using (BinaryReader bin = new BinaryReader(stream)) { + file_path_ = file_path; + binary_reader_ = bin; + Read(); + } + return format_; + } + + private VMDFormat Read() { + format_ = new VMDFormat(); + EntryPathes(); + + // 読ã¿è¾¼ã¿å¤±æ•—ã—ãŸå ´åˆã¯ã ã„ãŸã„データãŒãªã„ + // 失敗ã—ã¦ã‚‚読ã¿è¾¼ã¿ç¶šã‘ã‚‹ã“ã¨ãŒã‚ã‚‹ã®ã§ä¾‹å¤–ã§ã‚­ãƒ£ãƒƒãƒã—ã¦æ®‹ã‚Šã¯nullã«ã—ã¦ãŠã + int read_count = 0; + try { + format_.header = ReadHeader(); read_count++; + format_.motion_list = ReadMotionList(); read_count++; + format_.skin_list = ReadSkinList(); read_count++; + format_.camera_list = ReadCameraList(); read_count++; + format_.light_list = ReadLightList(); read_count++; + format_.self_shadow_list = ReadSelfShadowList(); read_count++; + } catch (EndOfStreamException e) { + Debug.Log(e.Message); + if (read_count <= 0) + format_.header = null; + if (read_count <= 1 || format_.motion_list.motion_count <= 0) + format_.motion_list = null; + if (read_count <= 2 || format_.skin_list.skin_count <= 0) + format_.skin_list = null; + if (read_count <= 3 || format_.camera_list.camera_count <= 0) + format_.camera_list = null; + if (read_count <= 4 || format_.light_list.light_count <= 0) + format_.light_list = null; + if (read_count <= 5 || format_.self_shadow_list.self_shadow_count <= 0) + format_.self_shadow_list = null; + } + return format_; + } + + private void EntryPathes() { + format_.path = file_path_; + format_.name = Path.GetFileNameWithoutExtension(file_path_); // .vmdを抜ã‹ã™ + format_.folder = Path.GetDirectoryName(file_path_); // VMDãŒæ ¼ç´ã•れã¦ã„るフォルダ + } + + public VMDFormat.Header ReadHeader() { + VMDFormat.Header result = new VMDFormat.Header(); + result.vmd_header = ConvertByteToString(binary_reader_.ReadBytes(30), ""); + result.vmd_model_name = ConvertByteToString(binary_reader_.ReadBytes(20), ""); + return result; + } + + private VMDFormat.MotionList ReadMotionList() { + VMDFormat.MotionList result = new VMDFormat.MotionList(); + result.motion_count = binary_reader_.ReadUInt32(); + result.motion = new Dictionary>(); + + // 一度ãƒãƒƒãƒ•ã‚¡ã«è²¯ã‚ã¦ã‚½ãƒ¼ãƒˆã™ã‚‹ + VMDFormat.Motion[] buf = new VMDFormat.Motion[result.motion_count]; + for (int i = 0; i < result.motion_count; i++) { + buf[i] = ReadMotion(); + } + Array.Sort(buf, (x,y)=>((int)x.frame_no - (int)y.frame_no)); + + try + { + // ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ã®æ•°ã ã‘newã•れãªã„よã­ï¼Ÿ + for (int i = 0; i < result.motion_count; i++) + { + result.motion.Add(buf[i].bone_name, new List()); + } + } + catch { } + + // dictionaryã«ã©ã‚“ã©ã‚“登録 + for (int i = 0; i < result.motion_count; i++) + { + result.motion[buf[i].bone_name].Add(buf[i]); + } + + return result; + } + + private VMDFormat.Motion ReadMotion() { + VMDFormat.Motion result = new VMDFormat.Motion(); + result.bone_name = ConvertByteToString(binary_reader_.ReadBytes(15), ""); + result.frame_no = binary_reader_.ReadUInt32(); + result.location = ReadSinglesToVector3(binary_reader_); + result.rotation = ReadSinglesToQuaternion(binary_reader_); + result.interpolation = binary_reader_.ReadBytes(64); + return result; + } + + /// + /// 表情リスト + /// + private VMDFormat.SkinList ReadSkinList() { + VMDFormat.SkinList result = new VMDFormat.SkinList(); + result.skin_count = binary_reader_.ReadUInt32(); + result.skin = new Dictionary>(); + + // 一度ãƒãƒƒãƒ•ã‚¡ã«è²¯ã‚ã¦ã‚½ãƒ¼ãƒˆã™ã‚‹ + VMDFormat.SkinData[] buf = new VMDFormat.SkinData[result.skin_count]; + for (int i = 0; i < result.skin_count; i++) { + buf[i] = ReadSkinData(); + } + Array.Sort(buf, (x,y)=>((int)x.frame_no - (int)y.frame_no)); + + try + { + // å…¨ã¦ã®ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ã‚’探索ã—ã€åˆ©ç”¨ã•れã¦ã„るボーンを特定ã™ã‚‹ + for (int i = 0; i < result.skin_count; i++) + { + result.skin.Add(buf[i].skin_name, new List()); + } + } + catch + { + //é‡è¤‡ã—ã¦ã„ã‚‹å ´åˆã¯ã“ã®å‡¦ç†ã«å…¥ã‚‹ + } + + // 辞書ã«ç™»éŒ²ã™ã‚‹ä½œæ¥­ + for (int i = 0; i < result.skin_count; i++) + { + result.skin[buf[i].skin_name].Add(buf[i]); + } + + return result; + } + + private VMDFormat.SkinData ReadSkinData() { + VMDFormat.SkinData result = new VMDFormat.SkinData(); + result.skin_name = ConvertByteToString(binary_reader_.ReadBytes(15), ""); + result.frame_no = binary_reader_.ReadUInt32(); + result.weight = binary_reader_.ReadSingle(); + return result; + } + + private VMDFormat.CameraList ReadCameraList() { + VMDFormat.CameraList result = new VMDFormat.CameraList(); + result.camera_count = binary_reader_.ReadUInt32(); + result.camera = new VMDFormat.CameraData[result.camera_count]; + for (int i = 0; i < result.camera_count; i++) { + result.camera[i] = ReadCameraData(); + } + Array.Sort(result.camera, (x,y)=>((int)x.frame_no - (int)y.frame_no)); + return result; + } + + private VMDFormat.CameraData ReadCameraData() { + VMDFormat.CameraData result = new VMDFormat.CameraData(); + result.frame_no = binary_reader_.ReadUInt32(); + result.length = binary_reader_.ReadSingle(); + result.location = ReadSinglesToVector3(binary_reader_); + result.rotation = ReadSinglesToVector3(binary_reader_); + result.interpolation = binary_reader_.ReadBytes(24); + result.viewing_angle = binary_reader_.ReadUInt32(); + result.perspective = binary_reader_.ReadByte(); + return result; + } + + private VMDFormat.LightList ReadLightList() { + VMDFormat.LightList result = new VMDFormat.LightList(); + result.light_count = binary_reader_.ReadUInt32(); + result.light = new VMDFormat.LightData[result.light_count]; + for (int i = 0; i < result.light_count; i++) { + result.light[i] = ReadLightData(); + } + + Array.Sort(result.light, (x,y)=>((int)x.frame_no - (int)y.frame_no)); + return result; + } + + private VMDFormat.LightData ReadLightData() { + VMDFormat.LightData result = new VMDFormat.LightData(); + result.frame_no = binary_reader_.ReadUInt32(); + result.rgb = ReadSinglesToColor(binary_reader_, 1); + result.location = ReadSinglesToVector3(binary_reader_); + return result; + } + + private VMDFormat.SelfShadowList ReadSelfShadowList() { + VMDFormat.SelfShadowList result = new VMDFormat.SelfShadowList(); + result.self_shadow_count = binary_reader_.ReadUInt32(); + result.self_shadow = new VMDFormat.SelfShadowData[result.self_shadow_count]; + for (int i = 0; i < result.self_shadow_count; i++) { + result.self_shadow[i] = ReadSelfShadowData(); + } + + Array.Sort(result.self_shadow, (x,y)=>((int)x.frame_no - (int)y.frame_no)); + return result; + } + + private VMDFormat.SelfShadowData ReadSelfShadowData() { + VMDFormat.SelfShadowData result = new VMDFormat.SelfShadowData(); + result.frame_no = binary_reader_.ReadUInt32(); + result.mode = binary_reader_.ReadByte(); + result.distance = binary_reader_.ReadSingle(); + return result; + } + + // ShiftJISã‹ã‚‰UTF-8ã«å¤‰æ›ã—ã¦stringã§è¿”ã™ + private static string ConvertByteToString(byte[] bytes, string line_feed_code = null) + { + // ãƒ‘ãƒ‡ã‚£ãƒ³ã‚°ã®æ¶ˆåŽ», 文字を詰ã‚ã‚‹ + if (bytes[0] == 0) return ""; + int count; + for (count = 0; count < bytes.Length; count++) if (bytes[count] == 0) break; + byte[] buf = new byte[count]; // NULL文字をå«ã‚ã‚‹ã¨ã†ã¾ã行ã‹ãªã„ + for (int i = 0; i < count; i++) { + buf[i] = bytes[i]; + } + + buf = Encoding.Convert(Encoding.GetEncoding(932), Encoding.UTF8, buf); + + string result = Encoding.UTF8.GetString(buf); + if (null != line_feed_code) { + //改行コード統一(ã‚‚ã—ãã¯é™¤åŽ») + result = result.Replace("\r\n", "\n").Replace('\r', '\n').Replace("\n", line_feed_code); + } + return result; + } + + private static Vector3 ReadSinglesToVector3(BinaryReader bin) + { + const int count = 3; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = bin.ReadSingle(); + if (float.IsNaN(result[i])) result[i] = 0.0f; //éžæ•°å€¤ãªã‚‰å›žé¿ + } + return new Vector3(result[0], result[1], result[2]); + } + + private static Color ReadSinglesToColor(BinaryReader bin) + { + const int count = 4; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = bin.ReadSingle(); + } + return new Color(result[0], result[1], result[2], result[3]); + } + + private static Color ReadSinglesToColor(BinaryReader bin, float fix_alpha) + { + const int count = 3; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = bin.ReadSingle(); + } + return new Color(result[0], result[1], result[2], fix_alpha); + } + + private static Quaternion ReadSinglesToQuaternion(BinaryReader bin) + { + const int count = 4; + float[] result = new float[count]; + for (int i = 0; i < count; i++) + { + result[i] = bin.ReadSingle(); + if (float.IsNaN(result[i])) result[i] = 0.0f; //éžæ•°å€¤ãªã‚‰å›žé¿ + } + return new Quaternion(result[0], result[1], result[2], result[3]); + } + + string file_path_; + BinaryReader binary_reader_; + VMDFormat format_; +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/VMDLoaderWindow.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/VMDLoaderWindow.cs new file mode 100644 index 000000000..c038c0783 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MMDLoader/VMDLoaderWindow.cs @@ -0,0 +1,52 @@ +using UnityEngine; +using System.Collections; +using UnityEditor; + +public class VMDLoaderWindow : EditorWindow { + Object vmdFile; + GameObject pmdPrefab; + MMD.VMDImportConfig vmd_config; + + [MenuItem ("MMD for Unity/VMD Loader")] + static void Init() { + var window = (VMDLoaderWindow)EditorWindow.GetWindow(true, "VMDLoader"); + window.Show(); + } + + void OnEnable() + { + // デフォルトコンフィグ + vmdFile = null; + pmdPrefab = null; + vmd_config = MMD.Config.LoadAndCreate().vmd_config.Clone(); + } + + void OnGUI() { + // GUIã®æœ‰åŠ¹åŒ– + GUI.enabled = !EditorApplication.isPlaying; + + // GUIæç”» + pmdPrefab = (GameObject)EditorGUILayout.ObjectField("PMD Prefab", pmdPrefab, typeof(GameObject), false); + vmdFile = EditorGUILayout.ObjectField("VMD File", vmdFile, typeof(Object), false); + vmd_config.OnGUIFunction(); + + { + bool gui_enabled_old = GUI.enabled; + GUI.enabled = !EditorApplication.isPlaying && (pmdPrefab != null) && (vmdFile != null); + if (GUILayout.Button("Convert")) { + LoadMotion(); + vmdFile = null; + } + GUI.enabled = gui_enabled_old; + } + } + + void LoadMotion() { + string file_path = AssetDatabase.GetAssetPath(vmdFile); + MMD.MotionAgent motion_agent = new MMD.MotionAgent(file_path); + motion_agent.CreateAnimationClip(pmdPrefab + , vmd_config.createAnimationFile + , vmd_config.interpolationQuality + ); + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MorphManagerEditor.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MorphManagerEditor.cs new file mode 100644 index 000000000..ae6f261e3 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/MorphManagerEditor.cs @@ -0,0 +1,123 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Linq; + +/// +/// 表情用Inspectoræ‹¡å¼µ +/// +[CustomEditor(typeof(MorphManager))] +public sealed class MorphManagerEditor : Editor +{ + /// + /// スタティックコンストラクタ + /// + static MorphManagerEditor() + { + panel_displays_ = new bool[System.Enum.GetValues(typeof(MorphManager.PanelType)).Length]; + for (int i = 0, i_max = panel_displays_.Length; i < i_max; ++i) { + panel_displays_[i] = true; + } + } + + /// + /// åˆå›žå‡¦ç† + /// + public void Awake() + { + MorphManager self = (MorphManager)target; + + children_ = new Transform[System.Enum.GetValues(typeof(MorphManager.PanelType)).Length][]; + //å­ç™»éŒ² + for (int i = 0, i_max = children_.Length; i < i_max; ++i) { + children_[i] = self.vertex_morph.script.Where(x=>x.panel == (MorphManager.PanelType)i) + .Select(x=>x.transform) + .Concat(self.uv_morph.SelectMany(x=>x.script) + .Where(x=>x.panel == (MorphManager.PanelType)i) + .Select(x=>x.transform) + ) + .Concat(self.material_morph.script.Where(x=>x.panel == (MorphManager.PanelType)i) + .Select(x=>x.transform) + ) + .Concat(self.bone_morph.script.Where(x=>x.panel == (MorphManager.PanelType)i) + .Select(x=>x.transform) + ) + .Concat(self.group_morph.script.Where(x=>x.panel == (MorphManager.PanelType)i) + .Select(x=>x.transform) + ) + .ToArray(); + } + } + + /// + /// Inspectoræç”» + /// + public override void OnInspectorGUI() + { + bool is_dirty = false; + + is_dirty = OnInspectorGUIforPanelList() || is_dirty; + + if (is_dirty) { + //æ›´æ–°ãŒæœ‰ã£ãŸãªã‚‰ + //Inspectoræ›´æ–° + EditorUtility.SetDirty(target); + } + } + + /// + /// パãƒãƒ«ãƒªã‚¹ãƒˆã®ç‚ºã®Inspectoræç”» + /// + /// æ›´æ–°ãŒæœ‰ã£ãŸã‹(true:更新有り, false:未更新) + private bool OnInspectorGUIforPanelList() + { + bool is_update = false; + + for (int i = 0, i_max = children_.Length; i < i_max; ++i) { + if (MorphManager.PanelType.Base == (MorphManager.PanelType)i) { + //Baseã ã£ãŸã‚‰ã‚¹ã‚­ãƒƒãƒ— + continue; + } + + //パãƒãƒ«ãƒ„リータイトル + string panel_name = ((MMDSkinsScript.SkinType)i).ToString(); + panel_displays_[i] = EditorGUILayout.Foldout(panel_displays_[i], panel_name); + //パãƒãƒ«ãƒ„リー内部 + if (panel_displays_[i]) { + //ã“ã®ãƒ‘ãƒãƒ«ã‚’表示ã™ã‚‹ãªã‚‰ + ++EditorGUI.indentLevel; + EditorGUILayout.BeginVertical(); + { + //モーフオブジェクト走査 + foreach (Transform child in children_[i]) { + float value = child.localPosition.z; + value = EditorGUILayout.Slider(child.name, value, 0.0f, 1.0f); + if (child.localPosition.z != value) { + //å¤‰æ›´ãŒæŽ›ã‹ã£ãŸãªã‚‰ + //Undo登録 +#if !UNITY_4_2 //4.3ä»¥é™ + Undo.RecordObject(child, "Morph Change"); +#else + Undo.RegisterUndo(child, "Morph Change"); +#endif + //Zä½ç½®æ›´æ–° + Vector3 position = child.localPosition; + position.z = value; + child.localPosition = position; + //改変モーフオブジェクトã®Inspectoræ›´æ–° + EditorUtility.SetDirty(child.transform); + + is_update = true; + } + } + } + EditorGUILayout.EndVertical(); + --EditorGUI.indentLevel; + } + } + return is_update; + } + + private static bool[] panel_displays_; //パãƒãƒ«ã®è¡¨ç¤º + private Transform[][] children_; //パãƒãƒ«åˆ¥å­ãƒ¢ãƒ¼ãƒ•オブジェクト +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/PhysicsManagerEditor.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/PhysicsManagerEditor.cs new file mode 100644 index 000000000..d3b1e5e5b --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/PhysicsManagerEditor.cs @@ -0,0 +1,93 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Linq; + +/// +/// ç‰©ç†æ¼”算用Inspectoræ‹¡å¼µ +/// +[CustomEditor(typeof(PhysicsManager))] +public sealed class PhysicsManagerEditor : Editor +{ + /// + /// åˆå›žå‡¦ç† + /// + public void Awake() + { + PhysicsManager self = (PhysicsManager)target; + if (null != self.connect_bone_list) { + joint_list_ = self.connect_bone_list.Where(x=>(null != x.joint)) + .Select(x=>x.joint.GetComponent()) + .ToArray(); + } else { + joint_list_ = null; + } + } + + /// + /// Inspectoræç”» + /// + public override void OnInspectorGUI() + { + if (null != joint_list_) { + //å†ç”Ÿæ™‚ã¯æ›¸ãæ›ãˆä¸å¯ + bool old_gui_enabled = GUI.enabled; + bool crnt_gui_enabled = !Application.isPlaying; + GUI.enabled = crnt_gui_enabled; + + foreach(var joint in joint_list_) { + GameObject parent_object = GetOriginalParent(joint); + if (null == parent_object) { + //Physicsã«ç§»å‹•ã™ã‚‹å‰ã®GameObjectãŒç„¡ã„ãªã‚‰ + //ラベルã®ã¿ + GUI.enabled = false; + EditorGUILayout.LabelField(joint.name); + GUI.enabled = crnt_gui_enabled; + } else if (joint.GetComponent().isKinematic) { + //ボーン追従(isKinematic)オブジェクト付属ã®ã‚¸ãƒ§ã‚¤ãƒ³ãƒˆãªã‚‰ + //移動ä¸å¯ + GUI.enabled = false; + EditorGUILayout.Toggle(joint.name, false); + GUI.enabled = crnt_gui_enabled; + } else if (Selection.activeTransform == joint.transform.parent) { + //Physicsã«å±žã—ã¦ã„ã‚‹ãªã‚‰ + //ç§»å‹•å¯ + if (true != EditorGUILayout.Toggle(joint.name, true)) { + //変更ãªã‚‰ + //ジョイントツリーã«ç§»å‹• + joint.transform.parent = parent_object.transform; + } + } else if (parent_object.transform == joint.transform.parent) { + //ジョイントツリーã«å±žã—ã¦ã„ã‚‹ + //ç§»å‹•å¯ + if (false != EditorGUILayout.Toggle(joint.name, false)) { + //変更ãªã‚‰ + //Physicsã«ç§»å‹• + joint.transform.parent = Selection.activeTransform; + } + } else { + //手動ã§ç§»å‹•ã—ãŸã¨æ€ã‚れる + //ラベルã®ã¿ + GUI.enabled = false; + EditorGUILayout.LabelField(joint.name); + GUI.enabled = crnt_gui_enabled; + } + } + + GUI.enabled = old_gui_enabled; + } + } + + /// + /// Physicsã«ç§»å‹•ã™ã‚‹å‰ã®GameObjectã‚’å–å¾—ã™ã‚‹ + /// + private GameObject GetOriginalParent(ConfigurableJoint joint) + { + PhysicsManager self = (PhysicsManager)target; + return self.connect_bone_list.Where(x=>(joint.gameObject == x.joint)) + .Select(x=>x.parent) + .FirstOrDefault(); + } + + private ConfigurableJoint[] joint_list_; //移動対象リスト +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/Private/XFileConverter.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/Private/XFileConverter.cs new file mode 100644 index 000000000..79ac070bb --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/Private/XFileConverter.cs @@ -0,0 +1,163 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using System; + +namespace xfile { + public class XFileConverter { + string filePath; + string folderPath; + string fileName; + StreamReader sr; + + MeshSection meshSection; + MaterialList matList; + + // フォルダã®ãƒ‘スå–å¾— + // 最後ã«ã‚¹ãƒ©ãƒƒã‚·ãƒ¥ã‚¢ãƒª + private string GetFolderPath() { + string[] str = filePath.Split('/'); + string result = ""; + for (int i = 0; i < str.Length-1; i++) + result += str[i] + "/"; + return result; + } + + private string GetFileName() { + string[] str = filePath.Split('/'); + return str[str.Length-1]; + } + + // 1行1行解釈ã—ã¦ã‚¯ãƒ©ã‚¹ã‚’作ã£ã¦ã + private void Parser(string s) { + if (Regex.IsMatch(s, "Material ")) { + s = Regex.Replace(s, "Material ", ""); // マッãƒã•ã›ã‚‹å‰ã«é‚ªé­”ãªã®ã¯æ¶ˆã™ + Match m = Regex.Match(s, "\\w+"); + matList.AddMaterial(sr, m.Value); + } else if (Regex.IsMatch(s, "Mesh ")) { + s = Regex.Replace(s, "Mesh ", ""); + Match m = Regex.Match(s, "\\w+"); + Debug.Log(m.Value); + meshSection = new MeshSection(sr, m.Value); + } + } + + private void CreateFolder() { + string buf = folderPath; + buf.Replace("/", "\\"); + System.IO.Directory.CreateDirectory(buf + "Materials"); // ã¨ã‚Šã‚ãˆãšã€ãƒžãƒ†ãƒªã‚¢ãƒ«ã®ãƒ•ã‚©ãƒ«ãƒ€ä½œæˆ + } + + public XFileConverter(UnityEngine.Object xfile) { + filePath = UnityEditor.AssetDatabase.GetAssetPath(xfile); + folderPath = GetFolderPath(); + fileName = GetFileName(); + + CreateFolder(); + sr = new StreamReader(filePath); + matList = new MaterialList(sr); + + while (!sr.EndOfStream) { + Parser(sr.ReadLine()); + } + } + + private void EntryVerticesForMesh(Mesh mesh) { + if (meshSection.vtxList.vertex.Length > 65000) + throw new Exception("A mesh may not have more than 65000 vertices."); + mesh.vertices = meshSection.vtxList.vertex; + } + + private void EntryUVForMesh(Mesh mesh) { + mesh.uv = meshSection.uvList.uvs; + } + + // サブメッシュã®ç™»éŒ² + private void EntrySubMeshForMesh(Mesh mesh) { + MeshList meshList = meshSection.meshList; + MeshMaterialList matList = meshSection.matList; + mesh.subMeshCount = matList.MaterialCount; // ã‚µãƒ–ãƒ¡ãƒƒã‚·ãƒ¥ã®æ•°ã‚’ã“ã“ã§è¨­å®š + + /* + for (int i = 0; i < meshList.MeshCount; i++) { + mesh.SetTriangles(meshList.mesh[i], matList.materialIndex[i]); + }*/ + + for (int i = 0; i < matList.MaterialCount; i++) { + List submesh = new List(); + for (int j = 0; j < meshList.MeshCount; j++) { + if (i == matList.materialIndex[j]) { + foreach (int num in meshList.mesh[j]) + submesh.Add(num); + } + } + int[] buf = new int[submesh.Count]; + submesh.CopyTo(buf); + mesh.SetTriangles(buf, i); + } + } + + public UnityEngine.Object CreatePrefab() { + string path = folderPath + fileName.Split('.')[0] + ".prefab"; + return PrefabUtility.CreateEmptyPrefab(path); + } + + private void EntryNormal(Mesh mesh) { + mesh.normals = meshSection.normList.normals; + } + + // メッシュã®ç”Ÿæˆ + public Mesh CreateMesh() { + Mesh mesh = new Mesh(); + EntryVerticesForMesh(mesh); + EntryUVForMesh(mesh); + EntrySubMeshForMesh(mesh); + EntryNormal(mesh); + AssetDatabase.CreateAsset(mesh, folderPath + fileName.Split('.')[0] + ".asset"); + return mesh; + } + + // マテリアルã®ç™»éŒ² + private UnityEngine.Material EntryMaterial(int i) { + UnityEngine.Material mat = new UnityEngine.Material(Shader.Find("VertexLit")); + Material source = matList.materials[i]; + Texture tex = null; + + // テクスãƒãƒ£ã‚’貼る + if (source.TextureFileName != "") { + tex = AssetDatabase.LoadAssetAtPath(folderPath + source.TextureFileName, typeof(Texture)) as Texture; + mat.mainTexture = tex; + mat.SetTextureScale("_MainTex", new Vector2(1, -1)); + } + + mat.color = source.DiffuseColor; + mat.SetColor("_SpecColor", source.SpecularColor); + mat.SetColor("_Emission", source.EmissionColor); + mat.SetFloat("_Shiness", source.Specularity); + mat.name = this.fileName + "_" + source.Name; + + AssetDatabase.CreateAsset(mat, folderPath + "Materials/" + mat.name + ".asset"); + return mat; + } + + public UnityEngine.Material[] CreateMaterials() { + UnityEngine.Material[] material = new UnityEngine.Material[matList.MaterialCount]; + for (int i = 0; i < matList.MaterialCount; i++) { + material[i] = EntryMaterial(i); + } + return material; + } + + public void ReplacePrefab(UnityEngine.Object prefab, Mesh mesh, UnityEngine.Material[] materials) { + GameObject obj = new GameObject(fileName.Split('.')[0]); + MeshFilter filter = obj.AddComponent(); + filter.mesh = mesh; + MeshRenderer mren = obj.AddComponent(); + mren.sharedMaterials = materials; + PrefabUtility.ReplacePrefab(obj, prefab); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/Private/XFileFormat.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/Private/XFileFormat.cs new file mode 100644 index 000000000..25929e8bd --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/Private/XFileFormat.cs @@ -0,0 +1,348 @@ +using UnityEngine; +using System.Collections; +using System.IO; +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace xfile { + + public class Converter { + static public string[] InvalidCheck(StreamReader s, int checkNum, char split) { + string[] str = s.ReadLine().Split(split); + if (str.Length < checkNum) { + str = s.ReadLine().Split(split); + if (str.Length < checkNum) Debug.LogError("Invalid Stream?"); + } + return str; + } + + static public string[] InvalidCheck(StreamReader s, int checkNum) { + return InvalidCheck(s, checkNum, ';'); + } + + static public Vector3 ToVector3(StreamReader s) { + Vector3 v = new Vector3(); + string[] str = InvalidCheck(s, 3); + v.x = Convert.ToSingle(str[0]); + v.y = Convert.ToSingle(str[1]); + v.z = Convert.ToSingle(str[2]); + return v; + } + + static public Vector2 ToVector2(StreamReader s) { + Vector2 v = new Vector2(); + string[] str = s.ReadLine().Split(','); + v.x = Convert.ToSingle(str[0]); + str = str[1].Split(';'); + v.y = Convert.ToSingle(str[0]); + return v; + } + + static public int ToInt(StreamReader s) { + return ToInt(s, ';'); + } + + static public int ToInt(StreamReader s, char split) { + string[] str = InvalidCheck(s, 1, split); + int num = 0; + try { + num = Convert.ToInt32(str[0]); + } + catch { + str = str[0].Split(';'); + num = Convert.ToInt32(str[0]); + } + return num; + } + + static public float ToFloat(StreamReader s) { + string[] str = InvalidCheck(s, 1); + return Convert.ToSingle(str[0]); + } + + static public Color ToColor(StreamReader s) { + Color c = new Color(); + string[] str = InvalidCheck(s, 4); + c.r = Convert.ToSingle(str[0]); + c.g = Convert.ToSingle(str[1]); + c.b = Convert.ToSingle(str[2]); + c.a = Convert.ToSingle(str[3]); + return c; + } + + static public Color ToColor(StreamReader s, float alpha) { + Color c = new Color(); + string[] str = InvalidCheck(s, 3); + c.r = Convert.ToSingle(str[0]); + c.g = Convert.ToSingle(str[1]); + c.b = Convert.ToSingle(str[2]); + c.a = alpha; + return c; + } + } + + /// + /// 頂点リスト + /// + public class VertexList { + private int vertexCount; + public int VertexCount { + get { return vertexCount; } + } + + public Vector3[] vertex; + + public VertexList(StreamReader s) { + vertexCount = Converter.ToInt(s); + Debug.Log("VertexList.Length: " + vertexCount); + + vertex = new Vector3[vertexCount]; + for (int i = 0; i < vertexCount; i++) + vertex[i] = Converter.ToVector3(s); + } + } + + /// + /// メッシュリスト + /// ãƒãƒªã‚´ãƒ³ã‚’æ§‹æˆã™ã‚‹é ‚点インデックスã®é›†åˆ + /// + public class MeshList { + private int meshCount; + public int MeshCount { + get { return meshCount; } + } + + public List mesh; + + public MeshList(StreamReader s, VertexList l) { + meshCount = Converter.ToInt(s); + Debug.Log("MeshList.Length: " + meshCount); + + // 頂点インデックスã®ä¿å­˜ + mesh = new List(); + for (int i = 0; i < meshCount; i++) { + // ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ã®æŠ½å‡º + string[] str = s.ReadLine().Split(';'); + mesh.Add(new int[Convert.ToInt32(str[0])]); + + // æ•°å€¤ã®æŠ½å‡º + str = str[1].Split(','); + for (int j = 0; j < mesh[i].Length; j++) { + try { + mesh[i][j] = Convert.ToInt32(str[j]); + } catch { + Debug.Log("Invalid MeshList: " + i); + } + } + } + } + } + + /// + /// 頂点マテリアルリスト + /// マテリアルを利用ã™ã‚‹é ‚点インデックスã®é›†åˆ + /// + public class MeshMaterialList { + int materialCount; + public int MaterialCount { + get { return materialCount; } + } + + int polygonCount; + public int PolygonCount { + get { return polygonCount; } + } + + public int[] materialIndex; + public string[] materialReferens; + + public MeshMaterialList(StreamReader s) { + materialCount = Converter.ToInt(s); + Debug.Log("MeshMaterialList.Length: " + materialCount); + polygonCount = Converter.ToInt(s); + + materialIndex = new int[polygonCount]; + for (int i = 0; i < polygonCount; i++) { + materialIndex[i] = Converter.ToInt(s, ','); + } + + materialReferens = new string[materialCount]; + for (int i = 0; i < materialCount; i++) { + string[] str = s.ReadLine().Split('{'); + str = str[1].Split('}'); + materialReferens[i] = str[0]; + } + + string buf = s.ReadLine(); + if (!Regex.IsMatch(buf, "}")) + throw new Exception("MeshMaterialList End?: " + buf); + } + } + + /// + /// 法線リスト + /// + public class MeshNormalList { + int normalCount; + public int NormalCount { + get { return normalCount; } + } + + public int NormalIndexCount { + get { return normalIndex.Count; } + } + + public Vector3[] normals; // 法線データ + public List normalIndex; // ã©ã®é ‚点ãŒã©ã®æ³•線データをå‚ç…§ã—ã¦ã„ã‚‹ã‹ + + public MeshNormalList(StreamReader s) { + normalCount = Converter.ToInt(s); + Debug.Log("MeshNormalList.Length: " + normalCount); + + // 法線ã®èª­ã¿è¾¼ã¿ + normals = new Vector3[normalCount]; + for (int i = 0; i < normalCount; i++) { + normals[i] = Converter.ToVector3(s); + } + + // インデックスã®èª­ã¿è¾¼ã¿ + normalIndex = new List(); + string read = s.ReadLine(); + read = s.ReadLine(); // カウントã®èª­ã¿æ¨ã¦ + while (!Regex.IsMatch(read, "}")) { + string[] str = read.Split(';'); + int[] buf = new int[Convert.ToInt32(str[0])]; + str = str[1].Split(','); + for (int i = 0; i < buf.Length; i++) { + buf[i] = Convert.ToInt32(str[i]); + } + normalIndex.Add(buf); + read = s.ReadLine(); + } + Debug.Log("MeshNormalIndex.Length: " + normalIndex.Count); + } + } + + /// + /// UVリスト + /// + public class MeshTextureCoordList { + int uvCount; + public int UVCount { + get { return uvCount; } + } + + public Vector2[] uvs; + + public MeshTextureCoordList(StreamReader s) { + uvCount = Converter.ToInt(s); + Debug.Log("MeshTextureCoordList.Length: " + uvCount); + + uvs = new Vector2[uvCount]; + for (int i = 0; i < uvCount; i++) { + uvs[i] = Converter.ToVector2(s); + } + s.ReadLine(); + } + } + + public class MeshSection { + private string name; + public string Name { + get { return name; } + } + + public MeshList meshList; + public VertexList vtxList; + public MeshMaterialList matList; + public MeshNormalList normList; + public MeshTextureCoordList uvList; + + public MeshSection(StreamReader sr, string name) { + this.name = name; + vtxList = new VertexList(sr); + meshList = new MeshList(sr, vtxList); + + // ä»–ã®ä½•ã‹ãŒã‚ã‚‹å ´åˆ + // é–‰ã˜ã‚‹ã¾ã§ç¹°ã‚Šè¿”ã— + string read = sr.ReadLine(); + while (!Regex.IsMatch(read, "}")) { + if (Regex.IsMatch(read, "MeshMaterialList") ){ + matList = new MeshMaterialList(sr); + } else if (Regex.IsMatch(read, "MeshNormals")) { + normList = new MeshNormalList(sr); + } else if (Regex.IsMatch(read, "MeshTextureCoords")) { + uvList = new MeshTextureCoordList(sr); + } + read = sr.ReadLine(); + } + } + } + + public class MaterialList { + public int MaterialCount { + get { return materials.Count; } + } + + public List materials; + + public MaterialList(StreamReader s) { + materials = new List(); + } + + public void AddMaterial(StreamReader s, string name) { + materials.Add(new Material(s, name)); + } + } + + /// + /// マテリアル + /// + public class Material { + private string name; + public string Name { + get { return name; } + } + + private Color diffuseColor; + public Color DiffuseColor { + get { return diffuseColor; } + } + + private float specularity; + public float Specularity { + get { return specularity; } + } + + private Color specularColor; + public Color SpecularColor { + get { return specularColor; } + } + + private Color emissionColor; + public Color EmissionColor { + get { return emissionColor; } + } + + private string textureFileName; + public string TextureFileName { + get { return textureFileName; } + } + + public Material(StreamReader s, string name) { + this.name = name; + diffuseColor = Converter.ToColor(s); + specularity = Converter.ToFloat(s); + specularColor = Converter.ToColor(s, 1.0f); + emissionColor = Converter.ToColor(s, 1.0f); + string str = s.ReadLine(); + if (Regex.IsMatch(str, "TextureFilename")) { + string[] buf = str.Split('"'); + textureFileName = buf[1]; + } else { + textureFileName = ""; + } + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/Private/XFileImporter.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/Private/XFileImporter.cs new file mode 100644 index 000000000..7d6c9e300 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/Private/XFileImporter.cs @@ -0,0 +1,34 @@ +using UnityEngine; +using System.Collections; + +/* + * 1. Google Sketchupã®ãƒ—ラグインをインストール + * http://www.3drad.com/Google-SketchUp-To-DirectX-XNA-Exporter-Plug-in.htm + * (プラグインã¯Sketchupをインストールã—ãŸãƒ•ォルダã®Pluginsフォルダã«ã‚¹ã‚¯ãƒªãƒ—トを入れれã°OK) + * + * 2. Xファイルã®å‡ºåŠ› + * é©å½“ã«ãƒ•ォルダを指定ã—ã¦å‡ºåŠ› + * + * 3. Projectã¸ã®èª­ã¿è¾¼ã¿ + * 出力ã—ãŸãƒ•ォルダã”ã¨Projectã«æŠ•ã’れã°OK + * + * 4. スクリプトã®é©ç”¨ + * é©å½“ãªGameObjectã«ã“ã®ã‚¹ã‚¯ãƒªãƒ—トをé©ç”¨ã•ã›ã‚‹ + * xFile変数ã«ãƒ­ãƒ¼ãƒ‰ã—ãŸXファイルをD&Dã—ã¦å®Ÿè¡Œã™ã‚Œã°å‡ºæ¥ä¸ŠãŒã‚Š + * + * è«¸æ³¨æ„ + * Xãƒ•ã‚¡ã‚¤ãƒ«ã¯æ–¹è¨€ãŒå¤šã„ã®ã§ã€ç¾åœ¨ã¯1.ã®ãƒ—ラグインã§å‡ºåŠ›ã—ãŸãƒ•ァイルã®ã¿å¯¾å¿œ + */ + +public class XFileImporter { + + // Use this for initialization + public static void Import(Object xFile) { + xfile.XFileConverter cnv = new xfile.XFileConverter(xFile); + + Object prefab = cnv.CreatePrefab(); + Material[] material = cnv.CreateMaterials(); + Mesh mesh = cnv.CreateMesh(); + cnv.ReplacePrefab(prefab, mesh, material); + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/XFileImporterWindow.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/XFileImporterWindow.cs new file mode 100644 index 000000000..38af9c170 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Editor/XFileImporter/XFileImporterWindow.cs @@ -0,0 +1,29 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; + +public class XFileImporterWindow : EditorWindow { + Object xFile = null; + + [MenuItem ("MMD for Unity/XFile Importer")] + static void Init() { + var window = (XFileImporterWindow)EditorWindow.GetWindow(true, "XFile Importer"); + window.Show(); + } + + void OnGUI() { + const int height = 20; + + xFile = EditorGUI.ObjectField( + new Rect(0, 0, position.width-16, height), "XFile" ,xFile, typeof(Object), true); + + if (xFile != null) { + if (GUI.Button(new Rect(0, height+2, position.width/2, height), "Convert")) { + XFileImporter.Import(xFile); + xFile = null; // 読ã¿çµ‚ã‚ã£ãŸã®ã§ç©ºã«ã™ã‚‹ + } + } else { + EditorGUI.LabelField(new Rect(0, height+2, position.width, height), "Missing", "Select XFile"); + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/LICENSE b/Assets/Scripts/3rd/mmd-for-unity-master/LICENSE new file mode 100644 index 000000000..635ec7af8 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/LICENSE @@ -0,0 +1,12 @@ +Copyright (c) 2011, Eiichi Takebuchi, Takahiro Inoue, Shota Ozaki, goopymoon, Masamitsu Ishikawa, Kazuki Yasufuku, Fumiya Hirano. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +Neither the name of the MikuMikuDance for Unity nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/README.md b/Assets/Scripts/3rd/mmd-for-unity-master/README.md new file mode 100644 index 000000000..af3883dd2 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/README.md @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:56624b8f12239484c049a80f2f792c6deb0739744d49c3802ee0f35134d7c67e +size 124 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/ExpressionManagerScript.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/ExpressionManagerScript.cs new file mode 100644 index 000000000..1a35e454c --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/ExpressionManagerScript.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; + +/// +/// 表情ã®ç®¡ç†ã‚¯ãƒ©ã‚¹ +/// +public class ExpressionManagerScript : MonoBehaviour +{ + public int[] indices; + + public Vector3[] source; // 元頂点, source_position + + public Vector3[] composite; + + public Mesh mesh; // メッシュ + private Mesh renderer_shared_mesh; // レンダー共有メッシュ + + public MMDSkinsScript[] skin_script; // å­ä¾›ã®è¡¨æƒ…ã®ã‚¹ã‚¯ãƒªãƒ—トé…列 + + //int lip_count = 0; + //int eye_count = 0; + //int eye_brow_count = 0; + //int other_count = 0; + + void Init() + { + // meshã®å–å¾— + if (!mesh) { + //後方互æ›ç”¨ã‚³ãƒ¼ãƒ‰(新コンãƒãƒ¼ã‚¿ã§ã¯ mesh ã¯å¿…ãšè¨­å®šã•れる) + //メッシュãŒè¨­å®šã•れã¦ã„ãªã‘れ㰠SkinnedMeshRenderer ã‹ã‚‰å–å¾—ã™ã‚‹ + mesh = transform.parent.gameObject.GetComponent().sharedMesh; + } + renderer_shared_mesh = (Mesh)Instantiate(mesh); //複製ã—ã¦ã€æ›¸ãæ›ãˆã¯ãã¡ã‚‰ã§è¡Œã† + renderer_shared_mesh.name = "ExpressionManagerScript/" + mesh.name; + transform.parent.gameObject.GetComponent().sharedMesh = renderer_shared_mesh; + + // 頂点インデックスå–å¾— + indices = transform.Find("base").GetComponent().targetIndices; + + skin_script = GetSkinScripts(); // 表情ã«ä»˜ã„ã¦ã„るスクリプトをå–å¾— + + // 元頂点é…列ã«å…¥ã‚Œã¦ã„ã + source = new Vector3[indices.Length]; + for (int i = 0; i < indices.Length; i++) + source[i] = mesh.vertices[indices[i]]; + + // åˆæˆã™ã‚‹ãƒ™ã‚¯ãƒˆãƒ«é…列 + composite = new Vector3[indices.Length]; + for (int i = 0; i < indices.Length; i++) + composite[i] = Vector3.zero; + } + + void Start() + { + Init(); + } + + // SkinScriptã®é…列をå­ä¾›ã®è¡¨æƒ…ã‹ã‚‰æŽ¢ã—ã¦æ‹¾ã£ã¦ãã‚‹ + MMDSkinsScript[] GetSkinScripts() + { + // 表情ã®ã‚¹ã‚¯ãƒªãƒ—トを拾ã£ã¦ãã‚‹ + var scripts = new MMDSkinsScript[transform.childCount]; + for (int i = 0; i < scripts.Length; i++) + scripts[i] = transform.GetChild(i).GetComponent(); + + return scripts; + } + + void LateUpdate() + { + Renderer renderer=transform.parent.GetComponent(); + if(!renderer.enabled) + return; + var vtxs = renderer_shared_mesh.vertices; // é…列をå—ã‘入れ + + //å„表情ã®åˆæˆãƒ™ã‚¯ãƒˆãƒ«ã‚’åˆæœŸåŒ–ã—ã¦ãŠã + for (int i = 0; i < indices.Length; i++) + composite[i] = Vector3.zero; + // 表情ã”ã¨ã«è¨ˆç®—ã™ã‚‹ + foreach (var s in this.skin_script) + { + s.Compute(composite); + } + + // ã“ã“ã§è¨ˆç®—çµæžœã‚’入れã¦ã„ã + for (int i = 0; i < indices.Length; i++) + { + vtxs[indices[i]] = source[i] + composite[i]; + } + + renderer_shared_mesh.vertices = vtxs; // ã“ã“ã§å映 + } + +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/HalfLambert.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/HalfLambert.shader new file mode 100644 index 000000000..219eaf07c --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/HalfLambert.shader @@ -0,0 +1,103 @@ +// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' + +// Lucifuges‚³‚ñ‚Ì’ñ‹Ÿ +Shader "MMD/HalfLambertOutline" +{ + Properties + { + _Color("Main Color", Color) = (1,1,1,1) + _Shininess("Specularity", Float) = 6 + _SpecularColor("Specular Color", Color) = (0,0,0,1) + _AmbColor("Ambient Color", Color) = (0,0,0,1) + _OutlineColor("Outline Color", Color) = (0,0,0,1) + _OutlineWidth("Outline Width", Range(0, 1)) = 0.2 + _MainTex("Base (RGB) Trans (A)", 2D) = "white" {} + } + + SubShader + { + Tags + { + "Queue"="Geometry" + "RenderType"="Opaque" + } + + Cull Off + LOD 200 + + CGPROGRAM + #pragma surface surf HalfLambert addshadow dualforward + + half4 _Color; + half _Shininess; + half4 _SpecularColor; + half4 _AmbColor; + sampler2D _MainTex; + + struct Input + { + float2 uv_MainTex; + half4 color : COLOR; + half3 viewDir; + half3 worldNormal; + }; + + half4 LightingHalfLambert(SurfaceOutput s, half3 lightDir, half atten) + { + half NdotL = dot(s.Normal, lightDir); + half wrap = NdotL * 0.5 + 0.5; + half3 lit = _LightColor0.rgb * (wrap * atten); + return half4(s.Albedo * lit + s.Emission, s.Alpha); + } + + void surf(Input IN, inout SurfaceOutput o) + { + + half4 tex0 = tex2D(_MainTex, IN.uv_MainTex); + o.Albedo = _AmbColor.rgb + tex0.rgb * IN.color.rgb * _Color.rgb; + o.Alpha = tex0.a * IN.color.a; + half rim = pow(1 - dot(IN.worldNormal, normalize(IN.viewDir)), _Shininess); + o.Emission = _SpecularColor.rgb * _SpecularColor.a * rim; + } + + ENDCG + + // Outline Pass + Pass + { + Cull Front + Lighting Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + + float4 _OutlineColor; + float _OutlineWidth; + + struct v2f + { + half4 pos : SV_POSITION; + }; + + v2f vert(appdata_base v) + { + half4 pos = UnityObjectToClipPos(v.vertex); + half width = 0.01 * _OutlineWidth; + half4 edge_pos = v.vertex + pos.w * width * half4(v.normal, 0.0); + v2f o; + o.pos = UnityObjectToClipPos(edge_pos); + return o; + } + + half4 frag(v2f i) : COLOR + { + return half4(_OutlineColor); + } + ENDCG + } + + } + Fallback "Specular" +} \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/IK/BoneController.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/IK/BoneController.cs new file mode 100644 index 000000000..1732a00f7 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/IK/BoneController.cs @@ -0,0 +1,104 @@ +using UnityEngine; +using System.Collections.Generic; +using System.Linq; + +public class BoneController : MonoBehaviour +{ + public BoneController additive_parent; + public float additive_rate; + public CCDIKSolver ik_solver; + public BoneController[] ik_solver_targets; + + public bool add_local; + public bool add_move; + public bool add_rotate; + + /// + /// 簡略化トランスフォーム + /// + [System.Serializable] + public class LiteTransform { + public Vector3 position; // ä½ç½® + public Quaternion rotation; // 回転 + + public LiteTransform(Vector3 p, Quaternion r) {position = p; rotation = r;} + } + private LiteTransform prev_global_; + private LiteTransform prev_local_; + + /// + /// åˆå›žæ›´æ–°å‰å‡¦ç† + /// + void Start() + { + if (null != ik_solver) { + ik_solver = transform.GetComponent(); + if (0 == ik_solver_targets.Length) { + ik_solver_targets = Enumerable.Repeat(ik_solver.target, 1) + .Concat(ik_solver.chains) + .Select(x=>x.GetComponent()) + .ToArray(); + } + } + UpdatePrevTransform(); + } + + /// + /// ボーン変形 + /// + public void Process() + { + if (null != additive_parent) { + //付与親有りãªã‚‰ + LiteTransform additive_parent_transform = additive_parent.GetDeltaTransform(add_local); + if (add_move) { + //付与移動有りãªã‚‰ + transform.localPosition += additive_parent_transform.position * additive_rate; + } + if (add_rotate) { + //付与回転有りãªã‚‰ + Quaternion delta_rotate_rate; + if (0.0f <= additive_rate) { + //正回転 + delta_rotate_rate = Quaternion.Slerp(Quaternion.identity, additive_parent_transform.rotation, additive_rate); + } + else + { + //逆回転 + Quaternion additive_parent_delta_rotate_reverse = Quaternion.Inverse(additive_parent_transform.rotation); + delta_rotate_rate = Quaternion.Slerp(Quaternion.identity, additive_parent_delta_rotate_reverse, -additive_rate); + } + transform.localRotation *= delta_rotate_rate; + } + } + } + + /// + /// 差分トランスフォームå–å¾— + /// + /// 差分トランスフォーム + /// ローカル付与ã‹(true:ローカル付与, false:通常付与) + public LiteTransform GetDeltaTransform(bool is_add_local) { + LiteTransform result; + if (is_add_local) { + //ローカル付与(親もå«ã‚ãŸå¤‰å½¢é‡ç®—出) + result = new LiteTransform(transform.position - prev_global_.position + , Quaternion.Inverse(prev_global_.rotation) * transform.rotation + ); + } else { + //通常付与(ã“ã®ãƒœãƒ¼ãƒ³å˜ä½“ã§ã®å¤‰å½¢é‡ç®—出) + result = new LiteTransform(transform.localPosition - prev_local_.position + , Quaternion.Inverse(prev_local_.rotation) * transform.localRotation + ); + } + return result; + } + + /// + /// 差分基点トランスフォーム更新 + /// + public void UpdatePrevTransform() { + prev_global_ = new LiteTransform(transform.position, transform.rotation); + prev_local_ = new LiteTransform(transform.localPosition, transform.localRotation); + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/IK/CCDIKSolver.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/IK/CCDIKSolver.cs new file mode 100644 index 000000000..66c51b220 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/IK/CCDIKSolver.cs @@ -0,0 +1,145 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; + +public class CCDIKSolver : MonoBehaviour +{ + /* MEMO + * -------------------- + * IKボーンã«ã“ã®ã‚¹ã‚¯ãƒªãƒ—トをé©ç”¨ã—ã¦ã€Solveを呼ã³å‡ºã™ã€‚ + * target = ターゲット(IKボーンを目指ã™ãƒœãƒ¼ãƒ³ï¼‰ + * chains = IK影響下ボーン + * -------------------- + */ + + // Target + // IKボーンを目指ã™ãƒœãƒ¼ãƒ³ + public Transform target; + + // Loop count + // ushortã ã¨Inspectorã«å‡ºãªã„ + public int iterations; + + // rad limit + // "å˜ä½è§’" + public float controll_weight; + + // IK影響下ボーン + public Transform[] chains; + + // ãƒ¬ã‚¤ã®æç”»ï¼ˆãƒ‡ãƒãƒƒã‚°ç”¨ï¼‰ + public bool drawRay = false; + + // 計算 + public void Solve() + { + // 有効化ã•れã¦ãªã‹ã£ãŸå ´åˆã¯å®Ÿè¡Œã—ãªã„ + if (!this.enabled) return; + + // ループ回数ã§è¨ˆç®—ã—ã¦ã„ã + for (int tries = 0, _mt = iterations; tries < _mt; tries++) + { + // IK影響下ボーンã”ã¨ã« + for (int _i = 0, _m = chains.Length; _i < _m; _i++) + { + var bone = chains[_i]; + var bonePos = bone.position; + + // エフェクタ設定 + var effectorPos = target.position; + var effectorDirection = (effectorPos - bonePos); + + // ターゲット設定 + var targetDirection = (transform.position - bonePos); + + // 線を引ã„ã¨ã„ã¦ã¿ã‚‹ + if (drawRay) + { + Debug.DrawRay(bonePos, effectorDirection, Color.green); + Debug.DrawRay(bonePos, targetDirection, Color.red); + } + + // å†…ç© + effectorDirection = effectorDirection.normalized; + targetDirection = targetDirection.normalized; + float rotateDot = Vector3.Dot(effectorDirection, targetDirection); + + // 角度算出。 + // controll_weightã«ã‚ˆã‚‹ä¸€å›žã®è¨ˆç®—ã§ã®åˆ¶é™ + float rotateAngle = Mathf.Acos(rotateDot); + if (float.IsNaN(rotateAngle)) continue; + var limit = 4 * controll_weight * (_i + 1); + if (rotateAngle > limit) + rotateAngle = limit; + if (rotateAngle < -limit) + rotateAngle = -limit; + rotateAngle *= Mathf.Rad2Deg; + + // 外ç©ã§å›žè»¢è»¸ç®—出 + // lockDirectionを見ã¦ã€å›žè»¢åˆ¶é™ => 一旦ãªã— + var rotateAxis = Vector3.Cross(effectorDirection, targetDirection).normalized; + + // 大丈夫ãã†ãªã‚‰ + if (float.IsNaN(rotateAxis.x) || float.IsNaN(rotateAxis.y) || float.IsNaN(rotateAxis.z)) + continue; + + // 回㙠+ var rotate = Quaternion.AngleAxis(rotateAngle, rotateAxis); + bone.rotation = rotate * bone.rotation; + + // è§’åº¦åˆ¶é™ + limitter(bone); + } + } + } + + // è§’åº¦åˆ¶é™ + void limitter(Transform bone) + { + // 足首ã®Z回転 + if (bone.name.Contains("足首")) + { + var vv = bone.localEulerAngles; + vv.z = 0; + bone.localRotation = Quaternion.Euler(vv); + return; + } + + // 本æ¥ãªã‚‰è¨­å®šå€¤ã«åŸºã¥ã„ã¦ã‚„ã‚‹ã‘ã©ã€ã¨ã‚Šã‚ãˆãšè†é™å®š + if (!bone.name.Contains("ã²ã–")) + return; + + // オイラー角をå–å¾— + var v = bone.localEulerAngles; + + // y,z回転を無効化 + if (adjust_rot(v.y) == adjust_rot(v.z)) + { + v.y = adjust_rot(v.y); + v.z = adjust_rot(v.z); + } + + // é€†ã«æ›²ãŒã‚‰ãªã„よã†ã«ã€åˆ¶é™ã—ã¦ã‚ã’ã‚‹ + if (v.x < 90 && v.x > 2 && ((v.y == 0 && v.z == 0) || (v.y == 180 && v.z == 180))) + v.x = 360 - v.x * 0.99f; + + bone.localRotation = Quaternion.Euler(v); + } + + // 0ã‹180ã‹è¿‘ã„æ–¹ã«å›ºå®š + int adjust_rot(float n) + { + if (Mathf.Abs(n) > Mathf.Abs(180 - n) && Mathf.Abs(360 - n) > Mathf.Abs(180 - n)) + return 180; + else + return 0; + } + + // MMDEngine.cs ã®æ–¹ã§IKãƒœãƒ¼ãƒ³å…¨ä½“ã‚‚ä¿æŒã—ã¦ã‚‹ã®ã§ã€ + // ãã£ã¡ã‹ã‚‰Solve()を呼ã³å‡ºã—ã¦ã„る。 + //-------------------- + //void LateUpdate() + //{ + // Solve(); + //} +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/MMDEngine.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/MMDEngine.cs new file mode 100644 index 000000000..d409dd770 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/MMDEngine.cs @@ -0,0 +1,135 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +public class MMDEngine : MonoBehaviour { + + public float scale = 1.0f; //読ã¿è¾¼ã¿ã‚¹ã‚±ãƒ¼ãƒ« + public bool useRigidbody = false; + public int[] groupTarget; // éžè¡çªå‰›ä½“リスト + public GameObject[] rigids; // 剛体リスト + public GameObject[] joints; // ConfigurableJointã®å…¥ã£ã¦ã„るボーンã®ãƒªã‚¹ãƒˆ +#if UNITY_EDITOR + public float outline_width; //エッジ幅係数(エディタ用) + public float[] material_outline_widths; //æè³ªã®ã‚¨ãƒƒã‚¸å¹…(エディタ用) + public bool enable_render_queue; //カスタムレンダーキューã®ä½¿ç”¨ + public int render_queue_value; //カスタムレンダーキュー値 +#endif + + // 訳ãŒã‚ã£ã¦ã“ã†ãªã£ã¦ã‚‹ + public int[] ignore1; + public int[] ignore2; + public int[] ignore3; + public int[] ignore4; + public int[] ignore5; + public int[] ignore6; + public int[] ignore7; + public int[] ignore8; + public int[] ignore9; + public int[] ignore10; + public int[] ignore11; + public int[] ignore12; + public int[] ignore13; + public int[] ignore14; + public int[] ignore15; + public int[] ignore16; + List ignoreList; + + // ボーンã®è¨ˆç®— + public BoneController[] bone_controllers; + // IKã®è¨ˆç®—é † + public CCDIKSolver[] ik_list; + + // Use this for initialization + void Start () + { + if (useRigidbody) + { + ignoreList = new List(); + ignoreList.Add(ignore1); + ignoreList.Add(ignore2); + ignoreList.Add(ignore3); + ignoreList.Add(ignore4); + ignoreList.Add(ignore5); + ignoreList.Add(ignore6); + ignoreList.Add(ignore7); + ignoreList.Add(ignore8); + ignoreList.Add(ignore9); + ignoreList.Add(ignore10); + ignoreList.Add(ignore11); + ignoreList.Add(ignore12); + ignoreList.Add(ignore13); + ignoreList.Add(ignore14); + ignoreList.Add(ignore15); + ignoreList.Add(ignore16); + + // éžè¡çªã‚°ãƒ«ãƒ¼ãƒ—ã®è¨­å®š + for (int i = 0; i < rigids.Length; i++) + { + for (int shift = 0; shift < 16; shift++) + { + // フラグãƒã‚§ãƒƒã‚¯ + if ((groupTarget[i] & (1 << shift)) == 0) + { + for (int j = 0; j < ignoreList[shift].Length; j++) + { + int ignoreIndex=ignoreList[shift][j]; + if (i == ignoreIndex) continue; + Physics.IgnoreCollision(rigids[i].GetComponent(), + rigids[ignoreIndex].GetComponent(), true); + } + } + } + } + } + } + + void LateUpdate() + { + //IKåæ˜  + foreach (CCDIKSolver ik_script in this.ik_list) { + ik_script.Solve(); + } + + if (0 < bone_controllers.Length) { + //ãƒœãƒ¼ãƒ³ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ©ãƒ¼ãŒæœ‰ã‚Œã°(PMXãªã‚‰) + //ボーン計算 + foreach (BoneController bone_controller in bone_controllers) { + bone_controller.Process(); + } + //差分基点座標更新 + foreach (BoneController bone_controller in bone_controllers) { + bone_controller.UpdatePrevTransform(); + } + } + } + + public static void Initialize(MMDEngine engine, int[] groupTarget, List[] ignoreGroups, GameObject[] rigidArray) + { + if (!engine.useRigidbody) + { + engine.groupTarget = groupTarget; + engine.rigids = rigidArray; + engine.useRigidbody = true; + + engine.ignore1 = ignoreGroups[0].ToArray(); + engine.ignore2 = ignoreGroups[1].ToArray(); + engine.ignore3 = ignoreGroups[2].ToArray(); + engine.ignore4 = ignoreGroups[3].ToArray(); + engine.ignore5 = ignoreGroups[4].ToArray(); + engine.ignore6 = ignoreGroups[5].ToArray(); + engine.ignore7 = ignoreGroups[6].ToArray(); + engine.ignore8 = ignoreGroups[7].ToArray(); + engine.ignore9 = ignoreGroups[8].ToArray(); + engine.ignore10 = ignoreGroups[9].ToArray(); + engine.ignore11 = ignoreGroups[10].ToArray(); + engine.ignore12 = ignoreGroups[11].ToArray(); + engine.ignore13 = ignoreGroups[12].ToArray(); + engine.ignore14 = ignoreGroups[13].ToArray(); + engine.ignore15 = ignoreGroups[14].ToArray(); + engine.ignore16 = ignoreGroups[15].ToArray(); + } + } +} + diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/MMDSkinsScript.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/MMDSkinsScript.cs new file mode 100644 index 000000000..39d9a5794 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/MMDSkinsScript.cs @@ -0,0 +1,64 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; + +public class MMDSkinsScript : MonoBehaviour +{ + // 表情ã®ç¨®é¡ž + public enum SkinType + { + Base, + EyeBrow, + Eye, + Lip, + Other, + } + + // å…¨ã¦ã®é ‚点データã‹ã‚‰ã‚¿ãƒ¼ã‚²ãƒƒãƒˆã¨ãªã‚‹é ‚点インデックス + public int[] targetIndices; + + // モーフ先ã¸ã®ãƒ™ã‚¯ãƒˆãƒ« + public Vector3[] morphTarget; + + // 表情ã®ç¨®é¡ž + public SkinType skinType; + + // å‰ãƒ•レームã®ã‚¦ã‚§ã‚¤ãƒˆå€¤ + float prev_weight = 0; + + // ウェイト付ããƒ¢ãƒ¼ãƒ•çµæžœ + public Vector3[] current_morph=null; + + // Use this for initialization + void Start () + { + + } + + // モーフã®è¨ˆç®— + public bool Compute(Vector3[] composite) + { + bool computed_morph = false; // 計算ã—ãŸã‹ã©ã†ã‹ + + float weight = transform.localPosition.z; + + if(current_morph==null || targetIndices.Length!=current_morph.Length) + current_morph=new Vector3[targetIndices.Length]; + + if (weight != prev_weight) + { + computed_morph = true; + for (int i = 0; i < targetIndices.Length; i++) + current_morph[i]=morphTarget[i] * weight; + } + for (int i = 0; i < targetIndices.Length; i++) + { + if(targetIndices[i] + /// ãƒ¢ãƒ¼ãƒ•å‡¦ç† + /// + /// æ›´æ–°ã—ãŸã‹(true:æ›´æ–°ã—ãŸã€false:未更新) + /// モーフ値 + public bool Compute(BoneMorphParameter[] composite) + { + bool result = false; + //キャッシュ設定 + float weight = base.GetWeight(transform); + if ((prev_weight_ != weight) || (null == values_cache_)) { + values_cache_ = values.Select(x=>x * weight).ToArray(); + prev_weight_ = weight; + result = true; + } + + //åæ˜  + for (int i = 0, i_max = values_cache_.Length; i < i_max; ++i) { + composite[indices[i]] += values_cache_[i]; + } + return result; + } + + /// + /// ボーンモーフパラメータ + /// + [System.Serializable] + public class BoneMorphParameter { + public Vector3 position; //移動 + public Quaternion rotation; //回転 + + /// + /// é›¶ + /// + public static BoneMorphParameter zero { + get { + BoneMorphParameter result = new BoneMorphParameter(); + result.position = Vector3.zero; + result.rotation = Quaternion.identity; + return result; + } + } + + /// + /// パラメータã®ç·šå½¢è£œé–“ + /// + /// 補間値 + /// 補間始点 + /// 補間終点 + /// 補間係数(0.0fãªã‚‰å§‹ç‚¹ã€1.0fãªã‚‰çµ‚点) + public static BoneMorphParameter Lerp (BoneMorphParameter lhs, BoneMorphParameter rhs, float weight) { + BoneMorphParameter result = new BoneMorphParameter(); + result.position = Vector3.Lerp(lhs.position, rhs.position, weight); + result.rotation = Quaternion.Slerp(lhs.rotation, rhs.rotation, weight); + return result; + } + + /// + /// 加算 + /// + /// 加算値 + /// 被加数 + /// 加数 + public static BoneMorphParameter operator+ (BoneMorphParameter lhs, BoneMorphParameter rhs) { + BoneMorphParameter result = new BoneMorphParameter(); + result.position = lhs.position + rhs.position; + result.rotation = lhs.rotation * rhs.rotation; //順回転乗算 + return result; + } + + /// + /// 減算 + /// + /// 減算値 + /// 被加数 + /// 加数 + public static BoneMorphParameter operator- (BoneMorphParameter lhs, BoneMorphParameter rhs) { + BoneMorphParameter result = new BoneMorphParameter(); + result.position = lhs.position - rhs.position; + result.rotation = lhs.rotation * Quaternion.Inverse(rhs.rotation); //逆回転乗算 + return result; + } + + /// + /// スカラー乗算 + /// + /// スカラー乗算値 + /// 被乗数 + /// ä¹—æ•° + public static BoneMorphParameter operator* (BoneMorphParameter lhs, float rhs) { + BoneMorphParameter result = new BoneMorphParameter(); + result.position = lhs.position * rhs; + result.rotation = Quaternion.Slerp(Quaternion.identity, lhs.rotation, rhs); //0.0fãŒæŽ›ã‘られれã°Quaternion.identity化ã™ã‚‹ + return result; + } + public static BoneMorphParameter operator* (float lhs, BoneMorphParameter rhs) { + return rhs * lhs; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/GroupMorph.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/GroupMorph.cs new file mode 100644 index 000000000..6d41baafb --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/GroupMorph.cs @@ -0,0 +1,36 @@ +using UnityEngine; +using System.Collections.Generic; +using System.Linq; + +public class GroupMorph : MorphBase +{ + public MorphManager.PanelType panel; + public int[] indices; + public float[] values; + + private float prev_weight_ = 0.0f; + private float[] values_cache_ = null; + + /// + /// ãƒ¢ãƒ¼ãƒ•å‡¦ç† + /// + /// æ›´æ–°ã—ãŸã‹(true:æ›´æ–°ã—ãŸã€false:未更新) + /// モーフ値 + public bool Compute(float[] composite) + { + bool result = false; + //キャッシュ設定 + float weight = base.GetWeight(transform); + if ((prev_weight_ != weight) || (null == values_cache_)) { + values_cache_ = values.Select(x=>x * weight).ToArray(); + prev_weight_ = weight; + result = true; + } + + //åæ˜  + for (int i = 0, i_max = values_cache_.Length; i < i_max; ++i) { + composite[indices[i]] += values_cache_[i]; + } + return result; + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/MaterialMorph.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/MaterialMorph.cs new file mode 100644 index 000000000..8e15885dc --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/MaterialMorph.cs @@ -0,0 +1,269 @@ +using UnityEngine; +using System.Collections.Generic; +using System.Linq; + +public class MaterialMorph : MorphBase +{ + public enum OperationType { + Mul, + Add, + } + + public MorphManager.PanelType panel; + public int[] indices; + public MaterialMorphParameter[] values; + public OperationType[] operation; + + private float prev_weight_ = 0.0f; + private MaterialMorphParameter[] values_cache_ = null; + + /// + /// ãƒ¢ãƒ¼ãƒ•å‡¦ç† + /// + /// æ›´æ–°ã—ãŸã‹(true:æ›´æ–°ã—ãŸã€false:未更新) + /// 乗算モーフ値 + /// 加算モーフ値 + /// ä¹—ç®—ã§ã‚‚加算ã§ã‚‚ç„¡ã„æ¼”算パラメータãŒè¨­å®šã•れã¦ã„ã‚‹ + public bool Compute(MaterialMorphParameter[] composite_mul, MaterialMorphParameter[] composite_add) + { + bool result = false; + //キャッシュ設定 + float weight = base.GetWeight(transform); + if ((prev_weight_ != weight) || (null == values_cache_)) { + values_cache_ = new MaterialMorphParameter[values.Length]; + for (int i = 0, i_max = values_cache_.Length; i < i_max; ++i) { + switch (operation[i]) { + case OperationType.Mul: //ä¹—ç®— + { + values_cache_[i] = MaterialMorphParameter.Lerp(MaterialMorphParameter.one, values[i], weight); + } + break; + case OperationType.Add: //加算 + { + values_cache_[i] = values[i] * weight; + } + break; + default: + throw new System.IndexOutOfRangeException(); + } + } + prev_weight_ = weight; + result = true; + } + + //åæ˜  + for (int i = 0, i_max = values_cache_.Length; i < i_max; ++i) { + switch (operation[i]) { + case OperationType.Mul: //ä¹—ç®— + { + composite_mul[indices[i]] *= values_cache_[i]; + } + break; + case OperationType.Add: //加算 + { + composite_add[indices[i]] += values_cache_[i]; + } + break; + default: + throw new System.IndexOutOfRangeException(); + } + } + return result; + } + + /// + /// æè³ªãƒ¢ãƒ¼ãƒ•パラメータ + /// + [System.Serializable] + public class MaterialMorphParameter { + public Color color; //拡散色(éžé€éŽåº¦ã‚’αãƒãƒ£ãƒ³ãƒãƒ«ã«æ ¼ç´) + public Color specular; //å射色(å射強度をαãƒãƒ£ãƒ³ãƒãƒ«ã«æ ¼ç´) + public Color ambient; //環境色 + public Color outline_color; //エッジ色 + public float outline_width; //エッジ幅 + public Color texture_color; //テクスãƒãƒ£è‰² + public Color sphere_color; //スフィア色 + public Color toon_color; //トゥーン色 + + /// + /// é›¶ + /// + public static MaterialMorphParameter zero { + get { + MaterialMorphParameter result = new MaterialMorphParameter(); + result.texture_color = result.sphere_color = result.toon_color = result.outline_color = result.ambient = result.specular = result.color = new Color(0.0f, 0.0f, 0.0f, 0.0f); + result.outline_width = 0.0f; + return result; + } + } + + /// + /// 壱 + /// + public static MaterialMorphParameter one { + get { + MaterialMorphParameter result = new MaterialMorphParameter(); + result.texture_color = result.sphere_color = result.toon_color = result.outline_color = result.ambient = result.specular = result.color = new Color(1.0f, 1.0f, 1.0f, 1.0f); + result.outline_width = 1.0f; + return result; + } + } + + /// + /// パラメータã®ç·šå½¢è£œé–“ + /// + /// 補間値 + /// 補間始点 + /// 補間終点 + /// 補間係数(0.0fãªã‚‰å§‹ç‚¹ã€1.0fãªã‚‰çµ‚点) + public static MaterialMorphParameter Lerp (MaterialMorphParameter lhs, MaterialMorphParameter rhs, float weight) { + MaterialMorphParameter result = new MaterialMorphParameter(); + float lhs_weight = 1.0f - weight; + float rhs_weight = weight; + result.color = lhs.color * lhs_weight + rhs.color * rhs_weight; + result.specular = lhs.specular * lhs_weight + rhs.specular * rhs_weight; + result.ambient = lhs.ambient * lhs_weight + rhs.ambient * rhs_weight; + result.outline_color = lhs.outline_color * lhs_weight + rhs.outline_color * rhs_weight; + result.outline_width = lhs.outline_width * lhs_weight + rhs.outline_width * rhs_weight; + result.texture_color = lhs.texture_color * lhs_weight + rhs.texture_color * rhs_weight; + result.sphere_color = lhs.sphere_color * lhs_weight + rhs.sphere_color * rhs_weight; + result.toon_color = lhs.toon_color * lhs_weight + rhs.toon_color * rhs_weight; + return result; + } + + /// + /// 加算 + /// + /// 加算値 + /// 被加数 + /// 加数 + public static MaterialMorphParameter operator+ (MaterialMorphParameter lhs, MaterialMorphParameter rhs) { + MaterialMorphParameter result = new MaterialMorphParameter(); + result.color = lhs.color + rhs.color; + result.specular = lhs.specular + rhs.specular; + result.ambient = lhs.ambient + rhs.ambient; + result.outline_color = lhs.outline_color + rhs.outline_color; + result.outline_width = lhs.outline_width + rhs.outline_width; + result.texture_color = lhs.texture_color + rhs.texture_color; + result.sphere_color = lhs.sphere_color + rhs.sphere_color; + result.toon_color = lhs.toon_color + rhs.toon_color; + return result; + } + + /// + /// スカラー加算 + /// + /// スカラー加算値 + /// 被加数 + /// 加数 + public static MaterialMorphParameter operator+ (MaterialMorphParameter lhs, float rhs) { + MaterialMorphParameter result = new MaterialMorphParameter(); + Color rhs_color = new Color(rhs, rhs, rhs, rhs); + result.color = lhs.color + rhs_color; + result.specular = lhs.specular + rhs_color; + result.ambient = lhs.ambient + rhs_color; + result.outline_color = lhs.outline_color + rhs_color; + result.outline_width = lhs.outline_width + rhs; + result.texture_color = lhs.texture_color + rhs_color; + result.sphere_color = lhs.sphere_color + rhs_color; + result.toon_color = lhs.toon_color + rhs_color; + return result; + } + public static MaterialMorphParameter operator+ (float lhs, MaterialMorphParameter rhs) { + return rhs + lhs; + } + + /// + /// 減算 + /// + /// 減算値 + /// 被加数 + /// 加数 + public static MaterialMorphParameter operator- (MaterialMorphParameter lhs, MaterialMorphParameter rhs) { + MaterialMorphParameter result = new MaterialMorphParameter(); + result.color = lhs.color - rhs.color; + result.specular = lhs.specular - rhs.specular; + result.ambient = lhs.ambient - rhs.ambient; + result.outline_color = lhs.outline_color - rhs.outline_color; + result.outline_width = lhs.outline_width - rhs.outline_width; + result.texture_color = lhs.texture_color - rhs.texture_color; + result.sphere_color = lhs.sphere_color - rhs.sphere_color; + result.toon_color = lhs.toon_color - rhs.toon_color; + return result; + } + + /// + /// スカラー減算 + /// + /// スカラー減算値 + /// 被加数 + /// 加数 + public static MaterialMorphParameter operator- (MaterialMorphParameter lhs, float rhs) { + MaterialMorphParameter result = new MaterialMorphParameter(); + Color rhs_color = new Color(rhs, rhs, rhs, rhs); + result.color = lhs.color - rhs_color; + result.specular = lhs.specular - rhs_color; + result.ambient = lhs.ambient - rhs_color; + result.outline_color = lhs.outline_color - rhs_color; + result.outline_width = lhs.outline_width - rhs; + result.texture_color = lhs.texture_color - rhs_color; + result.sphere_color = lhs.sphere_color - rhs_color; + result.toon_color = lhs.toon_color - rhs_color; + return result; + } + public static MaterialMorphParameter operator- (float lhs, MaterialMorphParameter rhs) { + MaterialMorphParameter result = new MaterialMorphParameter(); + Color lhs_color = new Color(lhs, lhs, lhs, lhs); + result.color = lhs_color - rhs.color; + result.specular = lhs_color - rhs.specular; + result.ambient = lhs_color - rhs.ambient; + result.outline_color = lhs_color - rhs.outline_color; + result.outline_width = lhs - rhs.outline_width; + result.texture_color = lhs_color - rhs.texture_color; + result.sphere_color = lhs_color - rhs.sphere_color; + result.toon_color = lhs_color - rhs.toon_color; + return result; + } + + /// + /// ä¹—ç®— + /// + /// 乗算値 + /// 被乗数 + /// ä¹—æ•° + public static MaterialMorphParameter operator* (MaterialMorphParameter lhs, MaterialMorphParameter rhs) { + MaterialMorphParameter result = new MaterialMorphParameter(); + result.color = lhs.color * rhs.color; + result.specular = lhs.specular * rhs.specular; + result.ambient = lhs.ambient * rhs.ambient; + result.outline_color = lhs.outline_color * rhs.outline_color; + result.outline_width = lhs.outline_width * rhs.outline_width; + result.texture_color = lhs.texture_color * rhs.texture_color; + result.sphere_color = lhs.sphere_color * rhs.sphere_color; + result.toon_color = lhs.toon_color * rhs.toon_color; + return result; + } + + /// + /// スカラー乗算 + /// + /// スカラー乗算値 + /// 被乗数 + /// ä¹—æ•° + public static MaterialMorphParameter operator* (MaterialMorphParameter lhs, float rhs) { + MaterialMorphParameter result = new MaterialMorphParameter(); + result.color = lhs.color * rhs; + result.specular = lhs.specular * rhs; + result.ambient = lhs.ambient * rhs; + result.outline_color = lhs.outline_color * rhs; + result.outline_width = lhs.outline_width * rhs; + result.texture_color = lhs.texture_color * rhs; + result.sphere_color = lhs.sphere_color * rhs; + result.toon_color = lhs.toon_color * rhs; + return result; + } + public static MaterialMorphParameter operator* (float lhs, MaterialMorphParameter rhs) { + return rhs * lhs; + } + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/MorphBase.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/MorphBase.cs new file mode 100644 index 000000000..33fd9ff66 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/MorphBase.cs @@ -0,0 +1,16 @@ +using UnityEngine; +using System.Collections.Generic; +using System.Linq; + +public class MorphBase : MonoBehaviour +{ + public float group_weight = 0.0f; + + /// + /// ウェイト計算 + /// + public float GetWeight(Transform transform) + { + return transform.localPosition.z + group_weight; + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/MorphManager.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/MorphManager.cs new file mode 100644 index 000000000..7bb99c2df --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/MorphManager.cs @@ -0,0 +1,354 @@ +using UnityEngine; +using System.Collections.Generic; +using System.Linq; + +/// +/// モーフ管ç†ã‚¯ãƒ©ã‚¹ +/// +public class MorphManager : MonoBehaviour +{ + // 表情ã®ç¨®é¡ž + public enum PanelType + { + Base, + EyeBrow, + Eye, + Lip, + Other, + } + + public SkinnedMeshRenderer[] renderers; // レンダー + public Mesh[] mesh; // メッシュ + private Mesh[] renderer_shared_mesh_; // レンダー共有メッシュ + public Material[][] materials; // マテリアル + private Material[][] renderer_shared_materials_; // レンダー共有マテリアル + public Transform[] bones; // ボーン + public MorphBase[] morphs; // モーフ + + /// + /// グループモーフ + /// + [System.Serializable] + public class GroupMorphPack { + public int[] indices; // グループインデックス + public float[] source; // グループ元データ + public GroupMorph[] script; // グループモーフã®ã‚¹ã‚¯ãƒªãƒ—トé…列 + + public GroupMorphPack(int[] i = null, float[] s = null, GroupMorph[] c = null) {indices = i; source = s; script = c;} + } + public GroupMorphPack group_morph = null; // グループモーフ + + /// + /// ボーンモーフ + /// + [System.Serializable] + public class BoneMorphPack { + public int[] indices; // ボーンインデックス + public BoneMorph.BoneMorphParameter[] source; // ボーン元データ + public BoneMorph[] script; // ボーンモーフã®ã‚¹ã‚¯ãƒªãƒ—トé…列 + + public BoneMorphPack(int[] i = null, BoneMorph.BoneMorphParameter[] s = null, BoneMorph[] c = null) {indices = i; source = s; script = c;} + } + public BoneMorphPack bone_morph = null; // ボーンモーフ + + /// + /// 頂点モーフ + /// + [System.Serializable] + public class VertexMorphPack { + [System.Serializable] + public class Meshes { + public int[] indices; + } + public Meshes[] meshes; // メッシュ別頂点インデックス + public Vector3[] source; // 頂点元データ + public VertexMorph[] script; // 頂点モーフã®ã‚¹ã‚¯ãƒªãƒ—トé…列 + + public VertexMorphPack(Meshes[] i = null, Vector3[] s = null, VertexMorph[] c = null) {meshes = i; source = s; script = c;} + } + public VertexMorphPack vertex_morph = null; // 頂点モーフ + + /// + /// UVモーフ + /// + [System.Serializable] + public class UvMorphPack { + [System.Serializable] + public class Meshes { + public int[] indices; + } + public Meshes[] meshes; // メッシュ別UVインデックス + public Vector2[] source; // UV元データ + public UvMorph[] script; // UVモーフã®ã‚¹ã‚¯ãƒªãƒ—トé…列 + + public UvMorphPack(Meshes[] i = null, Vector2[] s = null, UvMorph[] c = null) {meshes = i; source = s; script = c;} + } + public UvMorphPack[] uv_morph; // UVモーフ + + /// + /// æè³ªãƒ¢ãƒ¼ãƒ• + /// + [System.Serializable] + public class MaterialMorphPack { + [System.Serializable] + public class Meshes { + public int[] indices; + } + public Meshes[] meshes; // メッシュ別æè³ªã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ + public MaterialMorph.MaterialMorphParameter[] source; // æè³ªå…ƒãƒ‡ãƒ¼ã‚¿ + public MaterialMorph[] script; // æè³ªãƒ¢ãƒ¼ãƒ•ã®ã‚¹ã‚¯ãƒªãƒ—トé…列 + + public MaterialMorphPack(Meshes[] i = null, MaterialMorph.MaterialMorphParameter[] s = null, MaterialMorph[] c = null) {meshes = i; source = s; script = c;} + } + public MaterialMorphPack material_morph; // æè³ªãƒ¢ãƒ¼ãƒ• + + /// + /// åˆå›žæ›´æ–°å‰å‡¦ç† + /// + void Start() + { + //メッシュ + renderer_shared_mesh_ = mesh.Select(x=>{ + Mesh m = (Mesh)Instantiate(x); //複製ã—ã¦ã€æ›¸ãæ›ãˆã¯ãã¡ã‚‰ã§è¡Œã† + m.name = "MorphManager/" + x.name; + return m; + }) + .ToArray(); + for (int i = 0, i_max = renderers.Length; i < i_max; ++i) { + renderers[i].sharedMesh = renderer_shared_mesh_[i]; + } + + //マテリアル + renderer_shared_materials_ = renderers.Select(x=>x.materials).ToArray(); + } + + /// + /// å¾Œæ›´æ–°å‡¦ç† + /// + void LateUpdate() + { + //æç”»ç¢ºèª + if(!renderers[0].enabled) { + //æç”»ã•れã¦ã„ãªã„ãªã‚‰ + //実行ã—ãªã„ + return; + } + + //グループモーフ計算 + ComputeGroupMorph(); + + //ボーンモーフ計算 + ComputeBoneMorph(); + + //頂点モーフ計算 + ComputeVertexMorph(); + + //UVモーフ計算 + ComputeUvMorph(); + + //æè³ªãƒ¢ãƒ¼ãƒ•計算 + ComputeMaterialMorph(); + } + + /// + /// グループモーフ計算 + /// + void ComputeGroupMorph() + { + if (0 < group_morph.indices.Length) { + //å„表情ã®åˆæˆãƒ™ã‚¯ãƒˆãƒ«ã‚’åˆæœŸåŒ–ã—ã¦ãŠã + float[] composite = new float[group_morph.source.Length]; + System.Array.Copy(group_morph.source, composite, group_morph.source.Length); + + // 表情ã”ã¨ã«è¨ˆç®—ã™ã‚‹ + bool is_update = false; + foreach (var morph in group_morph.script) { + if (morph.Compute(composite)) { + is_update = true; + } + } + + // ã“ã“ã§è¨ˆç®—çµæžœã‚’入れã¦ã„ã + if (is_update) { + for (int i = 0, i_max = group_morph.indices.Length; i < i_max; ++i) { + MorphBase morph_base = morphs[group_morph.indices[i]]; + morph_base.group_weight = composite[i]; // ã“ã“ã§å映 + } + } + } + } + + + /// + /// ボーンモーフ計算 + /// + void ComputeBoneMorph() + { + if (0 < bone_morph.indices.Length) { + //å„表情ã®åˆæˆãƒ™ã‚¯ãƒˆãƒ«ã‚’åˆæœŸåŒ–ã—ã¦ãŠã + BoneMorph.BoneMorphParameter[] composite = new BoneMorph.BoneMorphParameter[bone_morph.source.Length]; + System.Array.Copy(bone_morph.source, composite, bone_morph.source.Length); + + // 表情ã”ã¨ã«è¨ˆç®—ã™ã‚‹ + bool is_update = false; + foreach (var morph in bone_morph.script) { + if (morph.Compute(composite)) { + is_update = true; + } + } + + // ã“ã“ã§è¨ˆç®—çµæžœã‚’入れã¦ã„ã + if (is_update) { + for (int i = 0, i_max = bone_morph.indices.Length; i < i_max; ++i) { + bones[bone_morph.indices[i]].localPosition = composite[i].position; + bones[bone_morph.indices[i]].localRotation = composite[i].rotation; + } + } + } + } + + /// + /// 頂点モーフ計算 + /// + void ComputeVertexMorph() + { + if (0 < vertex_morph.meshes.Length) { + //å„表情ã®åˆæˆãƒ™ã‚¯ãƒˆãƒ«ã‚’åˆæœŸåŒ–ã—ã¦ãŠã + Vector3[] composite = new Vector3[vertex_morph.source.Length]; + System.Array.Copy(vertex_morph.source, composite, vertex_morph.source.Length); + + // 表情ã”ã¨ã«è¨ˆç®—ã™ã‚‹ + bool is_update = false; + foreach (var morph in vertex_morph.script) { + if (morph.Compute(composite)) { + is_update = true; + } + } + + // ã“ã“ã§è¨ˆç®—çµæžœã‚’入れã¦ã„ã + if (is_update) { + for (int r = 0, r_max = renderers.Length; r < r_max; ++r) { + var vtxs = renderer_shared_mesh_[r].vertices; // é…列をå—ã‘入れ + for (int v = 0, v_max = vertex_morph.meshes[r].indices.Length; v < v_max; ++v) { + if (vertex_morph.meshes[r].indices[v] < vtxs.Length) { + vtxs[vertex_morph.meshes[r].indices[v]] = composite[v]; + } + } + renderer_shared_mesh_[r].vertices = vtxs; // ã“ã“ã§å映 + } + } + } + } + + /// + /// UVモーフ計算 + /// + void ComputeUvMorph() + { + for (int i = 0, i_max = System.Math.Min(uv_morph.Length, 2); i < i_max; ++i) { + //å„表情ã®åˆæˆãƒ™ã‚¯ãƒˆãƒ«ã‚’åˆæœŸåŒ–ã—ã¦ãŠã + Vector2[] composite = new Vector2[uv_morph[i].source.Length]; + System.Array.Copy(uv_morph[i].source, composite, uv_morph[i].source.Length); + + // 表情ã”ã¨ã«è¨ˆç®—ã™ã‚‹ + bool is_update = false; + foreach (var morph in uv_morph[i].script) { + if (morph.Compute(composite)) { + is_update = true; + } + } + + // ã“ã“ã§è¨ˆç®—çµæžœã‚’入れã¦ã„ã + if (is_update) { + for (int r = 0, r_max = renderers.Length; r < r_max; ++r) { + var uvs = ((0 == i)? renderer_shared_mesh_[r].uv: renderer_shared_mesh_[r].uv2); // é…列をå—ã‘入れ + for (int v = 0, v_max = uv_morph[i].meshes[r].indices.Length; v < v_max; ++v) { + if (uv_morph[i].meshes[r].indices[v] < uvs.Length) { + uvs[uv_morph[i].meshes[r].indices[v]] = composite[v]; + } + } + if (0 == i) { + renderer_shared_mesh_[r].uv = uvs; // ã“ã“ã§å映 + } else { + renderer_shared_mesh_[r].uv2 = uvs; // ã“ã“ã§å映 + } + } + } + } + } + + /// + /// æè³ªãƒ¢ãƒ¼ãƒ•計算 + /// + void ComputeMaterialMorph() + { + if (0 < material_morph.meshes.Length) { + //å„æè³ªã‚’åˆæœŸåŒ–ã—ã¦ãŠã + MaterialMorph.MaterialMorphParameter[] composite_mul = Enumerable.Repeat(MaterialMorph.MaterialMorphParameter.one, material_morph.source.Length).ToArray(); + MaterialMorph.MaterialMorphParameter[] composite_add = Enumerable.Repeat(MaterialMorph.MaterialMorphParameter.zero, material_morph.source.Length).ToArray(); + + // 表情ã”ã¨ã«è¨ˆç®—ã™ã‚‹ + bool is_update = false; + foreach (var morph in material_morph.script) { + if (morph.Compute(composite_mul, composite_add)) { + is_update = true; + } + } + + if (is_update) { + //å…¨æè³ªè¨ˆç®— + bool has_all_target = false; + if (-1 == material_morph.meshes[0].indices.LastOrDefault()) { + //最後ã«-1(≒uint.MaxValue)ãŒæœ‰ã‚Œã° + //å…¨æè³ªãƒ¢ãƒ¼ãƒ•ãŒæœ‰ã‚‹ + has_all_target = true; + } + if (has_all_target) { + //å…¨æè³ªãƒ¢ãƒ¼ãƒ•ãŒæœ‰ã‚Œã° + //å…¨æè³ªã«å映 + MaterialMorph.MaterialMorphParameter composite_mul_all = composite_mul.Last(); + MaterialMorph.MaterialMorphParameter composite_add_all = composite_add.Last(); + for (int i = 0, i_max = material_morph.source.Length - 1; i < i_max; ++i) { + composite_mul[i] *= composite_mul_all; + composite_add[i] += composite_add_all; + } + } + + // ã“ã“ã§è¨ˆç®—çµæžœã‚’入れã¦ã„ã + for (int r = 0, r_max = renderers.Length; r < r_max; ++r) { + for (int m = 0, m_max = material_morph.source.Length - ((has_all_target)? 1: 0); m < m_max; ++m) { + int index = material_morph.meshes[r].indices[m]; + if (index < renderer_shared_materials_[r].Length) { + ApplyMaterialMorph(renderer_shared_materials_[r][index] + , material_morph.source[m] + , composite_mul[m] + , composite_add[m] + ); + } + } + } + } + } + } + + /// + /// æè³ªãƒ¢ãƒ¼ãƒ•åæ˜  + /// + /// åæ˜ å…ˆãƒžãƒ†ãƒªã‚¢ãƒ« + /// åæ˜ ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ + private static void ApplyMaterialMorph(Material material, MaterialMorph.MaterialMorphParameter source, MaterialMorph.MaterialMorphParameter composite_mul, MaterialMorph.MaterialMorphParameter composite_add) { + MaterialMorph.MaterialMorphParameter composite = source * composite_mul + composite_add; + material.SetColor("_Color", composite.color); + material.SetFloat("_Opacity", composite.color.a); + material.SetColor("_AmbColor", composite.ambient); + material.SetColor("_SpecularColor", composite.specular); + material.SetFloat("_Shininess", composite.specular.a); + material.SetColor("_OutlineColor", composite.outline_color); + material.SetFloat("_OutlineWidth", composite.outline_width); +#if MFU_CHANGEABLE_TEXTURE_COLOR_SHADER //テクスãƒãƒ£ã‚«ãƒ©ãƒ¼ã®å¤‰æ›´å‡ºæ¥ã‚‹ã‚·ã‚§ãƒ¼ãƒ€ãƒ¼ãŒç„¡ã„ã®ã§ç„¡åŠ¹åŒ– + material.SetColor("_MainTexColor", composite.texture_color); + material.SetColor("_SphereTexColor", composite.sphere_color); + material.SetColor("_ToonTexColor", composite.toon_color); +#endif //MFU_CHANGEABLE_TEXTURE_COLOR_SHADER + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/UvMorph.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/UvMorph.cs new file mode 100644 index 000000000..b3635fddb --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/UvMorph.cs @@ -0,0 +1,36 @@ +using UnityEngine; +using System.Collections.Generic; +using System.Linq; + +public class UvMorph : MorphBase +{ + public MorphManager.PanelType panel; + public int[] indices; + public Vector2[] values; + + private float prev_weight_ = 0.0f; + private Vector2[] values_cache_ = null; + + /// + /// ãƒ¢ãƒ¼ãƒ•å‡¦ç† + /// + /// æ›´æ–°ã—ãŸã‹(true:æ›´æ–°ã—ãŸã€false:未更新) + /// モーフ値 + public bool Compute(Vector2[] composite) + { + bool result = false; + //キャッシュ設定 + float weight = base.GetWeight(transform); + if ((prev_weight_ != weight) || (null == values_cache_)) { + values_cache_ = values.Select(x=>x * weight).ToArray(); + prev_weight_ = weight; + result = true; + } + + //åæ˜  + for (int i = 0, i_max = values_cache_.Length; i < i_max; ++i) { + composite[indices[i]] += values_cache_[i]; + } + return result; + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/VertexMorph.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/VertexMorph.cs new file mode 100644 index 000000000..c5b92a1fa --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/Morph/VertexMorph.cs @@ -0,0 +1,36 @@ +using UnityEngine; +using System.Collections.Generic; +using System.Linq; + +public class VertexMorph : MorphBase +{ + public MorphManager.PanelType panel; + public int[] indices; + public Vector3[] values; + + private float prev_weight_ = 0.0f; + private Vector3[] values_cache_ = null; + + /// + /// ãƒ¢ãƒ¼ãƒ•å‡¦ç† + /// + /// æ›´æ–°ã—ãŸã‹(true:æ›´æ–°ã—ãŸã€false:未更新) + /// モーフ値 + public bool Compute(Vector3[] composite) + { + bool result = false; + //キャッシュ設定 + float weight = base.GetWeight(transform); + if ((prev_weight_ != weight) || (null == values_cache_)) { + values_cache_ = values.Select(x=>x * weight).ToArray(); + prev_weight_ = weight; + result = true; + } + + //åæ˜  + for (int i = 0, i_max = values_cache_.Length; i < i_max; ++i) { + composite[indices[i]] += values_cache_[i]; + } + return result; + } +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/LICENSE b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material Transparent.mat b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material Transparent.mat new file mode 100644 index 000000000..af5527db7 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material Transparent.mat @@ -0,0 +1,46 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: PMD Material Transparent + m_Shader: {fileID: 4800000, guid: d9a28a4fb26b1bf4aa2074b1b9e5a000, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SphereAddTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SphereMulTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ToonTex: + m_Texture: {fileID: 2800000, guid: df2482a76bd514960b85b7ba12b9ea17, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Opacity: 0.8 + - _Shininess: 0 + m_Colors: + - _AmbColor: {r: 0, g: 0, b: 0, a: 1} + - _Color: {r: 0.84393066, g: 0.8589086, b: 0.113923594, a: 1} + - _SpecularColor: {r: 0, g: 0, b: 0, a: 1} +--- !u!1002 &2100001 +EditorExtensionImpl: + serializedVersion: 6 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material with Outline Transparent.mat b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material with Outline Transparent.mat new file mode 100644 index 000000000..bada0848a --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material with Outline Transparent.mat @@ -0,0 +1,48 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: PMD Material with Outline Transparent + m_Shader: {fileID: 4800000, guid: 200ec679e5d921b4fbbfca0acb268f60, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SphereAddTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SphereMulTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ToonTex: + m_Texture: {fileID: 2800000, guid: df2482a76bd514960b85b7ba12b9ea17, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Opacity: 0.5 + - _OutlineWidth: 0.06858341 + - _Shininess: 0 + m_Colors: + - _AmbColor: {r: 0.21939135, g: 0.21939135, b: 0.21939135, a: 1} + - _Color: {r: 0.7620103, g: 0.21136099, b: 0.21136099, a: 1} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 0, g: 0, b: 0, a: 1} +--- !u!1002 &2100001 +EditorExtensionImpl: + serializedVersion: 6 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material with Outline.mat b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material with Outline.mat new file mode 100644 index 000000000..a8a8a1ba8 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material with Outline.mat @@ -0,0 +1,48 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: PMD Material with Outline + m_Shader: {fileID: 4800000, guid: 1caff3dbcad030e45946b79da5247af8, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SphereAddTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SphereMulTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ToonTex: + m_Texture: {fileID: 2800000, guid: df2482a76bd514960b85b7ba12b9ea17, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Opacity: 1 + - _OutlineWidth: 0.070219226 + - _Shininess: 0 + m_Colors: + - _AmbColor: {r: 0.23463738, g: 0.23463738, b: 0.23463738, a: 1} + - _Color: {r: 0.11564884, g: 0.3061467, b: 0.6743529, a: 1} + - _OutlineColor: {r: 0, g: 0, b: 0, a: 1} + - _SpecularColor: {r: 0.16904736, g: 0.16904736, b: 0.16904736, a: 1} +--- !u!1002 &2100001 +EditorExtensionImpl: + serializedVersion: 6 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material.mat b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material.mat new file mode 100644 index 000000000..5578bc13e --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/PMD Material.mat @@ -0,0 +1,45 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: PMD Material + m_Shader: {fileID: 4800000, guid: 0cb22e333ded91341b3f5eba1c6bb950, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SphereAddTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SphereMulTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ToonTex: + m_Texture: {fileID: 2800000, guid: df2482a76bd514960b85b7ba12b9ea17, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _Shininess: 0 + m_Colors: + - _AmbColor: {r: 0, g: 0, b: 0, a: 1} + - _Color: {r: 0.14534715, g: 0.848968, b: 0.52422005, a: 1} + - _SpecularColor: {r: 0, g: 0, b: 0, a: 1} +--- !u!1002 &2100001 +EditorExtensionImpl: + serializedVersion: 6 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/README.md b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/README.md new file mode 100644 index 000000000..49181478a --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/README.md @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c306fef6bd4342ea7ea548dd090cce48de602a1b9a636f99df1d1745fb8ed187 +size 1267 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-CullBack-NoCastShadow.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-CullBack-NoCastShadow.shader new file mode 100644 index 000000000..0063cba56 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-CullBack-NoCastShadow.shader @@ -0,0 +1,55 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/PMDMaterial-CullBack-NoCastShadow" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Settings + Tags + { + "ForceNoShadowCasting" = "True" + } + + // First Pass + Pass + { + Cull Back + } + + // Surface Shader + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + } + + // Other Environment + Fallback "Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-CullBack.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-CullBack.shader new file mode 100644 index 000000000..a4ce6de19 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-CullBack.shader @@ -0,0 +1,49 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/PMDMaterial-CullBack" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // First Pass + Pass + { + Cull Back + } + + // Surface Shader + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + } + + // Other Environment + Fallback "Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-NoCastShadow.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-NoCastShadow.shader new file mode 100644 index 000000000..958621072 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-NoCastShadow.shader @@ -0,0 +1,55 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/PMDMaterial-NoCastShadow" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Settings + Tags + { + "ForceNoShadowCasting" = "True" + } + + // First Pass + Pass + { + Cull Off + } + + // Surface Shader + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + } + + // Other Environment + Fallback "Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans-CullBack-NoCastShadow.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans-CullBack-NoCastShadow.shader new file mode 100644 index 000000000..e1eaa49ce --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans-CullBack-NoCastShadow.shader @@ -0,0 +1,56 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/Transparent/PMDMaterial-CullBack-NoCastShadow" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _Opacity("ä¸é€æ˜Žåº¦", Float) = 1.0 + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Settings + Tags + { + "Queue" = "Transparent" + "RenderType" = "Transparent" + } + + // Surface Shader + Cull Back + ZWrite On + Blend SrcAlpha OneMinusSrcAlpha + AlphaTest Greater 0.0 + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + } + + // Other Environment + Fallback "Transparent/Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans-CullBack.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans-CullBack.shader new file mode 100644 index 000000000..afe748238 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans-CullBack.shader @@ -0,0 +1,76 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/Transparent/PMDMaterial-CullBack" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _Opacity("ä¸é€æ˜Žåº¦", Float) = 1.0 + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Settings + Tags + { + "Queue" = "Transparent" + "RenderType" = "Transparent" + } + + // Surface Shader + Cull Back + ZWrite On + Blend SrcAlpha OneMinusSrcAlpha + AlphaTest Greater 0.0 + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // ShadowCast Pass + Pass + { + Tags + { + "LightMode" = "ShadowCaster" + } + Cull Off + Lighting Off + //Offset [_ShadowBias], [_ShadowBiasSlope] //使ãˆãªã„様ãªã®ã§ã‚³ãƒ¡ãƒ³ãƒˆã‚¢ã‚¦ãƒˆ + AlphaTest Greater 0.25 + + CGPROGRAM + #pragma vertex shadow_vert + #pragma fragment shadow_frag + #include "UnityCG.cginc" + #include "MeshPmdMaterialShadowVertFrag.cginc" + ENDCG + } + + } + + // Other Environment + Fallback "Transparent/Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans-NoCastShadow.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans-NoCastShadow.shader new file mode 100644 index 000000000..2690bf0e9 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans-NoCastShadow.shader @@ -0,0 +1,66 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/Transparent/PMDMaterial-NoCastShadow" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _Opacity("ä¸é€æ˜Žåº¦", Float) = 1.0 + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Settings + Tags + { + "Queue" = "Transparent" + "RenderType" = "Transparent" + } + + // Surface Shader + Cull Front + ZWrite Off + Blend SrcAlpha OneMinusSrcAlpha + AlphaTest Greater 0.0 + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // Surface Shader + Cull Back + ZWrite On + Blend SrcAlpha OneMinusSrcAlpha + AlphaTest Greater 0.0 + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + } + + // Other Environment + Fallback "Transparent/Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans.shader new file mode 100644 index 000000000..8a09788c4 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial-Trans.shader @@ -0,0 +1,86 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/Transparent/PMDMaterial" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _Opacity("ä¸é€æ˜Žåº¦", Float) = 1.0 + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Settings + Tags + { + "Queue" = "Transparent" + "RenderType" = "Transparent" + } + + // Surface Shader + Cull Front + ZWrite Off + Blend SrcAlpha OneMinusSrcAlpha + AlphaTest Greater 0.0 + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // Surface Shader + Cull Back + ZWrite On + Blend SrcAlpha OneMinusSrcAlpha + AlphaTest Greater 0.0 + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // ShadowCast Pass + Pass + { + Tags + { + "LightMode" = "ShadowCaster" + } + Cull Off + Lighting Off + //Offset [_ShadowBias], [_ShadowBiasSlope] //使ãˆãªã„様ãªã®ã§ã‚³ãƒ¡ãƒ³ãƒˆã‚¢ã‚¦ãƒˆ + AlphaTest Greater 0.25 + + CGPROGRAM + #pragma vertex shadow_vert + #pragma fragment shadow_frag + #include "UnityCG.cginc" + #include "MeshPmdMaterialShadowVertFrag.cginc" + ENDCG + } + + } + + // Other Environment + Fallback "Transparent/Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial.shader new file mode 100644 index 000000000..92067cd64 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterial.shader @@ -0,0 +1,49 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/PMDMaterial" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // First Pass + Pass + { + Cull Off + } + + // Surface Shader + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + } + + // Other Environment + Fallback "Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialDummy.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialDummy.shader new file mode 100644 index 000000000..2bae6d9cd --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialDummy.shader @@ -0,0 +1,55 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/Dummy" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _Opacity("ä¸é€æ˜Žåº¦", Float) = 1.0 + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _OutlineColor("エッジ色", Color) = (0,0,0,1) + _OutlineWidth("エッジ幅", Range(0,1)) = 0.2 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + + _DummyColor("ダミー色", Color) = (1,0,1,1) + _DummyOriginalShaderType("オリジナルシェーダータイプ", Float) = 0 + } + + SubShader + { + // First Pass + Pass + { + Color[_DummyColor] + Lighting Off + Cull Off + ZWrite On + ZTest LEqual + Offset 0, 0 + AlphaTest Greater 0.0 + } + } + + // Other Environment + Fallback "Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-CullBack-NoCastShadow.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-CullBack-NoCastShadow.shader new file mode 100644 index 000000000..d65ecfce0 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-CullBack-NoCastShadow.shader @@ -0,0 +1,66 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/PMDMaterial-with-Outline-CullBack-NoCastShadow" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _OutlineColor("エッジ色", Color) = (0,0,0,1) + _OutlineWidth("エッジ幅", Range(0,1)) = 0.2 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Settings + Tags + { + "ForceNoShadowCasting" = "True" + } + + // Surface Shader + Cull Back + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // Outline Pass + Pass + { + Cull Front + Lighting Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + #include "MeshPmdMaterialVertFrag.cginc" + ENDCG + } + } + + // Other Environment + Fallback "Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-CullBack.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-CullBack.shader new file mode 100644 index 000000000..ffae90896 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-CullBack.shader @@ -0,0 +1,60 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/PMDMaterial-with-Outline-CullBack" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _OutlineColor("エッジ色", Color) = (0,0,0,1) + _OutlineWidth("エッジ幅", Range(0,1)) = 0.2 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Surface Shader + Cull Back + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // Outline Pass + Pass + { + Cull Front + Lighting Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + #include "MeshPmdMaterialVertFrag.cginc" + ENDCG + } + } + + // Other Environment + Fallback "Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-NoCastShadow.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-NoCastShadow.shader new file mode 100644 index 000000000..ec9ab877f --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-NoCastShadow.shader @@ -0,0 +1,66 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/PMDMaterial-with-Outline-NoCastShadow" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _OutlineColor("エッジ色", Color) = (0,0,0,1) + _OutlineWidth("エッジ幅", Range(0,1)) = 0.2 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Settings + Tags + { + "ForceNoShadowCasting" = "True" + } + + // Surface Shader + Cull Off + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // Outline Pass + Pass + { + Cull Front + Lighting Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + #include "MeshPmdMaterialVertFrag.cginc" + ENDCG + } + } + + // Other Environment + Fallback "Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack-NoCastShadow.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack-NoCastShadow.shader new file mode 100644 index 000000000..01920792f --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack-NoCastShadow.shader @@ -0,0 +1,71 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/Transparent/PMDMaterial-with-Outline-CullBack-NoCastShadow" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _Opacity("ä¸é€æ˜Žåº¦", Float) = 1.0 + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _OutlineColor("エッジ色", Color) = (0,0,0,1) + _OutlineWidth("エッジ幅", Range(0,1)) = 0.2 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Settings + Tags + { + "Queue" = "Transparent" + "RenderType" = "Transparent" + } + + // Surface Shader Pass + Cull Back + ZWrite On + Blend SrcAlpha OneMinusSrcAlpha + AlphaTest Greater 0.0 + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // Outline Pass + Pass + { + Cull Front + Lighting Off + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + #include "MeshPmdMaterialVertFrag.cginc" + ENDCG + } + + } + + // Other Environment + Fallback "Transparent/Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack.shader new file mode 100644 index 000000000..0c30e15a5 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-CullBack.shader @@ -0,0 +1,91 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/Transparent/PMDMaterial-with-Outline-CullBack" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _Opacity("ä¸é€æ˜Žåº¦", Float) = 1.0 + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _OutlineColor("エッジ色", Color) = (0,0,0,1) + _OutlineWidth("エッジ幅", Range(0,1)) = 0.2 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Settings + Tags + { + "Queue" = "Transparent" + "RenderType" = "Transparent" + } + + // Surface Shader Pass + Cull Back + ZWrite On + Blend SrcAlpha OneMinusSrcAlpha + AlphaTest Greater 0.0 + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // Outline Pass + Pass + { + Cull Front + Lighting Off + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + #include "MeshPmdMaterialVertFrag.cginc" + ENDCG + } + + // ShadowCast Pass + Pass + { + Tags + { + "LightMode" = "ShadowCaster" + } + Cull Off + Lighting Off + //Offset [_ShadowBias], [_ShadowBiasSlope] //使ãˆãªã„様ãªã®ã§ã‚³ãƒ¡ãƒ³ãƒˆã‚¢ã‚¦ãƒˆ + AlphaTest Greater 0.25 + + CGPROGRAM + #pragma vertex shadow_vert + #pragma fragment shadow_frag + #include "UnityCG.cginc" + #include "MeshPmdMaterialShadowVertFrag.cginc" + ENDCG + } + + } + + // Other Environment + Fallback "Transparent/Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-NoCastShadow.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-NoCastShadow.shader new file mode 100644 index 000000000..2aa00e5ef --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans-NoCastShadow.shader @@ -0,0 +1,81 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/Transparent/PMDMaterial-with-Outline-NoCastShadow" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _Opacity("ä¸é€æ˜Žåº¦", Float) = 1.0 + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _OutlineColor("エッジ色", Color) = (0,0,0,1) + _OutlineWidth("エッジ幅", Range(0,1)) = 0.2 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Settings + Tags + { + "Queue" = "Transparent" + "RenderType" = "Transparent" + } + + // Surface Shader Pass ( Back ) + Cull Front + ZWrite On + Blend SrcAlpha OneMinusSrcAlpha + AlphaTest Greater 0.0 + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // Surface Shader Pass + Cull Back + ZWrite On + Blend SrcAlpha OneMinusSrcAlpha + AlphaTest Greater 0.0 + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // Outline Pass + Pass + { + Cull Front + Lighting Off + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + #include "MeshPmdMaterialVertFrag.cginc" + ENDCG + } + + } + + // Other Environment + Fallback "Transparent/Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans.shader new file mode 100644 index 000000000..7cfdaaa3d --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline-Trans.shader @@ -0,0 +1,101 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/Transparent/PMDMaterial-with-Outline" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _Opacity("ä¸é€æ˜Žåº¦", Float) = 1.0 + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _OutlineColor("エッジ色", Color) = (0,0,0,1) + _OutlineWidth("エッジ幅", Range(0,1)) = 0.2 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Settings + Tags + { + "Queue" = "Transparent" + "RenderType" = "Transparent" + } + + // Surface Shader Pass ( Back ) + Cull Front + ZWrite On + Blend SrcAlpha OneMinusSrcAlpha + AlphaTest Greater 0.0 + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // Surface Shader Pass + Cull Back + ZWrite On + Blend SrcAlpha OneMinusSrcAlpha + AlphaTest Greater 0.0 + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // Outline Pass + Pass + { + Cull Front + Lighting Off + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + #include "MeshPmdMaterialVertFrag.cginc" + ENDCG + } + + // ShadowCast Pass + Pass + { + Tags + { + "LightMode" = "ShadowCaster" + } + Cull Off + Lighting Off + //Offset [_ShadowBias], [_ShadowBiasSlope] //使ãˆãªã„様ãªã®ã§ã‚³ãƒ¡ãƒ³ãƒˆã‚¢ã‚¦ãƒˆ + AlphaTest Greater 0.25 + + CGPROGRAM + #pragma vertex shadow_vert + #pragma fragment shadow_frag + #include "UnityCG.cginc" + #include "MeshPmdMaterialShadowVertFrag.cginc" + ENDCG + } + + } + + // Other Environment + Fallback "Transparent/Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline.shader b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline.shader new file mode 100644 index 000000000..a42ee4e23 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialOutline.shader @@ -0,0 +1,60 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +Shader "MMD/PMDMaterial-with-Outline" +{ + Properties + { + _Color("拡散色", Color) = (1,1,1,1) + _SpecularColor("å射色", Color) = (1,1,1) + _AmbColor("環境色", Color) = (1,1,1) + _Shininess("å射強度", Float) = 0 + _OutlineColor("エッジ色", Color) = (0,0,0,1) + _OutlineWidth("エッジ幅", Range(0,1)) = 0.2 + _MainTex("テクスãƒãƒ£", 2D) = "white" {} + _ToonTex("トゥーン", 2D) = "white" {} + _SphereAddTex("スフィア(加算)", 2D) = "black" {} + _SphereMulTex("スフィア(乗算)", 2D) = "white" {} + } + + SubShader + { + // Surface Shader + Cull Off + CGPROGRAM + #pragma surface surf MMD + #include "MeshPmdMaterialSurface.cginc" + ENDCG + + // Outline Pass + Pass + { + Cull Front + Lighting Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + #include "MeshPmdMaterialVertFrag.cginc" + ENDCG + } + } + + // Other Environment + Fallback "Diffuse" +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialShadowVertFrag.cginc b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialShadowVertFrag.cginc new file mode 100644 index 000000000..d29f5915f --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialShadowVertFrag.cginc @@ -0,0 +1,42 @@ +// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' + +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +float _Opacity; +sampler2D _MainTex; +float4 _MainTex_ST; + +struct v2f +{ + float4 pos : SV_POSITION; + float2 uv : TEXCOORD0; +}; + +v2f shadow_vert( appdata_img v ) +{ + v2f o; + o.pos = UnityObjectToClipPos(v.vertex); + o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); + return o; +} + +half4 shadow_frag( v2f i ) : COLOR +{ + float4 tex_color = tex2D(_MainTex, i.uv); + return half4(0, 0, 0, tex_color.a * _Opacity); +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialSurface.cginc b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialSurface.cginc new file mode 100644 index 000000000..e02897ec3 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialSurface.cginc @@ -0,0 +1,89 @@ +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +float4 _Color; +float _Opacity; +float4 _AmbColor; +float4 _SpecularColor; +float _Shininess; +sampler2D _MainTex; +sampler2D _ToonTex; +sampler2D _SphereAddTex; +sampler2D _SphereMulTex; + +struct EditorSurfaceOutput +{ + half3 Albedo; + half3 Normal; + half3 Emission; + half3 Gloss; + half Specular; + half Alpha; + half4 Custom; +}; + +inline half4 LightingMMD (EditorSurfaceOutput s, half3 lightDir, half3 viewDir, half atten) +{ + // LightColor revison + float4 lightColor = _LightColor0 * 1.2 * atten; + + // Specular + float specularStrength = s.Specular; + float dirDotNormalHalf = max(0, dot(s.Normal, normalize(lightDir + viewDir))); + float dirSpecularWeight = pow( dirDotNormalHalf, _Shininess ); + float4 dirSpecular = _SpecularColor * lightColor * dirSpecularWeight; + // ToonMap + float lightStrength = dot(lightDir, s.Normal) * 0.5 + 0.5; + float4 toon = tex2D( _ToonTex, float2( specularStrength, lightStrength ) ); + // Output + float4 color = saturate( _AmbColor + ( _Color * lightColor ) ); + color *= s.Custom; + color += saturate(dirSpecular); + color *= toon; + color.a = s.Alpha; + return color; +} + +struct Input +{ + float2 uv_MainTex; +}; + +void surf (Input IN, inout EditorSurfaceOutput o) +{ + // Defaults + o.Albedo = 0.0; + o.Emission = 0.0; + o.Gloss = 0.0; + o.Specular = 0.0; + + // Diffuse Map + float2 uv_coord = float2( IN.uv_MainTex.x, IN.uv_MainTex.y ); + float4 tex_color = tex2D( _MainTex, uv_coord ); + // Sphere Map + float3 viewNormal = normalize( mul( UNITY_MATRIX_MV, float4(normalize(o.Normal), 0.0) ).xyz ); + float2 sphereUv = viewNormal.xy * 0.5 + 0.5; + float4 sphereAdd = tex2D( _SphereAddTex, sphereUv ); + float4 sphereMul = tex2D( _SphereMulTex, sphereUv ); + + // Output + o.Custom = tex_color; // DiffuseTex Default:White + o.Custom += sphereAdd; // SphereAddTex Default:Black + o.Custom *= sphereMul; // SphereMulTex Default:White + o.Custom.a = 1.0; + o.Alpha = _Opacity * tex_color.a; +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialVertFrag.cginc b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialVertFrag.cginc new file mode 100644 index 000000000..e4c735384 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Shaders/MeshPmdMaterialVertFrag.cginc @@ -0,0 +1,45 @@ +// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' + +/* + * MMD Shader for Unity + * + * Copyright 2012 Masataka SUMI, Takahiro INOUE + * + *    Licensed under the Apache License, Version 2.0 (the "License"); + *    you may not use this file except in compliance with the License. + *    You may obtain a copy of the License at + * + *        http://www.apache.org/licenses/LICENSE-2.0 + * + *    Unless required by applicable law or agreed to in writing, software + *    distributed under the License is distributed on an "AS IS" BASIS, + *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *    See the License for the specific language governing permissions and + *    limitations under the License. + */ +float4 _Color; +float _Opacity; +float4 _OutlineColor; +float _OutlineWidth; + +struct v2f +{ + float4 pos : SV_POSITION; + float2 uv : TEXCOORD0; +}; + +v2f vert( appdata_base v ) +{ + v2f o; + float4 pos = UnityObjectToClipPos(v.vertex); + float4 normal = UnityObjectToClipPos(float4(v.normal, 0.0)); + float width = _OutlineWidth / 1024.0; //目コピ調整値(算術根拠無ã—) + float depth_offset = pos.z / 4194304.0; //僅ã‹ã«å¥¥ã«ç§»å‹•(floatã®ä»®æ•°éƒ¨ã¯23bitãªã®ã§(1<<21)程度ã§å‰²ã£ãŸå€¤ã¯ä¸¸ã‚ã«å…¥ã‚‰ãªã„ãŒéžå¸¸ã«å°ã•ãªå€¤ã®ç­ˆ) + o.pos = pos + normal * float4(width, width, 0.0, 0.0) + float4(0.0, 0.0, depth_offset, 0.0); + + return o; +} +half4 frag( v2f i ) : COLOR +{ + return half4( _OutlineColor.rgb, _OutlineColor.a * _Opacity ); +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Toons/toon.png b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Toons/toon.png new file mode 100644 index 000000000..036c4c67c --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PMDMaterial/Toons/toon.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99d41452d43a53aa43dd882804cde1d02e83901ce32c3d5d3b5d6503efe3477e +size 2825 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PhysicsManager.cs b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PhysicsManager.cs new file mode 100644 index 000000000..f4b5b94fa --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/PhysicsManager.cs @@ -0,0 +1,30 @@ +using UnityEngine; +using System.Collections; + +/// +/// ç‰©ç†æ¼”算管ç†(基本的ã«Inspector拡張用ã«ä»˜åŠ ã™ã‚‹ã ã‘ã§ã€ã“ã®ã‚¯ãƒ©ã‚¹è‡ªä½“ã¯ä½•ã‚‚ã—ãªã„) +/// +public class PhysicsManager : MonoBehaviour { + + /// + /// åˆå›žæ›´æ–°å‰å‡¦ç† + /// + public void Start() + { + //å†ç”Ÿæ™‚ã«ã¯ä¸è¦ãªã®ã§ã€ãƒ“ルド版ã§ã¯å‰Šé™¤ + connect_bone_list = null; + } + + /// + /// Physicsã«ç§»å‹•ã™ã‚‹å‰ã®GameObject + /// + [System.Serializable] + public class ConnectBone { + public GameObject joint; + public GameObject parent; + + public ConnectBone(GameObject j = null, GameObject p = null) {joint = j; parent = p;} + } + + public ConnectBone[] connect_bone_list = null; // Physicsã«ç§»å‹•ã™ã‚‹å‰ã®GameObjectリスト +} diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon00.bmp b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon00.bmp new file mode 100644 index 000000000..44b11ee67 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon00.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b03c8464c66f7359f303a0d3f00e7d5570159fb3b8fe3c712095e59ef75ff4a0 +size 3126 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon01.bmp b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon01.bmp new file mode 100644 index 000000000..5f7b4434b --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon01.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e2da47c174dbbd0befb547346bdbeed36fa5daa74898ad261bd6720dce31302 +size 3128 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon02.bmp b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon02.bmp new file mode 100644 index 000000000..2ca1e76d2 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon02.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af1246cd9cf57d833f0eccc1fadbe7c7f88baddf3173bc103d373c2e3e82aed1 +size 3128 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon03.bmp b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon03.bmp new file mode 100644 index 000000000..dbc8ec368 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon03.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4268976ada66f2a7c3b5fd84c29d1183fd6069c2fdf2ce5c424f815a2680f25c +size 3128 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon04.bmp b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon04.bmp new file mode 100644 index 000000000..155218b2d --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon04.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e30ab164bc574241f2ac6c12172b6c75799afe5a03d4eb5cdb43c223f23de6e +size 3128 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon05.bmp b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon05.bmp new file mode 100644 index 000000000..c039c6658 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon05.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef1b687f0e5bbc6cd32909f8ebf890fd72cb1b704ebdf366fb7a4e3f8b1fae08 +size 3126 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon06.bmp b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon06.bmp new file mode 100644 index 000000000..4d9fbc334 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon06.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8811f63ecd91f8ff5cc7347011b2cc74c9ff028b1b08bd6438dab03ae9bf8f8 +size 3126 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon07.bmp b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon07.bmp new file mode 100644 index 000000000..44b11ee67 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon07.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b03c8464c66f7359f303a0d3f00e7d5570159fb3b8fe3c712095e59ef75ff4a0 +size 3126 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon08.bmp b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon08.bmp new file mode 100644 index 000000000..44b11ee67 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon08.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b03c8464c66f7359f303a0d3f00e7d5570159fb3b8fe3c712095e59ef75ff4a0 +size 3126 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon09.bmp b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon09.bmp new file mode 100644 index 000000000..44b11ee67 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon09.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b03c8464c66f7359f303a0d3f00e7d5570159fb3b8fe3c712095e59ef75ff4a0 +size 3126 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon10.bmp b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon10.bmp new file mode 100644 index 000000000..44b11ee67 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/Resources/toon/toon10.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b03c8464c66f7359f303a0d3f00e7d5570159fb3b8fe3c712095e59ef75ff4a0 +size 3126 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/logo.png b/Assets/Scripts/3rd/mmd-for-unity-master/logo.png new file mode 100644 index 000000000..3cc24a1d0 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/logo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0675c867c814f858dbb3d1359be39e0d03326f9edae2e5edd97bea6748322e3a +size 14479 diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/readme.html b/Assets/Scripts/3rd/mmd-for-unity-master/readme.html new file mode 100644 index 000000000..f094ee2ea --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/readme.html @@ -0,0 +1,129 @@ + + +MikuMikuDance for Unity - readme + + + + +
+ MikuMikuDance for Unity + +

+ + logo +
+ +


+ +
–ÚŽŸ

+
+ +


+ +
MikuMikuDance for Unity?
+
+ MikuMikuDance for Unity‚Æ‚ÍAƒQ[ƒ€ƒGƒ“ƒWƒ“‚ÌUnityã‚ÅMikuMikuDance‚̃‚ƒfƒ‹ƒf[ƒ^‚ð“®‚©‚µ‚½‚èA + ‚ ‚é‚¢‚ÍMikuMikuDance‚ł̧ì‚ðƒTƒ|[ƒg‚·‚éƒvƒƒWƒFƒNƒg‚Ì–¼‘O‚Å‚·B + MikuMikuDance for Unity‚ÍUnity‚ÅMMD‚ð“®‚©‚·‰ï‚É‚æ‚Á‚ĉ^‰c‚³‚êAŠJ”­‚ªs‚í‚ê‚Ä‚¢‚Ü‚·B +
+ +


+ +
Žg‚¢•û
+
+ MikuMikuDance for Unity‚ÌŽg‚¢•û‚ÉŠÖ‚·‚é“®‰æ‚Å‚·B
+ + +

+ —LŽu‚Ì•û‚É‚æ‚èAŽg‚¢•û‚âƒQ[ƒ€‚Ìì‚è•û‚àŠÜ‚߂ăuƒƒO“™‚ł܂Ƃ߂ç‚ê‚Ä‚¢‚Ü‚·B + ì‚邯‚«‚ÌŽQl‚É‚µ‚Ä‚­‚¾‚³‚¢B
+ + ŒŸõuMMD for Unity Žg‚¢•ûv + iŠO•”ƒŠƒ“ƒNj +
+ +


+ +
MikuMikuDance for Unity‚Ì’†g
+
+ MikuMikuDance for Unity‚Ɋ܂܂ê‚éƒpƒbƒP[ƒW‚͈ȉº‚Ì’Ê‚è‚Å‚·B +
    +
  • MMD Loader
  • +
  • XFile Importer
  • +
  • Resources
  • +
+
MMD Loader
+
+ MMD Loader‚É‚Í2Ží—ނ̃XƒNƒŠƒvƒg‚ª‚ ‚è‚Ü‚·B + MikuMikuDance‚ňµ‚í‚ê‚郂ƒfƒ‹ƒf[ƒ^‚ð“ǂݞ‚ÞPMD Loader‚ƃ‚[ƒVƒ‡ƒ“ƒf[ƒ^‚ð“ǂݞ‚ÞVMD Loader‚Å‚·B + “ǂݞ‚ñ‚¾ƒf[ƒ^‚̓vƒŒƒnƒu‰»‚³‚êAUnity‚ňµ‚¦‚éŒ`Ž®‚ɕϊ·‚³‚ê‚Ü‚·B +
+
XFile Importer
+
+ Google Sketchup‚ŕϊ·‚³‚ꂽXƒtƒ@ƒCƒ‹Œ`Ž®‚̃‚ƒfƒ‹ƒf[ƒ^‚ð“ǂݞ‚ÞƒXƒNƒŠƒvƒg‚Å‚·B + •ÏŠ·•û–@‚ɂ‚¢‚Ă͈ȉº‚Ì“®‰æ‚ðŽQl‚É‚µ‚Ä‚­‚¾‚³‚¢B +

+ +

+ iƒvƒ‰ƒOƒCƒ“‚ÉŠÖ‚µ‚Ă͓®‰æƒRƒƒ“ƒg‰º•”‚̃IƒXƒXƒ‚̃vƒ‰ƒOƒCƒ“‚ðŽg—p‚µ‚Ä‚­‚¾‚³‚¢B‚»‚êˆÈŠO‚̃vƒ‰ƒOƒCƒ“‚Í¡‚̂Ƃ±‚ë‘Ήž‚µ‚Ä‚¢‚Ü‚¹‚ñj +
+
Resources
+
+ “®“I‚ɒljÁ‚·‚邽‚߂ɕK—v‚ȃAƒZƒbƒg‚ð“ü‚ê‚Ä‚ ‚è‚Ü‚·B +
+
+ +


+ +
ƒ‚ƒfƒ‹‚Ì—˜—p‚ÉŠÖ‚µ‚Ä
+
+ MikuMikuDance for Unity‚Í‚ ‚ɂ܂³Ž‚Ì‹–‰Â‚Ì‚à‚ÆA + MikuMikuDance‚É•t‘®‚µ‚Ä‚¢‚郂ƒfƒ‹ƒf[ƒ^‚ð–³§ŒÀ‚ł̗˜—p‚ª”F‚ß‚ç‚ê‚Ä‚¢‚Ü‚·B + ƒ‚ƒfƒ‹‹y‚у‚[ƒVƒ‡ƒ“ƒf[ƒ^‚Ì—˜—p‚ÉŠÖ‚·‚éƒKƒCƒhƒ‰ƒCƒ“‚ÍMikuMikuDance‚É€‹’‚µ‚Ä‚¢‚Ü‚·B + ƒpƒbƒP[ƒW“à‚Ɋ܂܂ê‚È‚¢ƒ‚ƒfƒ‹‹y‚у‚[ƒVƒ‡ƒ“‚Ȃǂ̃f[ƒ^‚Ì—˜—p‚ÉŠÖ‚µ‚Ä‚Í쬎҂Ƃ̋¦‹c‚ÌãA—˜—p‚µ‚Ä‚­‚¾‚³‚¢B +
+ +


+ +
ƒ‰ƒCƒZƒ“ƒX
+
+ ‰ü•ÏEÄ”z•z‚ÍŽ©—R‚Å‚·B
+ —˜—p‚µ‚½ê‡‚Ì•ñ‚Í“Á‚É•K—v‚ ‚è‚Ü‚¹‚ñB
+ C³BSDƒ‰ƒCƒZƒ“ƒX‚É€‹’‚µ‚Ä‚¢‚Ü‚·‚ªAƒ‰ƒCƒZƒ“ƒX‘S•¶‚ÉŠÖ‚µ‚Ä‚Ílicense.txt‚ðŽQÆ‚µ‚Ä‚­‚¾‚³‚¢B +
+ +


+ +
–ÆÓ
+
+ MikuMikuDance for Unity‚̓Q[ƒ€§ì‹y‚ÑMikuMikuDance‚É‚æ‚é“®‰æ§ì‚ðŽx‰‡‚·‚邽‚߂ɊJ”­‚³‚ꂽƒ‰ƒCƒuƒ‰ƒŠ‚Å‚·‚ªA + —˜—pŽÒ‚Ì—˜—p•û–@‚É‚¨‚¢‚Ä”í‚Á‚½‘¹ŠQ‚ɂ‚¢‚Ä‚ÍUnity‚ÅMMD‚ð“®‚©‚·‰ï‹y‚Ñ’|Ÿº‰lˆêiGRGSIBERIAj‚Í‚»‚ÌÓ”C‚𕉂¢‚Ü‚¹‚ñB + MikuMikuDance for Unity‚Í—˜—pŽÒ‚²Ž©g‚Ì”»’f‚ÆÓ”C‚É‚¨‚¢‚Ä—˜—p‚µ‚Ä‚¢‚½‚¾‚­‚à‚̂Ƃµ‚Ü‚·B
+ ‚Ü‚½A—˜—pŽÒ‚ªƒ‚ƒfƒ‹‹y‚у‚[ƒVƒ‡ƒ“‚Ȃǂ̗˜—p•û–@‚É‚¨‚¢‚Ä”í‚Á‚½‘¹ŠQ‚ɂ‚¢‚Ä‚à“¯—l‚Æ’v‚µ‚Ü‚·B +
+ +


+ +
+ + (C) Unity‚ÅMMD‚ð“®‚©‚·‰ï
+ - TOP‚Ö - +
+
+ + + \ No newline at end of file diff --git a/Assets/Scripts/3rd/mmd-for-unity-master/tutorial.md b/Assets/Scripts/3rd/mmd-for-unity-master/tutorial.md new file mode 100644 index 000000000..6170b9e10 --- /dev/null +++ b/Assets/Scripts/3rd/mmd-for-unity-master/tutorial.md @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:389e809010cef99787f5bd045f42b9fe22a40859fc9e330c465ab7a2babc1a14 +size 8514 diff --git a/Assets/Scripts/AssetBatchRenamer.cs b/Assets/Scripts/AssetBatchRenamer.cs new file mode 100644 index 000000000..9418da4be --- /dev/null +++ b/Assets/Scripts/AssetBatchRenamer.cs @@ -0,0 +1,89 @@ +using UnityEngine; +using UnityEditor; +using System.IO; +using System.Collections.Generic; + +public class AssetBatchRenamer : EditorWindow +{ + int removeFrontCount = 0; + int removeBackCount = 0; + string prefixToAdd = ""; + string suffixToAdd = ""; + + [MenuItem("Tools/Asset Batch Renamer")] + public static void ShowWindow() + { + GetWindow("Asset Batch Renamer"); + } + + void OnGUI() + { + GUILayout.Label("ì„ íƒí•œ ì—ì…‹ ì´ë¦„ ì¼ê´„ 수정", EditorStyles.boldLabel); + + removeFrontCount = EditorGUILayout.IntField("앞ì—서 제거할 ë¬¸ìž ìˆ˜", removeFrontCount); + removeBackCount = EditorGUILayout.IntField("ë’¤ì—서 제거할 ë¬¸ìž ìˆ˜", removeBackCount); + prefixToAdd = EditorGUILayout.TextField("ì•žì— ì¶”ê°€í•  문ìžì—´", prefixToAdd); + suffixToAdd = EditorGUILayout.TextField("ë’¤ì— ì¶”ê°€í•  문ìžì—´", suffixToAdd); + + if (GUILayout.Button("ì„ íƒëœ ì—ì…‹ ì´ë¦„ 변경")) + { + RenameSelectedAssets(); + } + } + + void RenameSelectedAssets() + { + Object[] selectedObjects = Selection.objects; + Dictionary nameConflictMap = new Dictionary(); + + Undo.RecordObjects(selectedObjects, "Batch Rename Assets"); + + foreach (Object obj in selectedObjects) + { + string assetPath = AssetDatabase.GetAssetPath(obj); + string assetName = Path.GetFileNameWithoutExtension(assetPath); + string assetExtension = Path.GetExtension(assetPath); + string assetDir = Path.GetDirectoryName(assetPath); + + string newName = assetName; + + // 앞 ë¬¸ìž ì œê±° + if (removeFrontCount > 0 && newName.Length > removeFrontCount) + newName = newName.Substring(removeFrontCount); + + // ë’¤ ë¬¸ìž ì œê±° + if (removeBackCount > 0 && newName.Length > removeBackCount) + newName = newName.Substring(0, newName.Length - removeBackCount); + + // 앞뒤 추가 + newName = prefixToAdd + newName + suffixToAdd; + + // ì´ë¦„ ì¶©ëŒ ë°©ì§€ 처리 + string finalName = newName; + int counter = 1; + while (AssetExists(assetDir, finalName, assetExtension) && finalName != assetName) + { + finalName = newName + "_" + counter; + counter++; + } + + if (finalName != assetName) + { + string result = AssetDatabase.RenameAsset(assetPath, finalName); + if (!string.IsNullOrEmpty(result)) + { + Debug.LogWarning($"[{obj.name}] ì´ë¦„ 변경 실패: {result}"); + } + } + } + + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + + bool AssetExists(string directory, string name, string extension) + { + string fullPath = Path.Combine(directory, name + extension).Replace("\\", "/"); + return AssetDatabase.LoadAssetAtPath(fullPath) != null; + } +} diff --git a/Assets/Scripts/AssetBatchRenamer.cs.meta b/Assets/Scripts/AssetBatchRenamer.cs.meta new file mode 100644 index 000000000..5fcf5c645 --- /dev/null +++ b/Assets/Scripts/AssetBatchRenamer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 3ab2d3837e4d1874a9bfe3986e13179e \ No newline at end of file diff --git a/Assets/Scripts/AvatarComponetCopier.cs b/Assets/Scripts/AvatarComponetCopier.cs new file mode 100644 index 000000000..0aa7cdb94 --- /dev/null +++ b/Assets/Scripts/AvatarComponetCopier.cs @@ -0,0 +1,755 @@ +using UnityEngine; +using UnityEditor; +using System.Linq; +using System.Collections.Generic; +using VRM; +using MagicaCloth2; +using MagicaClothType = MagicaCloth2.MagicaCloth; +using UnityEngine.Animations; + +public class AvatarComponetCopier : EditorWindow +{ + GameObject sourcePrefab; + GameObject destinationPrefab; + bool showHumanoidBoneInfo = false; + Dictionary sourceHumanoidBones = new Dictionary(); + Dictionary targetHumanoidBones = new Dictionary(); + Vector2 scrollPosition = Vector2.zero; + + [MenuItem("Tools/Avatar Component Mover (SpringBone+MagicaCloth2)")] + static void ShowWindow() + { + GetWindow("Avatar Component Mover"); + } + + void OnGUI() + { + // 스í¬ë¡¤ë·° 시작 + scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); + + GUILayout.Label("Move VRMSpringBone/MagicaCloth2 & Collider Components", EditorStyles.boldLabel); + + sourcePrefab = (GameObject)EditorGUILayout.ObjectField("Source Object", sourcePrefab, typeof(GameObject), true); + destinationPrefab = (GameObject)EditorGUILayout.ObjectField("Target Object", destinationPrefab, typeof(GameObject), true); + + if (GUILayout.Button("휴머노ì´ë“œ 본 구조 확ì¸")) + { + if (sourcePrefab == null || destinationPrefab == null) + { + EditorUtility.DisplayDialog("Error", "Source and Target Objects must be set.", "OK"); + return; + } + CheckHumanoidStructure(); + } + + if (showHumanoidBoneInfo) + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField("휴머노ì´ë“œ 본 ì •ë³´", EditorStyles.boldLabel); + + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + EditorGUILayout.LabelField("소스 아바타 본 ì •ë³´:"); + foreach (var bone in sourceHumanoidBones) + { + if (bone.Value != null) + { + EditorGUILayout.LabelField($"{bone.Key}: {bone.Value.name}"); + } + } + EditorGUILayout.EndVertical(); + + EditorGUILayout.Space(); + + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + EditorGUILayout.LabelField("타겟 아바타 본 ì •ë³´:"); + foreach (var bone in targetHumanoidBones) + { + if (bone.Value != null) + { + EditorGUILayout.LabelField($"{bone.Key}: {bone.Value.name}"); + } + } + EditorGUILayout.EndVertical(); + } + + if (GUILayout.Button("휴머노ì´ë“œ 본 하위 콜ë¼ì´ë” ì´ë™")) + { + if (sourcePrefab == null || destinationPrefab == null) + { + EditorUtility.DisplayDialog("Error", "Source and Target Objects must be set.", "OK"); + return; + } + MoveCollidersUnderHumanoidBones(); + } + + if (GUILayout.Button("Spring본콜ë¼ì´ë” 복사")) + { + if (sourcePrefab == null || destinationPrefab == null) + { + EditorUtility.DisplayDialog("Error", "Source and Target Objects must be set.", "OK"); + return; + } + CopySpringBoneAndMagicaColliders(); + } + + if (GUILayout.Button("Spring본/Cloth 옮기기")) + { + if (sourcePrefab == null || destinationPrefab == null) + { + EditorUtility.DisplayDialog("Error", "Source and Target Objects must be set.", "OK"); + return; + } + MoveSpringBonesAndMagicaCloth(); + } + + if (GUILayout.Button("Constraint ê°’ 복사")) + { + if (sourcePrefab == null || destinationPrefab == null) + { + EditorUtility.DisplayDialog("Error", "Source and Target Objects must be set.", "OK"); + return; + } + CopyConstraints(); + } + + if (GUILayout.Button("BlendShapeCopy")) + { + if (sourcePrefab == null || destinationPrefab == null) + { + EditorUtility.DisplayDialog("Error", "Source and Target Objects must be set.", "OK"); + return; + } + CopyBlendShapes(); + } + + if (GUILayout.Button("ActiveStateCopy")) + { + if (sourcePrefab == null || destinationPrefab == null) + { + EditorUtility.DisplayDialog("Error", "Source and Target Objects must be set.", "OK"); + return; + } + CopyActiveStates(); + } + + // 스í¬ë¡¤ë·° ë + EditorGUILayout.EndScrollView(); + } + + void CheckHumanoidStructure() + { + sourceHumanoidBones.Clear(); + targetHumanoidBones.Clear(); + + var sourceAnimator = sourcePrefab.GetComponent(); + var targetAnimator = destinationPrefab.GetComponent(); + + if (sourceAnimator == null || targetAnimator == null) + { + EditorUtility.DisplayDialog("Error", "소스와 타겟 오브ì íЏ ëª¨ë‘ Animator ì»´í¬ë„ŒíŠ¸ê°€ 필요합니다.", "OK"); + return; + } + + if (!sourceAnimator.isHuman || !targetAnimator.isHuman) + { + EditorUtility.DisplayDialog("Error", "소스와 타겟 오브ì íЏ ëª¨ë‘ Humanoid íƒ€ìž…ì˜ ì•„ë°”íƒ€ê°€ 필요합니다.", "OK"); + return; + } + + // 모든 휴머노ì´ë“œ ë³¸ì— ëŒ€í•´ 매핑 + foreach (HumanBodyBones bone in System.Enum.GetValues(typeof(HumanBodyBones))) + { + if (bone == HumanBodyBones.LastBone) continue; + + var sourceBone = sourceAnimator.GetBoneTransform(bone); + var targetBone = targetAnimator.GetBoneTransform(bone); + + if (sourceBone != null) + sourceHumanoidBones[bone] = sourceBone; + if (targetBone != null) + targetHumanoidBones[bone] = targetBone; + } + + showHumanoidBoneInfo = true; + Debug.Log("휴머노ì´ë“œ 본 구조 확ì¸ì´ 완료ë˜ì—ˆìŠµë‹ˆë‹¤."); + } + + void MoveCollidersUnderHumanoidBones() + { + if (sourceHumanoidBones.Count == 0 || targetHumanoidBones.Count == 0) + { + EditorUtility.DisplayDialog("Error", "먼저 휴머노ì´ë“œ 본 구조를 확ì¸í•´ì£¼ì„¸ìš”.", "OK"); + return; + } + + Debug.Log("콜ë¼ì´ë” ì´ë™ 시작..."); + + // 소스 ì•„ë°”íƒ€ì˜ ê° íœ´ë¨¸ë…¸ì´ë“œ ë³¸ì— ëŒ€í•´ + foreach (var sourceBone in sourceHumanoidBones) + { + if (sourceBone.Value == null) continue; + + Debug.Log($"소스 본 검사 중: {sourceBone.Key} ({sourceBone.Value.name})"); + + // 타겟 아바타ì—서 ë™ì¼í•œ HumanBodyBones를 가진 본 찾기 + if (!targetHumanoidBones.TryGetValue(sourceBone.Key, out Transform targetBone)) + { + Debug.LogWarning($"타겟 아바타ì—서 {sourceBone.Key}ì— í•´ë‹¹í•˜ëŠ” ë³¸ì„ ì°¾ì„ ìˆ˜ 없습니다."); + continue; + } + + Debug.Log($"대ì‘ë˜ëŠ” 타겟 본 ì°¾ìŒ: {targetBone.name}"); + + // 소스 ë³¸ì˜ ì§ì ‘ì ì¸ ìžì‹ 오브ì íŠ¸ë§Œ 검사 + for (int i = 0; i < sourceBone.Value.childCount; i++) + { + var child = sourceBone.Value.GetChild(i); + Debug.Log($"ìžì‹ 오브ì íЏ 검사 중: {child.name}"); + + // VRMSpringBoneColliderGroup 검사 + var springCollider = child.GetComponent(); + if (springCollider != null) + { + Debug.Log($"VRMSpringBoneColliderGroup 발견: {child.name}"); + MoveColliderObject(child, sourceBone.Value, targetBone); + continue; + } + + // MagicaCapsuleCollider 검사 + var magicaCollider = child.GetComponent(); + if (magicaCollider != null) + { + Debug.Log($"MagicaCapsuleCollider 발견: {child.name}"); + MoveColliderObject(child, sourceBone.Value, targetBone); + continue; + } + } + } + + Debug.Log("휴머노ì´ë“œ 본 하위 콜ë¼ì´ë” ì´ë™ì´ 완료ë˜ì—ˆìŠµë‹ˆë‹¤."); + } + + void MoveColliderObject(Transform colliderObject, Transform sourceBone, Transform targetBone) + { + // 타겟 본ì—서 ë™ì¼í•œ ì´ë¦„ì˜ ìžì‹ì´ 있는지 í™•ì¸ + var existingCollider = targetBone.Find(colliderObject.name); + if (existingCollider != null) + { + Debug.LogWarning($"타겟 본 {targetBone.name}ì— ì´ë¯¸ {colliderObject.name}ì´(ê°€) 존재합니다."); + return; + } + + // 콜ë¼ì´ë” ì´ë™ + var originalParent = colliderObject.parent; + var originalPosition = colliderObject.position; + var originalRotation = colliderObject.rotation; + var originalScale = colliderObject.localScale; + + Debug.Log($"콜ë¼ì´ë” ì´ë™ 시ë„: {colliderObject.name}"); + Debug.Log($"- ì›ëž˜ 부모: {originalParent.name}"); + Debug.Log($"- ì›ëž˜ 위치: {originalPosition}"); + Debug.Log($"- ì›ëž˜ 회전: {originalRotation.eulerAngles}"); + Debug.Log($"- ì›ëž˜ í¬ê¸°: {originalScale}"); + + colliderObject.SetParent(targetBone, true); + colliderObject.position = originalPosition; + colliderObject.rotation = originalRotation; + colliderObject.localScale = originalScale; + + Debug.Log($"콜ë¼ì´ë” {colliderObject.name}를 {sourceBone.name}ì—서 {targetBone.name}로 ì´ë™í–ˆìŠµë‹ˆë‹¤."); + Debug.Log($"- 새로운 부모: {colliderObject.parent.name}"); + Debug.Log($"- 새로운 위치: {colliderObject.position}"); + Debug.Log($"- 새로운 회전: {colliderObject.rotation.eulerAngles}"); + Debug.Log($"- 새로운 í¬ê¸°: {colliderObject.localScale}"); + } + + string GetRelativePath(Transform target, Transform root) + { + if (target == root) return ""; + var path = target.name; + while (target.parent != null && target.parent != root) + { + target = target.parent; + path = target.name + "/" + path; + } + return path; + } + + void CopySpringBoneAndMagicaColliders() + { + // VRMSpringBoneColliderGroup + var srcColliders = sourcePrefab.GetComponentsInChildren(true) + .OrderBy(c => GetTransformPath(c.transform, sourcePrefab.transform)).ToArray(); + foreach (var srcCollider in srcColliders) + { + string path = GetTransformPath(srcCollider.transform, sourcePrefab.transform); + var tgtTransform = destinationPrefab.transform.Find(path); + if (tgtTransform == null) continue; + if (tgtTransform.GetComponent() != null) continue; + var tgtCollider = tgtTransform.gameObject.AddComponent(); + CopyColliderGroupParameters(srcCollider, tgtCollider); + } + // MagicaCloth2 Colliders + CopyMagicaCollider(); + CopyMagicaCollider(); + CopyMagicaCollider(); + Debug.Log("VRMSpringBoneColliderGroup & MagicaCloth2 Collider 복사가 완료ë˜ì—ˆìŠµë‹ˆë‹¤."); + } + + void CopyMagicaCollider() where T : Component + { + var srcColliders = sourcePrefab.GetComponentsInChildren(true) + .OrderBy(c => GetTransformPath(((Component)c).transform, sourcePrefab.transform)).ToArray(); + foreach (var srcCollider in srcColliders) + { + var srcTr = ((Component)srcCollider).transform; + string path = GetTransformPath(srcTr, sourcePrefab.transform); + var tgtTransform = destinationPrefab.transform.Find(path); + if (tgtTransform == null) continue; + if (tgtTransform.GetComponent() != null) continue; + var tgtCollider = tgtTransform.gameObject.AddComponent(); + CopyMagicaColliderComponents(srcCollider, tgtCollider); + } + } + + void CopyMagicaColliderComponents(Component src, Component tgt) + { + var fields = src.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + foreach (var field in fields) + { + var value = field.GetValue(src); + if (typeof(UnityEngine.Object).IsAssignableFrom(field.FieldType)) + { + Object refObj = value as Object; + if (refObj == null) { field.SetValue(tgt, null); continue; } + if (refObj is Transform tr) + { + string refPath = GetTransformPath(tr, sourcePrefab.transform); + var tgtTr = destinationPrefab.transform.Find(refPath); + if (tgtTr != null) + field.SetValue(tgt, tgtTr); + } + else if (refObj is GameObject go) + { + string refPath = GetTransformPath(go.transform, sourcePrefab.transform); + var tgtGo = destinationPrefab.transform.Find(refPath); + if (tgtGo != null) + field.SetValue(tgt, tgtGo.gameObject); + } + else if (refObj is Component comp) + { + string refPath = GetTransformPath(comp.gameObject.transform, sourcePrefab.transform); + var tgtGo = destinationPrefab.transform.Find(refPath); + if (tgtGo != null) + { + var tgtComps = tgtGo.GetComponents(comp.GetType()); + int compIdx = comp.gameObject.GetComponents(comp.GetType()).ToList().IndexOf(comp); + if (compIdx >= 0 && compIdx < tgtComps.Length) + field.SetValue(tgt, tgtComps[compIdx]); + } + } + else + { + // 기타 UnityEngine.Object íƒ€ìž…ì€ ê·¸ëŒ€ë¡œ 복사 + field.SetValue(tgt, refObj); + } + } + else + { + // ê°’ 타입, enum, string ë“±ì€ ê·¸ëŒ€ë¡œ 복사 + field.SetValue(tgt, value); + } + } + } + + void MoveSpringBonesAndMagicaCloth() + { + // VRMSpringBone + var srcSpringBones = sourcePrefab.GetComponentsInChildren(true) + .OrderBy(s => GetTransformPath(s.transform, sourcePrefab.transform)).ToArray(); + foreach (var srcSpringBone in srcSpringBones) + { + string path = GetTransformPath(srcSpringBone.transform, sourcePrefab.transform); + var tgtTransform = destinationPrefab.transform.Find(path); + if (tgtTransform == null) continue; + var tgtSpringBone = tgtTransform.gameObject.AddComponent(); + CopyVRMSpringBoneComponents(srcSpringBone, tgtSpringBone); + DestroyImmediate(srcSpringBone); + } + // MagicaCloth + var srcMagicaCloths = sourcePrefab.GetComponentsInChildren(true) + .OrderBy(s => GetTransformPath(s.transform, sourcePrefab.transform)).ToArray(); + foreach (var srcCloth in srcMagicaCloths) + { + string path = GetTransformPath(srcCloth.transform, sourcePrefab.transform); + var tgtTransform = destinationPrefab.transform.Find(path); + if (tgtTransform == null) continue; + var tgtCloth = tgtTransform.gameObject.AddComponent(); + CopyMagicaClothComponents(srcCloth, tgtCloth); + DestroyImmediate(srcCloth); + } + Debug.Log("VRMSpringBone & MagicaCloth 옮기기가 완료ë˜ì—ˆìŠµë‹ˆë‹¤."); + } + + void CopyColliderGroupParameters(VRMSpringBoneColliderGroup source, VRMSpringBoneColliderGroup target) + { + target.Colliders = source.Colliders.Select(c => new VRMSpringBoneColliderGroup.SphereCollider + { + Offset = c.Offset, + Radius = c.Radius + }).ToArray(); + } + + void CopyVRMSpringBoneComponents(VRMSpringBone original, VRMSpringBone copy) + { + copy.m_comment = original.m_comment; + copy.m_stiffnessForce = original.m_stiffnessForce; + copy.m_gravityPower = original.m_gravityPower; + copy.m_gravityDir = original.m_gravityDir; + copy.m_dragForce = original.m_dragForce; + copy.m_center = FindCorrespondingTransform(original.m_center, destinationPrefab.transform); + copy.m_hitRadius = original.m_hitRadius; + copy.m_updateType = original.m_updateType; + + copy.RootBones = original.RootBones + .Select(bone => FindCorrespondingTransform(bone, destinationPrefab.transform)) + .Where(t => t != null) + .ToList(); + + copy.ColliderGroups = original.ColliderGroups + .Select(colliderGroup => FindCorrespondingColliderGroup(colliderGroup, destinationPrefab.transform)) + .Where(cg => cg != null) + .ToArray(); + } + + Transform FindCorrespondingTransform(Transform original, Transform searchRoot) + { + if (original == null) return null; + var path = GetTransformPath(original, sourcePrefab.transform); + return searchRoot.Find(path); + } + + string GetTransformPath(Transform current, Transform root) + { + if (current == root) return ""; + var path = current.name; + while (current.parent != null && current.parent != root) + { + current = current.parent; + path = current.name + "/" + path; + } + return path; + } + + VRMSpringBoneColliderGroup FindCorrespondingColliderGroup(VRMSpringBoneColliderGroup original, Transform searchRoot) + { + if (original == null) return null; + var path = GetTransformPath(original.transform, sourcePrefab.transform); + var correspondingTransform = searchRoot.Find(path); + return correspondingTransform != null ? correspondingTransform.GetComponent() : null; + } + + void CopyMagicaClothComponents(MagicaClothType src, MagicaClothType tgt) + { + var fields = typeof(MagicaClothType).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + foreach (var field in fields) + { + var value = field.GetValue(src); + // ClothType ìš°ì„  복사 ë° ë¶„ê¸° 처리 + if (field.Name == "serializeData" && value is MagicaCloth2.ClothSerializeData sdata) + { + var tdata = new MagicaCloth2.ClothSerializeData(); + // ClothTypeì„ ë¨¼ì € 복사 + tdata.clothType = sdata.clothType; + // ClothTypeì— ë”°ë¼ ë¶„ê¸° + if (sdata.clothType == MagicaCloth2.ClothProcess.ClothType.MeshCloth) + { + // sourceRenderers 복사 + tdata.sourceRenderers = sdata.sourceRenderers + .Select(r => { + if (r == null) return null; + string path = GetTransformPath(r.transform, sourcePrefab.transform); + var tgtTr = destinationPrefab.transform.Find(path); + return tgtTr ? tgtTr.GetComponent() : null; + }) + .Where(r => r != null) + .ToList(); + } + else if (sdata.clothType == MagicaCloth2.ClothProcess.ClothType.BoneCloth || sdata.clothType == MagicaCloth2.ClothProcess.ClothType.BoneSpring) + { + // rootBones 복사 + tdata.rootBones = sdata.rootBones + .Select(bone => FindCorrespondingTransform(bone, destinationPrefab.transform)) + .Where(t => t != null) + .ToList(); + } + // colliderCollisionConstraint 복사 + if (sdata.colliderCollisionConstraint != null) + { + var srcCol = sdata.colliderCollisionConstraint; + var tgtCol = new MagicaCloth2.ColliderCollisionConstraint.SerializeData(); + tgtCol.mode = srcCol.mode; + tgtCol.friction = srcCol.friction; + tgtCol.limitDistance = srcCol.limitDistance; + // colliderList 변환 + tgtCol.colliderList = srcCol.colliderList + .Select(c => { + if (c == null) return null; + string path = GetTransformPath(c.transform, sourcePrefab.transform); + var tgtTr = destinationPrefab.transform.Find(path); + return tgtTr ? tgtTr.GetComponent() : null; + }) + .Where(c => c != null) + .ToList(); + // collisionBones 변환 + tgtCol.collisionBones = srcCol.collisionBones + .Select(bone => FindCorrespondingTransform(bone, destinationPrefab.transform)) + .Where(t => t != null) + .ToList(); + tdata.colliderCollisionConstraint = tgtCol; + } + // 공통 필드 복사 + tdata.paintMaps = new List(sdata.paintMaps); + tdata.paintMode = sdata.paintMode; + tdata.connectionMode = sdata.connectionMode; + tdata.rotationalInterpolation = sdata.rotationalInterpolation; + tdata.rootRotation = sdata.rootRotation; + tdata.updateMode = sdata.updateMode; + tdata.animationPoseRatio = sdata.animationPoseRatio; + tdata.reductionSetting = sdata.reductionSetting; + tdata.customSkinningSetting = sdata.customSkinningSetting; + tdata.normalAlignmentSetting = sdata.normalAlignmentSetting; + tdata.cullingSettings = sdata.cullingSettings; + tdata.normalAxis = sdata.normalAxis; + tdata.gravity = sdata.gravity; + tdata.gravityDirection = sdata.gravityDirection; + tdata.gravityFalloff = sdata.gravityFalloff; + tdata.stablizationTimeAfterReset = sdata.stablizationTimeAfterReset; + tdata.blendWeight = sdata.blendWeight; + tdata.damping = sdata.damping; + tdata.radius = sdata.radius; + // 기타 ê°’ë“¤ë„ í•„ìš”ì‹œ 추가 복사 + field.SetValue(tgt, tdata); + continue; + } + if (field.Name == "serializeData2" && value is MagicaCloth2.ClothSerializeData2 sdata2) + { + var tdata2 = new MagicaCloth2.ClothSerializeData2(); + // boneAttributeDict 변환 + tdata2.boneAttributeDict = sdata2.boneAttributeDict.ToDictionary( + kvp => FindCorrespondingTransform(kvp.Key, destinationPrefab.transform), + kvp => kvp.Value + ); + // selectionData 등 나머지 ê°’ì€ ê·¸ëŒ€ë¡œ 복사 + tdata2.selectionData = sdata2.selectionData; + tdata2.preBuildData = sdata2.preBuildData; + field.SetValue(tgt, tdata2); + continue; + } + // customSkinningSetting.skinningBones 변환 + if (field.Name == "customSkinningSetting" && value != null) + { + var srcSkin = value; + var skinField = value.GetType().GetField("skinningBones"); + if (skinField != null) + { + var srcList = skinField.GetValue(srcSkin) as List; + if (srcList != null) + { + var tgtList = srcList + .Select(bone => FindCorrespondingTransform(bone, destinationPrefab.transform)) + .Where(t => t != null) + .ToList(); + skinField.SetValue(srcSkin, tgtList); + } + } + field.SetValue(tgt, srcSkin); + continue; + } + // ì´í•˜ 기존 ë¡œì§ + if (typeof(UnityEngine.Object).IsAssignableFrom(field.FieldType)) + { + Object refObj = value as Object; + if (refObj == null) { field.SetValue(tgt, null); continue; } + if (refObj is Transform tr) + { + string refPath = GetTransformPath(tr, sourcePrefab.transform); + var tgtTr = destinationPrefab.transform.Find(refPath); + if (tgtTr != null) + field.SetValue(tgt, tgtTr); + } + else if (refObj is GameObject go) + { + string refPath = GetTransformPath(go.transform, sourcePrefab.transform); + var tgtGo = destinationPrefab.transform.Find(refPath); + if (tgtGo != null) + field.SetValue(tgt, tgtGo.gameObject); + } + else if (refObj is Component comp) + { + string refPath = GetTransformPath(comp.gameObject.transform, sourcePrefab.transform); + var tgtGo = destinationPrefab.transform.Find(refPath); + if (tgtGo != null) + { + var tgtComps = tgtGo.GetComponents(comp.GetType()); + int compIdx = comp.gameObject.GetComponents(comp.GetType()).ToList().IndexOf(comp); + if (compIdx >= 0 && compIdx < tgtComps.Length) + field.SetValue(tgt, tgtComps[compIdx]); + } + } + else + { + // 기타 UnityEngine.Object íƒ€ìž…ì€ ê·¸ëŒ€ë¡œ 복사 + field.SetValue(tgt, refObj); + } + } + else + { + // ê°’ 타입, enum, string ë“±ì€ ê·¸ëŒ€ë¡œ 복사 + field.SetValue(tgt, value); + } + } + } + + void CopyConstraints() + { + var srcTransforms = sourcePrefab.GetComponentsInChildren(true); + foreach (var srcTr in srcTransforms) + { + string path = GetTransformPath(srcTr, sourcePrefab.transform); + var tgtTr = destinationPrefab.transform.Find(path); + if (tgtTr == null) continue; + + // PositionConstraint + var srcPos = srcTr.GetComponent(); + if (srcPos != null) + CopyConstraintComponent(srcPos, tgtTr); + + // RotationConstraint + var srcRot = srcTr.GetComponent(); + if (srcRot != null) + CopyConstraintComponent(srcRot, tgtTr); + + // ParentConstraint + var srcParent = srcTr.GetComponent(); + if (srcParent != null) + CopyConstraintComponent(srcParent, tgtTr); + } + Debug.Log("Constraint ê°’ 복사가 완료ë˜ì—ˆìŠµë‹ˆë‹¤."); + } + + void CopyConstraintComponent(T srcConstraint, Transform tgtTr) where T : Behaviour + { + // ì´ë¯¸ 있으면 ì‚­ì œ 후 새로 추가 + var tgtConstraint = tgtTr.GetComponent(); + if (tgtConstraint != null) + DestroyImmediate(tgtConstraint); + tgtConstraint = tgtTr.gameObject.AddComponent(); + + if (srcConstraint is PositionConstraint srcPos && tgtConstraint is PositionConstraint tgtPos) + { + tgtPos.weight = srcPos.weight; + tgtPos.constraintActive = srcPos.constraintActive; + tgtPos.locked = srcPos.locked; + for (int i = 0; i < srcPos.sourceCount; i++) + { + var src = srcPos.GetSource(i); + var srcTr = src.sourceTransform; + if (srcTr == null) continue; + string srcPath = GetTransformPath(srcTr, sourcePrefab.transform); + var tgtSourceTr = destinationPrefab.transform.Find(srcPath); + if (tgtSourceTr == null) continue; + var newSource = src; + newSource.sourceTransform = tgtSourceTr; + tgtPos.AddSource(newSource); + } + tgtPos.translationAtRest = srcPos.translationAtRest; + tgtPos.translationOffset = srcPos.translationOffset; + tgtPos.translationAxis = srcPos.translationAxis; + } + else if (srcConstraint is RotationConstraint srcRot && tgtConstraint is RotationConstraint tgtRot) + { + tgtRot.weight = srcRot.weight; + tgtRot.constraintActive = srcRot.constraintActive; + tgtRot.locked = srcRot.locked; + for (int i = 0; i < srcRot.sourceCount; i++) + { + var src = srcRot.GetSource(i); + var srcTr = src.sourceTransform; + if (srcTr == null) continue; + string srcPath = GetTransformPath(srcTr, sourcePrefab.transform); + var tgtSourceTr = destinationPrefab.transform.Find(srcPath); + if (tgtSourceTr == null) continue; + var newSource = src; + newSource.sourceTransform = tgtSourceTr; + tgtRot.AddSource(newSource); + } + tgtRot.rotationAtRest = srcRot.rotationAtRest; + tgtRot.rotationOffset = srcRot.rotationOffset; + tgtRot.rotationAxis = srcRot.rotationAxis; + } + else if (srcConstraint is ParentConstraint srcParent && tgtConstraint is ParentConstraint tgtParent) + { + tgtParent.weight = srcParent.weight; + tgtParent.constraintActive = srcParent.constraintActive; + tgtParent.locked = srcParent.locked; + for (int i = 0; i < srcParent.sourceCount; i++) + { + var src = srcParent.GetSource(i); + var srcTr = src.sourceTransform; + if (srcTr == null) continue; + string srcPath = GetTransformPath(srcTr, sourcePrefab.transform); + var tgtSourceTr = destinationPrefab.transform.Find(srcPath); + if (tgtSourceTr == null) continue; + var newSource = src; + newSource.sourceTransform = tgtSourceTr; + tgtParent.AddSource(newSource); + // Offsetë„ ë³µì‚¬ + tgtParent.SetTranslationOffset(i, srcParent.GetTranslationOffset(i)); + tgtParent.SetRotationOffset(i, srcParent.GetRotationOffset(i)); + } + tgtParent.translationAtRest = srcParent.translationAtRest; + tgtParent.rotationAtRest = srcParent.rotationAtRest; + tgtParent.translationAxis = srcParent.translationAxis; + tgtParent.rotationAxis = srcParent.rotationAxis; + } + } + + void CopyBlendShapes() + { + var srcRenderers = sourcePrefab.GetComponentsInChildren(true); + foreach (var srcRenderer in srcRenderers) + { + string path = GetTransformPath(srcRenderer.transform, sourcePrefab.transform); + var tgtTransform = destinationPrefab.transform.Find(path); + if (tgtTransform == null) continue; + var tgtRenderer = tgtTransform.GetComponent(); + if (tgtRenderer == null) continue; + int blendShapeCount = srcRenderer.sharedMesh != null ? srcRenderer.sharedMesh.blendShapeCount : 0; + for (int i = 0; i < blendShapeCount; i++) + { + string shapeName = srcRenderer.sharedMesh.GetBlendShapeName(i); + int tgtIndex = tgtRenderer.sharedMesh != null ? tgtRenderer.sharedMesh.GetBlendShapeIndex(shapeName) : -1; + if (tgtIndex >= 0) + { + float value = srcRenderer.GetBlendShapeWeight(i); + tgtRenderer.SetBlendShapeWeight(tgtIndex, value); + } + } + } + Debug.Log("BlendShape ê°’ 복사가 완료ë˜ì—ˆìŠµë‹ˆë‹¤."); + } + + void CopyActiveStates() + { + var srcTransforms = sourcePrefab.GetComponentsInChildren(true); + foreach (var srcTr in srcTransforms) + { + string path = GetTransformPath(srcTr, sourcePrefab.transform); + var tgtTr = destinationPrefab.transform.Find(path); + if (tgtTr == null) continue; + tgtTr.gameObject.SetActive(srcTr.gameObject.activeSelf); + } + Debug.Log("ActiveState 복사가 완료ë˜ì—ˆìŠµë‹ˆë‹¤."); + } +} \ No newline at end of file diff --git a/Assets/Scripts/AvatarComponetCopier.cs.meta b/Assets/Scripts/AvatarComponetCopier.cs.meta new file mode 100644 index 000000000..e481d389a --- /dev/null +++ b/Assets/Scripts/AvatarComponetCopier.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 39f91032a3569014da62f31d9fe0cb8b \ No newline at end of file diff --git a/Assets/Scripts/Bitd.meta b/Assets/Scripts/Bitd.meta new file mode 100644 index 000000000..588dc11e6 --- /dev/null +++ b/Assets/Scripts/Bitd.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 491d8dbeddc94c343be3c58891497477 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Materials.meta b/Assets/Scripts/Bitd/Materials.meta new file mode 100644 index 000000000..9a4b4f365 --- /dev/null +++ b/Assets/Scripts/Bitd/Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d8229aaef4beaa5459ec9880b2b0ea5d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Materials/FakeShadow.mat b/Assets/Scripts/Bitd/Materials/FakeShadow.mat new file mode 100644 index 000000000..837f5b650 --- /dev/null +++ b/Assets/Scripts/Bitd/Materials/FakeShadow.mat @@ -0,0 +1,768 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: FakeShadow + m_Shader: {fileID: 4800000, guid: 00795bf598b44dc4e9bd363348e77085, type: 3} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 5000 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _AlphaMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _AnisotropyScaleMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _AnisotropyShiftNoiseMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _AnisotropyTangentMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _AudioLinkLocalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _AudioLinkMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BacklightColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseColorMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Bump2ndMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Bump2ndScaleMask: + 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} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DissolveMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DissolveNoiseMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DitherTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Emission2ndBlendMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Emission2ndGradTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Emission2ndMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionBlendMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionGradTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _GlitterColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _GlitterShapeTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main2ndBlendMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main2ndDissolveMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main2ndDissolveNoiseMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main2ndTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main3rdBlendMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main3rdDissolveMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main3rdDissolveNoiseMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main3rdTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainColorAdjustMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainGradationTex: + 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} + m_Offset: {x: 0, y: 0} + - _MatCap2ndBlendMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCap2ndBumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCap2ndTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCapBlendMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCapBumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCapTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + 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} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineVectorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineWidthMask: + 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} + - _ReflectionColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ReflectionCubeTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _RimColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _RimShadeMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Shadow2ndColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Shadow3rdColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ShadowBlurMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ShadowBorderMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ShadowColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ShadowStrengthMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SmoothnessTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AAStrength: 1 + - _AlphaBoostFA: 10 + - _AlphaMaskMode: 0 + - _AlphaMaskScale: 1 + - _AlphaMaskValue: 0 + - _AlphaToMask: 0 + - _Anisotropy2MatCap: 0 + - _Anisotropy2MatCap2nd: 0 + - _Anisotropy2Reflection: 0 + - _Anisotropy2ndBitangentWidth: 1 + - _Anisotropy2ndShift: 0 + - _Anisotropy2ndShiftNoiseScale: 0 + - _Anisotropy2ndSpecularStrength: 0 + - _Anisotropy2ndTangentWidth: 1 + - _AnisotropyBitangentWidth: 1 + - _AnisotropyScale: 1 + - _AnisotropyShift: 0 + - _AnisotropyShiftNoiseScale: 0 + - _AnisotropySpecularStrength: 1 + - _AnisotropyTangentWidth: 1 + - _ApplyReflection: 0 + - _ApplySpecular: 1 + - _ApplySpecularFA: 1 + - _AsOverlay: 0 + - _AsUnlit: 0 + - _AudioLink2Emission: 0 + - _AudioLink2Emission2nd: 0 + - _AudioLink2Emission2ndGrad: 0 + - _AudioLink2EmissionGrad: 0 + - _AudioLink2Main2nd: 0 + - _AudioLink2Main3rd: 0 + - _AudioLink2Vertex: 0 + - _AudioLinkAsLocal: 0 + - _AudioLinkMask_UVMode: 0 + - _AudioLinkUVMode: 1 + - _AudioLinkVertexUVMode: 1 + - _BackfaceForceShadow: 0 + - _BacklightBackfaceMask: 1 + - _BacklightBlur: 0.05 + - _BacklightBorder: 0.35 + - _BacklightDirectivity: 5 + - _BacklightMainStrength: 0 + - _BacklightNormalStrength: 1 + - _BacklightReceiveShadow: 1 + - _BacklightViewStrength: 1 + - _BeforeExposureLimit: 10000 + - _BitKey0: 0 + - _BitKey1: 0 + - _BitKey10: 0 + - _BitKey11: 0 + - _BitKey12: 0 + - _BitKey13: 0 + - _BitKey14: 0 + - _BitKey15: 0 + - _BitKey16: 0 + - _BitKey17: 0 + - _BitKey18: 0 + - _BitKey19: 0 + - _BitKey2: 0 + - _BitKey20: 0 + - _BitKey21: 0 + - _BitKey22: 0 + - _BitKey23: 0 + - _BitKey24: 0 + - _BitKey25: 0 + - _BitKey26: 0 + - _BitKey27: 0 + - _BitKey28: 0 + - _BitKey29: 0 + - _BitKey3: 0 + - _BitKey30: 0 + - _BitKey31: 0 + - _BitKey4: 0 + - _BitKey5: 0 + - _BitKey6: 0 + - _BitKey7: 0 + - _BitKey8: 0 + - _BitKey9: 0 + - _BlendOp: 0 + - _BlendOpAlpha: 0 + - _BlendOpAlphaFA: 4 + - _BlendOpFA: 4 + - _Bump2ndMap_UVMode: 0 + - _Bump2ndScale: 1 + - _BumpScale: 1 + - _ColorMask: 15 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DissolveNoiseStrength: 0.1 + - _DistanceFadeMode: 0 + - _DistanceFadeRimFresnelPower: 5 + - _DitherMaxValue: 255 + - _DstBlend: 3 + - _DstBlendAlpha: 10 + - _DstBlendAlphaFA: 1 + - _DstBlendFA: 1 + - _DummyProperty: 0 + - _Emission2ndBlend: 1 + - _Emission2ndBlendMode: 1 + - _Emission2ndFluorescence: 0 + - _Emission2ndGradSpeed: 1 + - _Emission2ndMainStrength: 0 + - _Emission2ndMap_UVMode: 0 + - _Emission2ndParallaxDepth: 0 + - _Emission2ndUseGrad: 0 + - _EmissionBlend: 1 + - _EmissionBlendMode: 1 + - _EmissionFluorescence: 0 + - _EmissionGradSpeed: 1 + - _EmissionMainStrength: 0 + - _EmissionMap_UVMode: 0 + - _EmissionParallaxDepth: 0 + - _EmissionUseGrad: 0 + - _FlipNormal: 0 + - _GSAAStrength: 0 + - _GlitterAngleRandomize: 0 + - _GlitterApplyShape: 0 + - _GlitterApplyTransparency: 1 + - _GlitterBackfaceMask: 0 + - _GlitterColorTex_UVMode: 0 + - _GlitterEnableLighting: 1 + - _GlitterMainStrength: 0 + - _GlitterNormalStrength: 1 + - _GlitterPostContrast: 1 + - _GlitterScaleRandomize: 0 + - _GlitterSensitivity: 0.25 + - _GlitterShadowMask: 0 + - _GlitterUVMode: 0 + - _GlitterVRParallaxStrength: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _IDMask1: 0 + - _IDMask2: 0 + - _IDMask3: 0 + - _IDMask4: 0 + - _IDMask5: 0 + - _IDMask6: 0 + - _IDMask7: 0 + - _IDMask8: 0 + - _IDMaskCompile: 0 + - _IDMaskControlsDissolve: 0 + - _IDMaskFrom: 8 + - _IDMaskIndex1: 0 + - _IDMaskIndex2: 0 + - _IDMaskIndex3: 0 + - _IDMaskIndex4: 0 + - _IDMaskIndex5: 0 + - _IDMaskIndex6: 0 + - _IDMaskIndex7: 0 + - _IDMaskIndex8: 0 + - _IDMaskIsBitmap: 0 + - _IDMaskPrior1: 0 + - _IDMaskPrior2: 0 + - _IDMaskPrior3: 0 + - _IDMaskPrior4: 0 + - _IDMaskPrior5: 0 + - _IDMaskPrior6: 0 + - _IDMaskPrior7: 0 + - _IDMaskPrior8: 0 + - _IgnoreEncryption: 0 + - _Invisible: 0 + - _LightMaxLimit: 1 + - _LightMinLimit: 0.05 + - _Main2ndDissolveNoiseStrength: 0.1 + - _Main2ndEnableLighting: 1 + - _Main2ndTexAlphaMode: 0 + - _Main2ndTexAngle: 0 + - _Main2ndTexBlendMode: 0 + - _Main2ndTexIsDecal: 0 + - _Main2ndTexIsLeftOnly: 0 + - _Main2ndTexIsMSDF: 0 + - _Main2ndTexIsRightOnly: 0 + - _Main2ndTexShouldCopy: 0 + - _Main2ndTexShouldFlipCopy: 0 + - _Main2ndTexShouldFlipMirror: 0 + - _Main2ndTex_Cull: 0 + - _Main2ndTex_UVMode: 0 + - _Main3rdDissolveNoiseStrength: 0.1 + - _Main3rdEnableLighting: 1 + - _Main3rdTexAlphaMode: 0 + - _Main3rdTexAngle: 0 + - _Main3rdTexBlendMode: 0 + - _Main3rdTexIsDecal: 0 + - _Main3rdTexIsLeftOnly: 0 + - _Main3rdTexIsMSDF: 0 + - _Main3rdTexIsRightOnly: 0 + - _Main3rdTexShouldCopy: 0 + - _Main3rdTexShouldFlipCopy: 0 + - _Main3rdTexShouldFlipMirror: 0 + - _Main3rdTex_Cull: 0 + - _Main3rdTex_UVMode: 0 + - _MainGradationStrength: 0 + - _MatCap2ndApplyTransparency: 1 + - _MatCap2ndBackfaceMask: 0 + - _MatCap2ndBlend: 1 + - _MatCap2ndBlendMode: 1 + - _MatCap2ndBumpScale: 1 + - _MatCap2ndCustomNormal: 0 + - _MatCap2ndEnableLighting: 1 + - _MatCap2ndLod: 0 + - _MatCap2ndMainStrength: 0 + - _MatCap2ndNormalStrength: 1 + - _MatCap2ndPerspective: 1 + - _MatCap2ndShadowMask: 0 + - _MatCap2ndVRParallaxStrength: 1 + - _MatCap2ndZRotCancel: 1 + - _MatCapApplyTransparency: 1 + - _MatCapBackfaceMask: 0 + - _MatCapBlend: 1 + - _MatCapBlendMode: 1 + - _MatCapBumpScale: 1 + - _MatCapCustomNormal: 0 + - _MatCapEnableLighting: 1 + - _MatCapLod: 0 + - _MatCapMainStrength: 0 + - _MatCapNormalStrength: 1 + - _MatCapPerspective: 1 + - _MatCapShadowMask: 0 + - _MatCapVRParallaxStrength: 1 + - _MatCapZRotCancel: 1 + - _Metallic: 0 + - _Mode: 0 + - _MonochromeLighting: 0 + - _OcclusionStrength: 1 + - _OffsetFactor: 0 + - _OffsetUnits: 0 + - _OutlineAlphaToMask: 0 + - _OutlineBlendOp: 0 + - _OutlineBlendOpAlpha: 0 + - _OutlineBlendOpAlphaFA: 4 + - _OutlineBlendOpFA: 4 + - _OutlineColorMask: 15 + - _OutlineCull: 1 + - _OutlineDeleteMesh: 0 + - _OutlineDisableInVR: 0 + - _OutlineDstBlend: 0 + - _OutlineDstBlendAlpha: 10 + - _OutlineDstBlendAlphaFA: 1 + - _OutlineDstBlendFA: 1 + - _OutlineEnableLighting: 1 + - _OutlineFixWidth: 0.5 + - _OutlineLitApplyTex: 0 + - _OutlineLitOffset: -8 + - _OutlineLitScale: 10 + - _OutlineLitShadowReceive: 0 + - _OutlineOffsetFactor: 0 + - _OutlineOffsetUnits: 0 + - _OutlineSrcBlend: 1 + - _OutlineSrcBlendAlpha: 1 + - _OutlineSrcBlendAlphaFA: 0 + - _OutlineSrcBlendFA: 1 + - _OutlineStencilComp: 8 + - _OutlineStencilFail: 0 + - _OutlineStencilPass: 0 + - _OutlineStencilReadMask: 255 + - _OutlineStencilRef: 0 + - _OutlineStencilWriteMask: 255 + - _OutlineStencilZFail: 0 + - _OutlineVectorScale: 1 + - _OutlineVectorUVMode: 0 + - _OutlineVertexR2Width: 0 + - _OutlineWidth: 0.08 + - _OutlineZBias: 0 + - _OutlineZClip: 1 + - _OutlineZTest: 2 + - _OutlineZWrite: 1 + - _Parallax: 0.02 + - _ParallaxOffset: 0.5 + - _Reflectance: 0.04 + - _ReflectionApplyTransparency: 1 + - _ReflectionBlendMode: 1 + - _ReflectionCubeEnableLighting: 1 + - _ReflectionCubeOverride: 0 + - _ReflectionNormalStrength: 1 + - _RimApplyTransparency: 1 + - _RimBackfaceMask: 1 + - _RimBlendMode: 1 + - _RimBlur: 0.65 + - _RimBorder: 0.5 + - _RimDirRange: 0 + - _RimDirStrength: 0 + - _RimEnableLighting: 1 + - _RimFresnelPower: 3.5 + - _RimIndirBlur: 0.1 + - _RimIndirBorder: 0.5 + - _RimIndirRange: 0 + - _RimMainStrength: 0 + - _RimNormalStrength: 1 + - _RimShadeBlur: 1 + - _RimShadeBorder: 0.5 + - _RimShadeFresnelPower: 1 + - _RimShadeNormalStrength: 1 + - _RimShadowMask: 0.5 + - _RimVRParallaxStrength: 1 + - _Shadow2ndBlur: 0.1 + - _Shadow2ndBorder: 0.15 + - _Shadow2ndNormalStrength: 1 + - _Shadow2ndReceive: 0 + - _Shadow3rdBlur: 0.1 + - _Shadow3rdBorder: 0.25 + - _Shadow3rdNormalStrength: 1 + - _Shadow3rdReceive: 0 + - _ShadowBlur: 0.1 + - _ShadowBlurMaskLOD: 0 + - _ShadowBorder: 0.5 + - _ShadowBorderMaskLOD: 0 + - _ShadowBorderRange: 0.08 + - _ShadowColorType: 0 + - _ShadowEnvStrength: 0 + - _ShadowFlatBlur: 1 + - _ShadowFlatBorder: 1 + - _ShadowMainStrength: 0 + - _ShadowMaskType: 0 + - _ShadowNormalStrength: 1 + - _ShadowPostAO: 0 + - _ShadowReceive: 0 + - _ShadowStrength: 1 + - _ShadowStrengthMaskLOD: 0 + - _ShiftBackfaceUV: 0 + - _Smoothness: 1 + - _SmoothnessTextureChannel: 0 + - _SpecularBlur: 0 + - _SpecularBorder: 0.5 + - _SpecularHighlights: 1 + - _SpecularNormalStrength: 1 + - _SpecularToon: 1 + - _SrcBlend: 0 + - _SrcBlendAlpha: 1 + - _SrcBlendAlphaFA: 0 + - _SrcBlendFA: 1 + - _StencilComp: 3 + - _StencilFail: 0 + - _StencilPass: 1 + - _StencilReadMask: 255 + - _StencilRef: 10 + - _StencilWriteMask: 255 + - _StencilZFail: 0 + - _SubpassCutoff: 0.5 + - _TessEdge: 10 + - _TessFactorMax: 3 + - _TessShrink: 0 + - _TessStrength: 0.5 + - _TransparentMode: 0 + - _UDIMDiscardCompile: 0 + - _UDIMDiscardMode: 0 + - _UDIMDiscardRow0_0: 0 + - _UDIMDiscardRow0_1: 0 + - _UDIMDiscardRow0_2: 0 + - _UDIMDiscardRow0_3: 0 + - _UDIMDiscardRow1_0: 0 + - _UDIMDiscardRow1_1: 0 + - _UDIMDiscardRow1_2: 0 + - _UDIMDiscardRow1_3: 0 + - _UDIMDiscardRow2_0: 0 + - _UDIMDiscardRow2_1: 0 + - _UDIMDiscardRow2_2: 0 + - _UDIMDiscardRow2_3: 0 + - _UDIMDiscardRow3_0: 0 + - _UDIMDiscardRow3_1: 0 + - _UDIMDiscardRow3_2: 0 + - _UDIMDiscardRow3_3: 0 + - _UDIMDiscardUV: 0 + - _UVSec: 0 + - _UseAnisotropy: 0 + - _UseAudioLink: 0 + - _UseBacklight: 0 + - _UseBump2ndMap: 0 + - _UseBumpMap: 0 + - _UseClippingCanceller: 0 + - _UseDither: 0 + - _UseEmission: 0 + - _UseEmission2nd: 0 + - _UseGlitter: 0 + - _UseMain2ndTex: 0 + - _UseMain3rdTex: 0 + - _UseMatCap: 0 + - _UseMatCap2nd: 0 + - _UseOutline: 0 + - _UsePOM: 0 + - _UseParallax: 0 + - _UseReflection: 0 + - _UseRim: 0 + - _UseRimShade: 0 + - _UseShadow: 0 + - _VertexLightStrength: 0 + - _ZClip: 1 + - _ZTest: 4 + - _ZWrite: 1 + - _e2gai: 2 + - _e2gci: 2 + - _egai: 2 + - _egci: 2 + - _lilDirectionalLightStrength: 1 + - _lilShadowCasterBias: 0 + - _lilToonVersion: 43 + m_Colors: + - _AudioLinkDefaultValue: {r: 0, g: 0, b: 2, a: 0.75} + - _AudioLinkLocalMapParams: {r: 120, g: 1, b: 0, a: 0} + - _AudioLinkMask_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _AudioLinkStart: {r: 0, g: 0, b: 0, a: 0} + - _AudioLinkUVParams: {r: 0.25, g: 0, b: 0, a: 0.125} + - _AudioLinkVertexStart: {r: 0, g: 0, b: 0, a: 0} + - _AudioLinkVertexStrength: {r: 0, g: 0, b: 0, a: 1} + - _AudioLinkVertexUVParams: {r: 0.25, g: 0, b: 0, a: 0.125} + - _BackfaceColor: {r: 0, g: 0, b: 0, a: 0} + - _BacklightColor: {r: 0.85, g: 0.8, b: 0.7, a: 1} + - _BaseColor: {r: 1, g: 0.8537736, b: 0.8537736, a: 0.3764706} + - _Color: {r: 1, g: 0.8537736, b: 0.8537736, a: 0.3764706} + - _Color2nd: {r: 1, g: 1, b: 1, a: 1} + - _Color3rd: {r: 1, g: 1, b: 1, a: 1} + - _DissolveColor: {r: 1, g: 1, b: 1, a: 1} + - _DissolveNoiseMask_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _DissolveParams: {r: 0, g: 0, b: 0.5, a: 0.1} + - _DissolvePos: {r: 0, g: 0, b: 0, a: 0} + - _DistanceFade: {r: 0.1, g: 0.01, b: 0, a: 0} + - _DistanceFadeColor: {r: 0, g: 0, b: 0, a: 1} + - _DistanceFadeRimColor: {r: 0, g: 0, b: 0, a: 0} + - _Emission2ndBlendMask_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _Emission2ndBlink: {r: 0, g: 0, b: 3.141593, a: 0} + - _Emission2ndColor: {r: 1, g: 1, b: 1, a: 1} + - _Emission2ndMap_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _EmissionBlendMask_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _EmissionBlink: {r: 0, g: 0, b: 3.141593, a: 0} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _EmissionMap_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _FakeShadowVector: {r: 0, g: 0, b: 0.01, a: 0.005} + - _GlitterAtras: {r: 1, g: 1, b: 0, a: 0} + - _GlitterColor: {r: 1, g: 1, b: 1, a: 1} + - _GlitterParams1: {r: 256, g: 256, b: 0.16, a: 50} + - _GlitterParams2: {r: 0.25, g: 0, b: 0, a: 0} + - _Keys: {r: 0, g: 0, b: 0, a: 0} + - _LightDirectionOverride: {r: 0.001, g: 0.002, b: 0.001, a: 0} + - _Main2ndDissolveColor: {r: 1, g: 1, b: 1, a: 1} + - _Main2ndDissolveNoiseMask_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _Main2ndDissolveParams: {r: 0, g: 0, b: 0.5, a: 0.1} + - _Main2ndDissolvePos: {r: 0, g: 0, b: 0, a: 0} + - _Main2ndDistanceFade: {r: 0.1, g: 0.01, b: 0, a: 0} + - _Main2ndTexDecalAnimation: {r: 1, g: 1, b: 1, a: 30} + - _Main2ndTexDecalSubParam: {r: 1, g: 1, b: 0, a: 1} + - _Main2ndTex_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _Main3rdDissolveColor: {r: 1, g: 1, b: 1, a: 1} + - _Main3rdDissolveNoiseMask_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _Main3rdDissolveParams: {r: 0, g: 0, b: 0.5, a: 0.1} + - _Main3rdDissolvePos: {r: 0, g: 0, b: 0, a: 0} + - _Main3rdDistanceFade: {r: 0.1, g: 0.01, b: 0, a: 0} + - _Main3rdTexDecalAnimation: {r: 1, g: 1, b: 1, a: 30} + - _Main3rdTexDecalSubParam: {r: 1, g: 1, b: 0, a: 1} + - _Main3rdTex_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _MainTexHSVG: {r: 0, g: 1, b: 1, a: 1} + - _MainTex_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _MatCap2ndBlendUV1: {r: 0, g: 0, b: 0, a: 0} + - _MatCap2ndColor: {r: 1, g: 1, b: 1, a: 1} + - _MatCapBlendUV1: {r: 0, g: 0, b: 0, a: 0} + - _MatCapColor: {r: 1, g: 1, b: 1, a: 1} + - _OutlineColor: {r: 0.6, g: 0.56, b: 0.73, a: 1} + - _OutlineLitColor: {r: 1, g: 0.19999996, b: 0, a: 0} + - _OutlineTexHSVG: {r: 0, g: 1, b: 1, a: 1} + - _OutlineTex_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _ReflectionColor: {r: 1, g: 1, b: 1, a: 1} + - _ReflectionCubeColor: {r: 0, g: 0, b: 0, a: 1} + - _RimColor: {r: 0.65999997, g: 0.5, b: 0.47999996, a: 1} + - _RimIndirColor: {r: 1, g: 1, b: 1, a: 1} + - _RimShadeColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + - _Shadow2ndColor: {r: 0.68, g: 0.65999997, b: 0.78999996, a: 1} + - _Shadow3rdColor: {r: 0, g: 0, b: 0, a: 0} + - _ShadowAOShift: {r: 1, g: 0, b: 1, a: 0} + - _ShadowAOShift2: {r: 1, g: 0, b: 1, a: 0} + - _ShadowBorderColor: {r: 1, g: 0.09999997, b: 0, a: 1} + - _ShadowColor: {r: 0.82, g: 0.76, b: 0.85, a: 1} + - _e2ga0: {r: 1, g: 0, b: 0, a: 0} + - _e2ga1: {r: 1, g: 0, b: 0, a: 1} + - _e2ga2: {r: 1, g: 0, b: 0, a: 0} + - _e2ga3: {r: 1, g: 0, b: 0, a: 0} + - _e2ga4: {r: 1, g: 0, b: 0, a: 0} + - _e2ga5: {r: 1, g: 0, b: 0, a: 0} + - _e2ga6: {r: 1, g: 0, b: 0, a: 0} + - _e2ga7: {r: 1, g: 0, b: 0, a: 0} + - _e2gc0: {r: 1, g: 1, b: 1, a: 0} + - _e2gc1: {r: 1, g: 1, b: 1, a: 1} + - _e2gc2: {r: 1, g: 1, b: 1, a: 0} + - _e2gc3: {r: 1, g: 1, b: 1, a: 0} + - _e2gc4: {r: 1, g: 1, b: 1, a: 0} + - _e2gc5: {r: 1, g: 1, b: 1, a: 0} + - _e2gc6: {r: 1, g: 1, b: 1, a: 0} + - _e2gc7: {r: 1, g: 1, b: 1, a: 0} + - _ega0: {r: 1, g: 0, b: 0, a: 0} + - _ega1: {r: 1, g: 0, b: 0, a: 1} + - _ega2: {r: 1, g: 0, b: 0, a: 0} + - _ega3: {r: 1, g: 0, b: 0, a: 0} + - _ega4: {r: 1, g: 0, b: 0, a: 0} + - _ega5: {r: 1, g: 0, b: 0, a: 0} + - _ega6: {r: 1, g: 0, b: 0, a: 0} + - _ega7: {r: 1, g: 0, b: 0, a: 0} + - _egc0: {r: 1, g: 1, b: 1, a: 0} + - _egc1: {r: 1, g: 1, b: 1, a: 1} + - _egc2: {r: 1, g: 1, b: 1, a: 0} + - _egc3: {r: 1, g: 1, b: 1, a: 0} + - _egc4: {r: 1, g: 1, b: 1, a: 0} + - _egc5: {r: 1, g: 1, b: 1, a: 0} + - _egc6: {r: 1, g: 1, b: 1, a: 0} + - _egc7: {r: 1, g: 1, b: 1, a: 0} + m_BuildTextureStacks: [] diff --git a/Assets/Scripts/Bitd/Materials/FakeShadow.mat.meta b/Assets/Scripts/Bitd/Materials/FakeShadow.mat.meta new file mode 100644 index 000000000..6bf46d211 --- /dev/null +++ b/Assets/Scripts/Bitd/Materials/FakeShadow.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dfee5f2c7477b594799da7414ddfec5b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Materials/FakeShadow_Body.mat b/Assets/Scripts/Bitd/Materials/FakeShadow_Body.mat new file mode 100644 index 000000000..70441f64c --- /dev/null +++ b/Assets/Scripts/Bitd/Materials/FakeShadow_Body.mat @@ -0,0 +1,768 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: FakeShadow_Body + m_Shader: {fileID: 4800000, guid: 00795bf598b44dc4e9bd363348e77085, type: 3} + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 5000 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _AlphaMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _AnisotropyScaleMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _AnisotropyShiftNoiseMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _AnisotropyTangentMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _AudioLinkLocalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _AudioLinkMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BacklightColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseColorMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Bump2ndMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Bump2ndScaleMask: + 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} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DissolveMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DissolveNoiseMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DitherTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Emission2ndBlendMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Emission2ndGradTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Emission2ndMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionBlendMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionGradTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _GlitterColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _GlitterShapeTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main2ndBlendMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main2ndDissolveMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main2ndDissolveNoiseMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main2ndTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main3rdBlendMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main3rdDissolveMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main3rdDissolveNoiseMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Main3rdTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainColorAdjustMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainGradationTex: + 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} + m_Offset: {x: 0, y: 0} + - _MatCap2ndBlendMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCap2ndBumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCap2ndTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCapBlendMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCapBumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MatCapTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + 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} + - _OutlineTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineVectorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OutlineWidthMask: + 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} + - _ReflectionColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ReflectionCubeTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _RimColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _RimShadeMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Shadow2ndColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _Shadow3rdColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ShadowBlurMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ShadowBorderMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ShadowColorTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ShadowStrengthMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SmoothnessTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AAStrength: 1 + - _AlphaBoostFA: 10 + - _AlphaMaskMode: 0 + - _AlphaMaskScale: 1 + - _AlphaMaskValue: 0 + - _AlphaToMask: 0 + - _Anisotropy2MatCap: 0 + - _Anisotropy2MatCap2nd: 0 + - _Anisotropy2Reflection: 0 + - _Anisotropy2ndBitangentWidth: 1 + - _Anisotropy2ndShift: 0 + - _Anisotropy2ndShiftNoiseScale: 0 + - _Anisotropy2ndSpecularStrength: 0 + - _Anisotropy2ndTangentWidth: 1 + - _AnisotropyBitangentWidth: 1 + - _AnisotropyScale: 1 + - _AnisotropyShift: 0 + - _AnisotropyShiftNoiseScale: 0 + - _AnisotropySpecularStrength: 1 + - _AnisotropyTangentWidth: 1 + - _ApplyReflection: 0 + - _ApplySpecular: 1 + - _ApplySpecularFA: 1 + - _AsOverlay: 0 + - _AsUnlit: 0 + - _AudioLink2Emission: 0 + - _AudioLink2Emission2nd: 0 + - _AudioLink2Emission2ndGrad: 0 + - _AudioLink2EmissionGrad: 0 + - _AudioLink2Main2nd: 0 + - _AudioLink2Main3rd: 0 + - _AudioLink2Vertex: 0 + - _AudioLinkAsLocal: 0 + - _AudioLinkMask_UVMode: 0 + - _AudioLinkUVMode: 1 + - _AudioLinkVertexUVMode: 1 + - _BackfaceForceShadow: 0 + - _BacklightBackfaceMask: 1 + - _BacklightBlur: 0.05 + - _BacklightBorder: 0.35 + - _BacklightDirectivity: 5 + - _BacklightMainStrength: 0 + - _BacklightNormalStrength: 1 + - _BacklightReceiveShadow: 1 + - _BacklightViewStrength: 1 + - _BeforeExposureLimit: 10000 + - _BitKey0: 0 + - _BitKey1: 0 + - _BitKey10: 0 + - _BitKey11: 0 + - _BitKey12: 0 + - _BitKey13: 0 + - _BitKey14: 0 + - _BitKey15: 0 + - _BitKey16: 0 + - _BitKey17: 0 + - _BitKey18: 0 + - _BitKey19: 0 + - _BitKey2: 0 + - _BitKey20: 0 + - _BitKey21: 0 + - _BitKey22: 0 + - _BitKey23: 0 + - _BitKey24: 0 + - _BitKey25: 0 + - _BitKey26: 0 + - _BitKey27: 0 + - _BitKey28: 0 + - _BitKey29: 0 + - _BitKey3: 0 + - _BitKey30: 0 + - _BitKey31: 0 + - _BitKey4: 0 + - _BitKey5: 0 + - _BitKey6: 0 + - _BitKey7: 0 + - _BitKey8: 0 + - _BitKey9: 0 + - _BlendOp: 0 + - _BlendOpAlpha: 0 + - _BlendOpAlphaFA: 4 + - _BlendOpFA: 4 + - _Bump2ndMap_UVMode: 0 + - _Bump2ndScale: 1 + - _BumpScale: 1 + - _ColorMask: 15 + - _Cull: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DissolveNoiseStrength: 0.1 + - _DistanceFadeMode: 0 + - _DistanceFadeRimFresnelPower: 5 + - _DitherMaxValue: 255 + - _DstBlend: 3 + - _DstBlendAlpha: 10 + - _DstBlendAlphaFA: 1 + - _DstBlendFA: 1 + - _DummyProperty: 0 + - _Emission2ndBlend: 1 + - _Emission2ndBlendMode: 1 + - _Emission2ndFluorescence: 0 + - _Emission2ndGradSpeed: 1 + - _Emission2ndMainStrength: 0 + - _Emission2ndMap_UVMode: 0 + - _Emission2ndParallaxDepth: 0 + - _Emission2ndUseGrad: 0 + - _EmissionBlend: 1 + - _EmissionBlendMode: 1 + - _EmissionFluorescence: 0 + - _EmissionGradSpeed: 1 + - _EmissionMainStrength: 0 + - _EmissionMap_UVMode: 0 + - _EmissionParallaxDepth: 0 + - _EmissionUseGrad: 0 + - _FlipNormal: 0 + - _GSAAStrength: 0 + - _GlitterAngleRandomize: 0 + - _GlitterApplyShape: 0 + - _GlitterApplyTransparency: 1 + - _GlitterBackfaceMask: 0 + - _GlitterColorTex_UVMode: 0 + - _GlitterEnableLighting: 1 + - _GlitterMainStrength: 0 + - _GlitterNormalStrength: 1 + - _GlitterPostContrast: 1 + - _GlitterScaleRandomize: 0 + - _GlitterSensitivity: 0.25 + - _GlitterShadowMask: 0 + - _GlitterUVMode: 0 + - _GlitterVRParallaxStrength: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _IDMask1: 0 + - _IDMask2: 0 + - _IDMask3: 0 + - _IDMask4: 0 + - _IDMask5: 0 + - _IDMask6: 0 + - _IDMask7: 0 + - _IDMask8: 0 + - _IDMaskCompile: 0 + - _IDMaskControlsDissolve: 0 + - _IDMaskFrom: 8 + - _IDMaskIndex1: 0 + - _IDMaskIndex2: 0 + - _IDMaskIndex3: 0 + - _IDMaskIndex4: 0 + - _IDMaskIndex5: 0 + - _IDMaskIndex6: 0 + - _IDMaskIndex7: 0 + - _IDMaskIndex8: 0 + - _IDMaskIsBitmap: 0 + - _IDMaskPrior1: 0 + - _IDMaskPrior2: 0 + - _IDMaskPrior3: 0 + - _IDMaskPrior4: 0 + - _IDMaskPrior5: 0 + - _IDMaskPrior6: 0 + - _IDMaskPrior7: 0 + - _IDMaskPrior8: 0 + - _IgnoreEncryption: 0 + - _Invisible: 0 + - _LightMaxLimit: 1 + - _LightMinLimit: 0.05 + - _Main2ndDissolveNoiseStrength: 0.1 + - _Main2ndEnableLighting: 1 + - _Main2ndTexAlphaMode: 0 + - _Main2ndTexAngle: 0 + - _Main2ndTexBlendMode: 0 + - _Main2ndTexIsDecal: 0 + - _Main2ndTexIsLeftOnly: 0 + - _Main2ndTexIsMSDF: 0 + - _Main2ndTexIsRightOnly: 0 + - _Main2ndTexShouldCopy: 0 + - _Main2ndTexShouldFlipCopy: 0 + - _Main2ndTexShouldFlipMirror: 0 + - _Main2ndTex_Cull: 0 + - _Main2ndTex_UVMode: 0 + - _Main3rdDissolveNoiseStrength: 0.1 + - _Main3rdEnableLighting: 1 + - _Main3rdTexAlphaMode: 0 + - _Main3rdTexAngle: 0 + - _Main3rdTexBlendMode: 0 + - _Main3rdTexIsDecal: 0 + - _Main3rdTexIsLeftOnly: 0 + - _Main3rdTexIsMSDF: 0 + - _Main3rdTexIsRightOnly: 0 + - _Main3rdTexShouldCopy: 0 + - _Main3rdTexShouldFlipCopy: 0 + - _Main3rdTexShouldFlipMirror: 0 + - _Main3rdTex_Cull: 0 + - _Main3rdTex_UVMode: 0 + - _MainGradationStrength: 0 + - _MatCap2ndApplyTransparency: 1 + - _MatCap2ndBackfaceMask: 0 + - _MatCap2ndBlend: 1 + - _MatCap2ndBlendMode: 1 + - _MatCap2ndBumpScale: 1 + - _MatCap2ndCustomNormal: 0 + - _MatCap2ndEnableLighting: 1 + - _MatCap2ndLod: 0 + - _MatCap2ndMainStrength: 0 + - _MatCap2ndNormalStrength: 1 + - _MatCap2ndPerspective: 1 + - _MatCap2ndShadowMask: 0 + - _MatCap2ndVRParallaxStrength: 1 + - _MatCap2ndZRotCancel: 1 + - _MatCapApplyTransparency: 1 + - _MatCapBackfaceMask: 0 + - _MatCapBlend: 1 + - _MatCapBlendMode: 1 + - _MatCapBumpScale: 1 + - _MatCapCustomNormal: 0 + - _MatCapEnableLighting: 1 + - _MatCapLod: 0 + - _MatCapMainStrength: 0 + - _MatCapNormalStrength: 1 + - _MatCapPerspective: 1 + - _MatCapShadowMask: 0 + - _MatCapVRParallaxStrength: 1 + - _MatCapZRotCancel: 1 + - _Metallic: 0 + - _Mode: 0 + - _MonochromeLighting: 0 + - _OcclusionStrength: 1 + - _OffsetFactor: 0 + - _OffsetUnits: 0 + - _OutlineAlphaToMask: 0 + - _OutlineBlendOp: 0 + - _OutlineBlendOpAlpha: 0 + - _OutlineBlendOpAlphaFA: 4 + - _OutlineBlendOpFA: 4 + - _OutlineColorMask: 15 + - _OutlineCull: 1 + - _OutlineDeleteMesh: 0 + - _OutlineDisableInVR: 0 + - _OutlineDstBlend: 0 + - _OutlineDstBlendAlpha: 10 + - _OutlineDstBlendAlphaFA: 1 + - _OutlineDstBlendFA: 1 + - _OutlineEnableLighting: 1 + - _OutlineFixWidth: 0.5 + - _OutlineLitApplyTex: 0 + - _OutlineLitOffset: -8 + - _OutlineLitScale: 10 + - _OutlineLitShadowReceive: 0 + - _OutlineOffsetFactor: 0 + - _OutlineOffsetUnits: 0 + - _OutlineSrcBlend: 1 + - _OutlineSrcBlendAlpha: 1 + - _OutlineSrcBlendAlphaFA: 0 + - _OutlineSrcBlendFA: 1 + - _OutlineStencilComp: 8 + - _OutlineStencilFail: 0 + - _OutlineStencilPass: 0 + - _OutlineStencilReadMask: 255 + - _OutlineStencilRef: 0 + - _OutlineStencilWriteMask: 255 + - _OutlineStencilZFail: 0 + - _OutlineVectorScale: 1 + - _OutlineVectorUVMode: 0 + - _OutlineVertexR2Width: 0 + - _OutlineWidth: 0.08 + - _OutlineZBias: 0 + - _OutlineZClip: 1 + - _OutlineZTest: 2 + - _OutlineZWrite: 1 + - _Parallax: 0.02 + - _ParallaxOffset: 0.5 + - _Reflectance: 0.04 + - _ReflectionApplyTransparency: 1 + - _ReflectionBlendMode: 1 + - _ReflectionCubeEnableLighting: 1 + - _ReflectionCubeOverride: 0 + - _ReflectionNormalStrength: 1 + - _RimApplyTransparency: 1 + - _RimBackfaceMask: 1 + - _RimBlendMode: 1 + - _RimBlur: 0.65 + - _RimBorder: 0.5 + - _RimDirRange: 0 + - _RimDirStrength: 0 + - _RimEnableLighting: 1 + - _RimFresnelPower: 3.5 + - _RimIndirBlur: 0.1 + - _RimIndirBorder: 0.5 + - _RimIndirRange: 0 + - _RimMainStrength: 0 + - _RimNormalStrength: 1 + - _RimShadeBlur: 1 + - _RimShadeBorder: 0.5 + - _RimShadeFresnelPower: 1 + - _RimShadeNormalStrength: 1 + - _RimShadowMask: 0.5 + - _RimVRParallaxStrength: 1 + - _Shadow2ndBlur: 0.1 + - _Shadow2ndBorder: 0.15 + - _Shadow2ndNormalStrength: 1 + - _Shadow2ndReceive: 0 + - _Shadow3rdBlur: 0.1 + - _Shadow3rdBorder: 0.25 + - _Shadow3rdNormalStrength: 1 + - _Shadow3rdReceive: 0 + - _ShadowBlur: 0.1 + - _ShadowBlurMaskLOD: 0 + - _ShadowBorder: 0.5 + - _ShadowBorderMaskLOD: 0 + - _ShadowBorderRange: 0.08 + - _ShadowColorType: 0 + - _ShadowEnvStrength: 0 + - _ShadowFlatBlur: 1 + - _ShadowFlatBorder: 1 + - _ShadowMainStrength: 0 + - _ShadowMaskType: 0 + - _ShadowNormalStrength: 1 + - _ShadowPostAO: 0 + - _ShadowReceive: 0 + - _ShadowStrength: 1 + - _ShadowStrengthMaskLOD: 0 + - _ShiftBackfaceUV: 0 + - _Smoothness: 1 + - _SmoothnessTextureChannel: 0 + - _SpecularBlur: 0 + - _SpecularBorder: 0.5 + - _SpecularHighlights: 1 + - _SpecularNormalStrength: 1 + - _SpecularToon: 1 + - _SrcBlend: 0 + - _SrcBlendAlpha: 1 + - _SrcBlendAlphaFA: 0 + - _SrcBlendFA: 1 + - _StencilComp: 3 + - _StencilFail: 0 + - _StencilPass: 1 + - _StencilReadMask: 255 + - _StencilRef: 10 + - _StencilWriteMask: 255 + - _StencilZFail: 0 + - _SubpassCutoff: 0.5 + - _TessEdge: 10 + - _TessFactorMax: 3 + - _TessShrink: 0 + - _TessStrength: 0.5 + - _TransparentMode: 0 + - _UDIMDiscardCompile: 0 + - _UDIMDiscardMode: 0 + - _UDIMDiscardRow0_0: 0 + - _UDIMDiscardRow0_1: 0 + - _UDIMDiscardRow0_2: 0 + - _UDIMDiscardRow0_3: 0 + - _UDIMDiscardRow1_0: 0 + - _UDIMDiscardRow1_1: 0 + - _UDIMDiscardRow1_2: 0 + - _UDIMDiscardRow1_3: 0 + - _UDIMDiscardRow2_0: 0 + - _UDIMDiscardRow2_1: 0 + - _UDIMDiscardRow2_2: 0 + - _UDIMDiscardRow2_3: 0 + - _UDIMDiscardRow3_0: 0 + - _UDIMDiscardRow3_1: 0 + - _UDIMDiscardRow3_2: 0 + - _UDIMDiscardRow3_3: 0 + - _UDIMDiscardUV: 0 + - _UVSec: 0 + - _UseAnisotropy: 0 + - _UseAudioLink: 0 + - _UseBacklight: 0 + - _UseBump2ndMap: 0 + - _UseBumpMap: 0 + - _UseClippingCanceller: 0 + - _UseDither: 0 + - _UseEmission: 0 + - _UseEmission2nd: 0 + - _UseGlitter: 0 + - _UseMain2ndTex: 0 + - _UseMain3rdTex: 0 + - _UseMatCap: 0 + - _UseMatCap2nd: 0 + - _UseOutline: 0 + - _UsePOM: 0 + - _UseParallax: 0 + - _UseReflection: 0 + - _UseRim: 0 + - _UseRimShade: 0 + - _UseShadow: 0 + - _VertexLightStrength: 0 + - _ZClip: 1 + - _ZTest: 4 + - _ZWrite: 1 + - _e2gai: 2 + - _e2gci: 2 + - _egai: 2 + - _egci: 2 + - _lilDirectionalLightStrength: 1 + - _lilShadowCasterBias: 0 + - _lilToonVersion: 43 + m_Colors: + - _AudioLinkDefaultValue: {r: 0, g: 0, b: 2, a: 0.75} + - _AudioLinkLocalMapParams: {r: 120, g: 1, b: 0, a: 0} + - _AudioLinkMask_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _AudioLinkStart: {r: 0, g: 0, b: 0, a: 0} + - _AudioLinkUVParams: {r: 0.25, g: 0, b: 0, a: 0.125} + - _AudioLinkVertexStart: {r: 0, g: 0, b: 0, a: 0} + - _AudioLinkVertexStrength: {r: 0, g: 0, b: 0, a: 1} + - _AudioLinkVertexUVParams: {r: 0.25, g: 0, b: 0, a: 0.125} + - _BackfaceColor: {r: 0, g: 0, b: 0, a: 0} + - _BacklightColor: {r: 0.85, g: 0.8, b: 0.7, a: 1} + - _BaseColor: {r: 1, g: 0.8915094, b: 0.8915094, a: 1} + - _Color: {r: 1, g: 0.8915094, b: 0.8915094, a: 1} + - _Color2nd: {r: 1, g: 1, b: 1, a: 1} + - _Color3rd: {r: 1, g: 1, b: 1, a: 1} + - _DissolveColor: {r: 1, g: 1, b: 1, a: 1} + - _DissolveNoiseMask_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _DissolveParams: {r: 0, g: 0, b: 0.5, a: 0.1} + - _DissolvePos: {r: 0, g: 0, b: 0, a: 0} + - _DistanceFade: {r: 0.1, g: 0.01, b: 0, a: 0} + - _DistanceFadeColor: {r: 0, g: 0, b: 0, a: 1} + - _DistanceFadeRimColor: {r: 0, g: 0, b: 0, a: 0} + - _Emission2ndBlendMask_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _Emission2ndBlink: {r: 0, g: 0, b: 3.141593, a: 0} + - _Emission2ndColor: {r: 1, g: 1, b: 1, a: 1} + - _Emission2ndMap_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _EmissionBlendMask_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _EmissionBlink: {r: 0, g: 0, b: 3.141593, a: 0} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _EmissionMap_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _FakeShadowVector: {r: 0, g: 0, b: 0.05, a: 0.03} + - _GlitterAtras: {r: 1, g: 1, b: 0, a: 0} + - _GlitterColor: {r: 1, g: 1, b: 1, a: 1} + - _GlitterParams1: {r: 256, g: 256, b: 0.16, a: 50} + - _GlitterParams2: {r: 0.25, g: 0, b: 0, a: 0} + - _Keys: {r: 0, g: 0, b: 0, a: 0} + - _LightDirectionOverride: {r: 0.001, g: 0.002, b: 0.001, a: 0} + - _Main2ndDissolveColor: {r: 1, g: 1, b: 1, a: 1} + - _Main2ndDissolveNoiseMask_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _Main2ndDissolveParams: {r: 0, g: 0, b: 0.5, a: 0.1} + - _Main2ndDissolvePos: {r: 0, g: 0, b: 0, a: 0} + - _Main2ndDistanceFade: {r: 0.1, g: 0.01, b: 0, a: 0} + - _Main2ndTexDecalAnimation: {r: 1, g: 1, b: 1, a: 30} + - _Main2ndTexDecalSubParam: {r: 1, g: 1, b: 0, a: 1} + - _Main2ndTex_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _Main3rdDissolveColor: {r: 1, g: 1, b: 1, a: 1} + - _Main3rdDissolveNoiseMask_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _Main3rdDissolveParams: {r: 0, g: 0, b: 0.5, a: 0.1} + - _Main3rdDissolvePos: {r: 0, g: 0, b: 0, a: 0} + - _Main3rdDistanceFade: {r: 0.1, g: 0.01, b: 0, a: 0} + - _Main3rdTexDecalAnimation: {r: 1, g: 1, b: 1, a: 30} + - _Main3rdTexDecalSubParam: {r: 1, g: 1, b: 0, a: 1} + - _Main3rdTex_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _MainTexHSVG: {r: 0, g: 1, b: 1, a: 1} + - _MainTex_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _MatCap2ndBlendUV1: {r: 0, g: 0, b: 0, a: 0} + - _MatCap2ndColor: {r: 1, g: 1, b: 1, a: 1} + - _MatCapBlendUV1: {r: 0, g: 0, b: 0, a: 0} + - _MatCapColor: {r: 1, g: 1, b: 1, a: 1} + - _OutlineColor: {r: 0.6, g: 0.56, b: 0.73, a: 1} + - _OutlineLitColor: {r: 1, g: 0.19999996, b: 0, a: 0} + - _OutlineTexHSVG: {r: 0, g: 1, b: 1, a: 1} + - _OutlineTex_ScrollRotate: {r: 0, g: 0, b: 0, a: 0} + - _ReflectionColor: {r: 1, g: 1, b: 1, a: 1} + - _ReflectionCubeColor: {r: 0, g: 0, b: 0, a: 1} + - _RimColor: {r: 0.65999997, g: 0.5, b: 0.47999996, a: 1} + - _RimIndirColor: {r: 1, g: 1, b: 1, a: 1} + - _RimShadeColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + - _Shadow2ndColor: {r: 0.68, g: 0.65999997, b: 0.78999996, a: 1} + - _Shadow3rdColor: {r: 0, g: 0, b: 0, a: 0} + - _ShadowAOShift: {r: 1, g: 0, b: 1, a: 0} + - _ShadowAOShift2: {r: 1, g: 0, b: 1, a: 0} + - _ShadowBorderColor: {r: 1, g: 0.09999997, b: 0, a: 1} + - _ShadowColor: {r: 0.82, g: 0.76, b: 0.85, a: 1} + - _e2ga0: {r: 1, g: 0, b: 0, a: 0} + - _e2ga1: {r: 1, g: 0, b: 0, a: 1} + - _e2ga2: {r: 1, g: 0, b: 0, a: 0} + - _e2ga3: {r: 1, g: 0, b: 0, a: 0} + - _e2ga4: {r: 1, g: 0, b: 0, a: 0} + - _e2ga5: {r: 1, g: 0, b: 0, a: 0} + - _e2ga6: {r: 1, g: 0, b: 0, a: 0} + - _e2ga7: {r: 1, g: 0, b: 0, a: 0} + - _e2gc0: {r: 1, g: 1, b: 1, a: 0} + - _e2gc1: {r: 1, g: 1, b: 1, a: 1} + - _e2gc2: {r: 1, g: 1, b: 1, a: 0} + - _e2gc3: {r: 1, g: 1, b: 1, a: 0} + - _e2gc4: {r: 1, g: 1, b: 1, a: 0} + - _e2gc5: {r: 1, g: 1, b: 1, a: 0} + - _e2gc6: {r: 1, g: 1, b: 1, a: 0} + - _e2gc7: {r: 1, g: 1, b: 1, a: 0} + - _ega0: {r: 1, g: 0, b: 0, a: 0} + - _ega1: {r: 1, g: 0, b: 0, a: 1} + - _ega2: {r: 1, g: 0, b: 0, a: 0} + - _ega3: {r: 1, g: 0, b: 0, a: 0} + - _ega4: {r: 1, g: 0, b: 0, a: 0} + - _ega5: {r: 1, g: 0, b: 0, a: 0} + - _ega6: {r: 1, g: 0, b: 0, a: 0} + - _ega7: {r: 1, g: 0, b: 0, a: 0} + - _egc0: {r: 1, g: 1, b: 1, a: 0} + - _egc1: {r: 1, g: 1, b: 1, a: 1} + - _egc2: {r: 1, g: 1, b: 1, a: 0} + - _egc3: {r: 1, g: 1, b: 1, a: 0} + - _egc4: {r: 1, g: 1, b: 1, a: 0} + - _egc5: {r: 1, g: 1, b: 1, a: 0} + - _egc6: {r: 1, g: 1, b: 1, a: 0} + - _egc7: {r: 1, g: 1, b: 1, a: 0} + m_BuildTextureStacks: [] diff --git a/Assets/Scripts/Bitd/Materials/FakeShadow_Body.mat.meta b/Assets/Scripts/Bitd/Materials/FakeShadow_Body.mat.meta new file mode 100644 index 000000000..b53d4e9f3 --- /dev/null +++ b/Assets/Scripts/Bitd/Materials/FakeShadow_Body.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fe8d1d57ad311304dbed908185159d8a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts.meta b/Assets/Scripts/Bitd/Scripts.meta new file mode 100644 index 000000000..c23fb8612 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7aea0b22f8a2d7f4292c8e42a1b8a95c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/ARKitAdder.cs b/Assets/Scripts/Bitd/Scripts/ARKitAdder.cs new file mode 100644 index 000000000..08d7c881d --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/ARKitAdder.cs @@ -0,0 +1,297 @@ +#if UNITY_EDITOR + +using UnityEngine; +using UnityEditor; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using VRM; +using UniGLTF; + +namespace Bitd +{ + public class ARKitAdder : EditorWindow + { + string[] blendShapeNames = new string[] + { + "eyeBlinkLeft", "eyeBlinkRight","eyeLookDownLeft", "eyeLookDownRight", + "eyeLookInLeft", "eyeLookInRight", "eyeLookOutLeft", "eyeLookOutRight", + "eyeLookUpLeft", "eyeLookUpRight", "eyeSquintLeft", "eyeSquintRight", "eyeWideLeft", "eyeWideRight", + "browDownLeft", "browDownRight", "browInnerUp", "browOuterUpLeft", "browOuterUpRight", + "mouthClose", "mouthFunnel", "mouthPucker", "mouthLeft", "mouthRight", "mouthSmileLeft", "mouthSmileRight", "mouthFrownLeft", "mouthFrownRight", + "mouthDimpleLeft", "mouthDimpleRight", "mouthStretchLeft", "mouthStretchRight", "mouthRollLower", "mouthRollUpper", + "mouthShrugLower", "mouthShrugUpper", "mouthPressLeft", "mouthPressRight", "mouthLowerDownLeft", "mouthLowerDownRight", + "mouthUpperUpLeft", "mouthUpperUpRight", "cheekPuff", "cheekSquintLeft", "cheekSquintRight", "noseSneerLeft", "noseSneerRight", + "jawOpen", "jawForward", "jawLeft", "jawRight", "tongueOut" + }; + + VRMBlendShapeProxy proxy; + + [MenuItem("Bitd/ARKit ìƒì„±ê¸°", false, 301)] + public static void ShowWindow() + { + var window = GetWindow("ARKit ìƒì„±ê¸°"); + } + + void OnGUI() + { + GUILayout.Label("íŒŒì¼ ìƒì„±ê¸°", EditorStyles.boldLabel); + + // ì„ íƒëœ 오브ì íЏ 표시 + proxy = (VRMBlendShapeProxy)EditorGUILayout.ObjectField("타겟 아바타", proxy, typeof(VRMBlendShapeProxy), true); + + if (proxy == null) + { + EditorGUILayout.HelpBox("아바타를 넣어주세요.", MessageType.Warning); + } + else + { + // 버튼: íŒŒì¼ ìƒì„± 시작 + if (GUILayout.Button("ARKit ìƒì„±")) + { + GenerateFiles(); + } + } + } + + private void GenerateFiles() + { + // íŒŒì¼ ê²½ë¡œ ì„ íƒ + string path = EditorUtility.SaveFolderPanel("íŒŒì¼ ì €ìž¥ 경로 ì„ íƒ", Application.dataPath, ""); + + if (string.IsNullOrEmpty(path)) + { + Debug.LogWarning("경로 ì„ íƒì´ 취소ë˜ì—ˆìŠµë‹ˆë‹¤."); + return; + } + + // Unity 경로로 변환 + if (path.StartsWith(Application.dataPath)) + { + path = "Assets" + path.Substring(Application.dataPath.Length); + } + else + { + Debug.LogError("경로는 반드시 Unity 프로ì íЏ 내부여야 합니다."); + return; + } + + Debug.Log($"íŒŒì¼ ìƒì„± 경로: {path}"); + + // íŒŒì¼ ìƒì„± 함수 호출 + CreateFilesAtPath(path); + + // ì—디터 윈ë„ìš° 닫기 + this.Close(); + + // ì—디터 ë¦¬ì»´íŒŒì¼ ê°•ì œ + AssetDatabase.Refresh(); + } + + private void CreateFilesAtPath(string path) + { + // íŒŒì¼ ìƒì„± 로ì§ì„ ì—¬ê¸°ì— êµ¬í˜„ + Debug.Log($"'{proxy.name}'ì— ìžˆëŠ” 블렌드ì‰ì´í”„ ê°’ì„ ì°¾ì•„ì„œ '{path}'ì— í´ë¦½ë“¤ì„ ìƒì„±í•©ë‹ˆë‹¤!"); + + SkinnedMeshRenderer[] targetObjs = proxy.GetComponentsInChildren(); + + for (int i = 0; i < targetObjs.Length; i++) + { + for (int j = 0; j < blendShapeNames.Length; j++) + { + CreateClipByName(path, blendShapeNames[j], targetObjs[i]); + //CreateClipByName(path, CapitalizeFirstLetter(blendShapeNames[j]), targetObjs[i]); + } + } + } + + private void CreateClipByName(string path, string clipName, SkinnedMeshRenderer body) + { + BlendShapeClip bsClip; + bool alreadyIn = false; + int targetIndex = -1; + string lowerFirstName = LowercaseFirstLetter(clipName); // ì•žê¸€ìž ì†Œë¬¸ìž ë“¤ì–´ì˜´ + string upperFirstName = CapitalizeFirstLetter(clipName); // ì•žê¸€ìž ëŒ€ë¬¸ìž ë“¤ì–´ì˜´ + + // 블쉪í´ë¦½ì„ 찾기 시작함 + + // 앞글ìžê°€ 소문ìžì¸ 경우 ì²´í¬ + for (int i = 0; i < proxy.BlendShapeAvatar.Clips.Count; i++) + { + if (proxy.BlendShapeAvatar.Clips[i].BlendShapeName.Contains(clipName)) + { + alreadyIn = true; + targetIndex = i; + break; + } + } + + // 소문ìžë¡œ ì²´í¬ë˜ì§€ ì•Šì„ ê²½ìš° 앞글ìžê°€ 대문ìžì¸ 경우 ì²´í¬ + if (!alreadyIn) + { + for (int i = 0; i < proxy.BlendShapeAvatar.Clips.Count; i++) + { + if (proxy.BlendShapeAvatar.Clips[i].BlendShapeName.Contains(upperFirstName)) + { + alreadyIn = true; + targetIndex = i; + break; + } + } + } + + // 블쉪í´ë¦½ 유무를 ì²´í¬ ì™„ë£Œí•¨ (í´ë¦½ ë„¤ìž„ì„ ì°¾ì•˜ë˜ ê±°ìž„) + + // 아래는 ì‰ì´í”„키 ë„¤ìž„ì„ ì°¾ìŒ + + // 소문ìžë¡œ ì­‰ 찾아봄 + int blendshapeIndex = body.sharedMesh.GetBlendShapeIndex(lowerFirstName); + // 해당하는 블랜드ì‰ì´í”„ê°€ ì—†ì„ ê²½ìš° 대문ìžë¡œ 한번 찾아봄 + if (blendshapeIndex < 0) + { + blendshapeIndex = body.sharedMesh.GetBlendShapeIndex(upperFirstName); + + // ì•„ì§ë„ 없으면 반환 + if (blendshapeIndex < 0) + { + return; + } + } + + // 블랜드ì‰ì´í”„키가 존재할 경우 로ì§ì„ 수행함 + + if (alreadyIn) + { + // 블쉪í´ë¦½ì´ ì´ë¯¸ 존재한다면 그걸로 ë“±ë¡ + bsClip = proxy.BlendShapeAvatar.Clips[targetIndex]; + } + else + { + // 블쉪í´ë¦½ì´ 존재하지 않는다면 새로 ìƒì„± + string fileName = $"{path}/{clipName}.asset"; + fileName = AssetDatabase.GenerateUniqueAssetPath(fileName); + + // Create new BlendShapeClip + bsClip = BlendShapeAvatar.CreateBlendShapeClip(fileName); + bsClip.BlendShapeName = lowerFirstName; + bsClip.Preset = BlendShapePreset.Unknown; + + proxy.BlendShapeAvatar.Clips.Add(bsClip); + } + + // Add BlendShapeBinding + var bsb = new BlendShapeBinding + { + RelativePath = body.name, + Index = blendshapeIndex, + Weight = 100 + }; + + if (!IsBindingAlreadySet(bsClip, bsb)) + { + Array.Resize(ref bsClip.Values, bsClip.Values.Length + 1); + bsClip.Values[bsClip.Values.Length - 1] = bsb; + } + + // Save changes + EditorUtility.SetDirty(bsClip); + EditorUtility.SetDirty(proxy.BlendShapeAvatar); + AssetDatabase.SaveAssets(); + Debug.Log($"Successfully created BlendShapeClip: {clipName}"); + } + + + //private void CreateClipByName(string path, string clipName, SkinnedMeshRenderer body) + //{ + // Debug.Log($"Creating BlendShapeClip: {clipName} / {body.name}"); + + // // Lowercase/Uppercase 처리 + // clipName = LowercaseFirstLetter(clipName); + // string upperFirstName = CapitalizeFirstLetter(clipName); + + // // Check if BlendShapeClip already exists + // BlendShapeClip bsClip = proxy.BlendShapeAvatar.Clips.Find( + // clip => clip.BlendShapeName.Equals(clipName, StringComparison.OrdinalIgnoreCase) || + // clip.BlendShapeName.Equals(upperFirstName, StringComparison.OrdinalIgnoreCase) + // ); + + // // Find BlendShape index + // string blendshapeName = bsClip != null && bsClip.BlendShapeName.Equals(upperFirstName) ? upperFirstName : clipName; + // int blendshapeIndex = body.sharedMesh.GetBlendShapeIndex(blendshapeName); + + // if (blendshapeIndex < 0) + // { + // Debug.LogWarning($"BlendShape '{blendshapeName}' not found in SkinnedMeshRenderer '{body.name}'."); + // return; + // } + + // if (bsClip == null) + // { + // // Generate unique path for the new BlendShapeClip + // string fileName = $"{path}/{clipName}.asset"; + // fileName = AssetDatabase.GenerateUniqueAssetPath(fileName); + + // // Create new BlendShapeClip + // bsClip = BlendShapeAvatar.CreateBlendShapeClip(fileName); + + // if (bsClip == null) + // { + // Debug.LogError($"Failed to create BlendShapeClip: {fileName}"); + // return; + // } + + // bsClip.BlendShapeName = clipName; + // proxy.BlendShapeAvatar.Clips.Add(bsClip); + // } + + // // Add BlendShapeBinding + // var bsb = new BlendShapeBinding + // { + // RelativePath = body.name, + // Index = blendshapeIndex, + // Weight = 100 + // }; + + // if (!IsBindingAlreadySet(bsClip, bsb)) + // { + // Array.Resize(ref bsClip.Values, bsClip.Values.Length + 1); + // bsClip.Values[bsClip.Values.Length - 1] = bsb; + // } + + // // Save changes + // EditorUtility.SetDirty(proxy.BlendShapeAvatar); + // AssetDatabase.SaveAssets(); + // Debug.Log($"Successfully created BlendShapeClip: {clipName}"); + //} + private bool IsBindingAlreadySet(BlendShapeClip clip, BlendShapeBinding binding) + { + foreach (var value in clip.Values) + { + if (value.RelativePath == binding.RelativePath && value.Index == binding.Index) + { + return true; + } + } + return false; + } + + private string CapitalizeFirstLetter(string input) + { + if (string.IsNullOrEmpty(input)) + return input; + + return char.ToUpper(input[0]) + input.Substring(1); + } + + private string LowercaseFirstLetter(string input) + { + if (string.IsNullOrEmpty(input)) + return input; + + return char.ToLower(input[0]) + input.Substring(1); + } + } +} + +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/ARKitAdder.cs.meta b/Assets/Scripts/Bitd/Scripts/ARKitAdder.cs.meta new file mode 100644 index 000000000..cf5a3b52d --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/ARKitAdder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c55036b08c579624eb21273ad996f0af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/BlendshapeModifier.cs b/Assets/Scripts/Bitd/Scripts/BlendshapeModifier.cs new file mode 100644 index 000000000..7f445d41f --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/BlendshapeModifier.cs @@ -0,0 +1,261 @@ +#if UNITY_EDITOR +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; + +namespace Bitd +{ + public class BlendshapeModifier : EditorWindow + { + private List gameObjects = new List(); // µå·¡±× ¾Ø µå·ÓÀ¸·Î ¹ÞÀº GameObject ¸ñ·Ï + private Dictionary blendShapes = new Dictionary(); // ºí·»µå½¦ÀÌÇÁ À̸§°ú °ª + private bool blendShapesLoaded = false; + + private Vector2 scrollPosObjects; // ¿ÀºêÁ§Æ® ¸ñ·Ï ½ºÅ©·Ñ À§Ä¡ + private Vector2 scrollPosBlendShapes; // ºí·»µå½¦ÀÌÇÁ ¸ñ·Ï ½ºÅ©·Ñ À§Ä¡ + + [MenuItem("Bitd/ºí·»µå½¦ÀÌÇÁ Àϰý¼öÁ¤", false, 2)] + public static void ShowWindow() + { + BlendshapeModifier window = GetWindow("ºí·»µå½¦ÀÌÇÁ ¼öÁ¤±â"); + window.position = new Rect(100, 100, 400, 900); + } + + void OnGUI() + { + GUILayout.Label("¾Æ·¡¿¡ °ÔÀÓ¿ÀºêÁ§Æ®µéÀ» ³Ö¾îÁÖ¼¼¿ä", EditorStyles.boldLabel); + GUILayout.Label("¸ðµç ¿ÀºêÁ§Æ®¿¡¼­ ºí·»µå½¦ÀÌÇÁÀÇ °ªÀ» ºÒ·¯¿Í Àϰý ¼öÁ¤ÇÕ´Ï´Ù.", EditorStyles.helpBox); + + // µå·¡±× ¾Ø µå·Ó ±¸¿ª »ý¼º + GUILayout.Space(10); + EditorGUILayout.HelpBox("µå·¡±× ¾Ø µå·ÓÀ¸·Î °ÔÀÓ ¿ÀºêÁ§Æ®¸¦ Ãß°¡Çϼ¼¿ä", MessageType.Info); + Rect dropArea = GUILayoutUtility.GetRect(0, 50, GUILayout.ExpandWidth(true)); + GUI.Box(dropArea, "¿©±â¿¡ µå·¡±×Çϼ¼¿ä", EditorStyles.helpBox); + HandleDragAndDrop(dropArea); + + // µå·¡±×µÈ °ÔÀÓ ¿ÀºêÁ§Æ® ¸®½ºÆ® Ç¥½Ã + GUILayout.Label("Ãß°¡µÈ °ÔÀÓ¿ÀºêÁ§Æ®:", EditorStyles.boldLabel); + scrollPosObjects = EditorGUILayout.BeginScrollView(scrollPosObjects, GUILayout.Height(100)); // ÃÖ´ë ³ôÀÌ Á¦ÇÑ + foreach (var go in gameObjects) + { + EditorGUILayout.ObjectField(go, typeof(GameObject), true); + } + EditorGUILayout.EndScrollView(); + GUILayout.Space(10); + + // ºí·»µå½¦ÀÌÇÁ °¡Á®¿À±â ¹öư + if (GUILayout.Button("ºí·»µå½¦ÀÌÇÁ °¡Á®¿À±â")) + { + LoadBlendShapes(); + } + + // ºÒ·¯¿Â ºí·»µå½¦ÀÌÇÁ ¸ñ·Ï Ç¥½Ã + if (blendShapesLoaded) + { + GUILayout.Space(10); + GUILayout.Label("ºí·»µå½¦ÀÌÇÁ °ª ¼³Á¤:", EditorStyles.boldLabel); + + scrollPosBlendShapes = EditorGUILayout.BeginScrollView(scrollPosBlendShapes, GUILayout.Height(500)); // ½ºÅ©·Ñºä ½ÃÀÛ + // DictionaryÀÇ Å°¿Í °ªÀ» º¹»çÇÏ¿© »ç¿ë + List keys = new List(blendShapes.Keys); + List values = new List(blendShapes.Values); + + for (int i = 0; i < keys.Count; i++) + { + values[i] = EditorGUILayout.Slider(keys[i], values[i], 0f, 100f); + } + + // º¯°æµÈ °ªÀ» ´Ù½Ã Dictionary¿¡ ¾÷µ¥ÀÌÆ® + for (int i = 0; i < keys.Count; i++) + { + blendShapes[keys[i]] = values[i]; + } + + EditorGUILayout.EndScrollView(); // ½ºÅ©·Ñºä Á¾·á + + GUILayout.Space(10); + + // ºí·»µå½¦ÀÌÇÁ ¼öÁ¤Çϱ⠹öư + if (GUILayout.Button("ºí·»µå½¦ÀÌÇÁ ¼öÁ¤Çϱâ")) + { + ApplyBlendShapes(); + } + } + } + + // µå·¡±× ¾Ø µå·Ó ó¸® + void HandleDragAndDrop(Rect dropArea) + { + Event evt = Event.current; + + switch (evt.type) + { + case EventType.DragUpdated: + case EventType.DragPerform: + if (!dropArea.Contains(evt.mousePosition)) + return; + + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + + if (evt.type == EventType.DragPerform) + { + DragAndDrop.AcceptDrag(); + + foreach (Object draggedObject in DragAndDrop.objectReferences) + { + if (draggedObject is GameObject) + { + gameObjects.Add((GameObject)draggedObject); // °ÔÀÓ ¿ÀºêÁ§Æ® Ãß°¡ + } + } + + evt.Use(); + } + break; + } + } + // ºí·»µå½¦ÀÌÇÁ¸¦ °¡Á®¿À´Â ÇÔ¼ö + void LoadBlendShapes() + { + blendShapes.Clear(); // ±âÁ¸ µ¥ÀÌÅ͸¦ ÃʱâÈ­ + blendShapesLoaded = true; + + SortedDictionary sortedBlendShapes = new SortedDictionary(); + + foreach (GameObject obj in gameObjects) + { + if (obj == null) continue; + + List skinnedMeshRenderers = FindAllSkinnedMeshRenderers(obj); + + foreach (SkinnedMeshRenderer skinnedMeshRenderer in skinnedMeshRenderers) + { + if (skinnedMeshRenderer == null) continue; + Mesh mesh = skinnedMeshRenderer.sharedMesh; + + if (mesh == null) continue; + + for (int i = 0; i < mesh.blendShapeCount; i++) + { + string blendShapeName = mesh.GetBlendShapeName(i); + + // Áߺ¹µÇÁö ¾Ê´Â ºí·»µå½¦ÀÌÇÁ À̸§¸¸ Ãß°¡ + if (!sortedBlendShapes.ContainsKey(blendShapeName)) + { + sortedBlendShapes.Add(blendShapeName, skinnedMeshRenderer.GetBlendShapeWeight(i)); + } + } + } + } + + // Á¤·ÄµÈ ºí·»µå½¦ÀÌÇÁ¸¦ Dictionary¿¡ º¹»ç + blendShapes = new Dictionary(sortedBlendShapes); + } + + void ApplyBlendShapes() + { + Undo.IncrementCurrentGroup(); + Undo.SetCurrentGroupName("Modify All Blendshapes"); + + foreach (GameObject obj in gameObjects) + { + if (obj == null) continue; + + List skinnedMeshRenderers = FindAllSkinnedMeshRenderers(obj); + + foreach (SkinnedMeshRenderer skinnedMeshRenderer in skinnedMeshRenderers) + { + if (skinnedMeshRenderer == null) continue; + + Undo.RecordObject(skinnedMeshRenderer, "Modify Blendshape"); + + Mesh mesh = skinnedMeshRenderer.sharedMesh; + + if (mesh == null) continue; + + foreach (var blendShape in blendShapes) + { + int blendShapeIndex = mesh.GetBlendShapeIndex(blendShape.Key); + if (blendShapeIndex != -1 && skinnedMeshRenderer.GetBlendShapeWeight(blendShapeIndex) != blendShape.Value) + { + skinnedMeshRenderer.SetBlendShapeWeight(blendShapeIndex, blendShape.Value); + Debug.Log($"{obj.name}ÀÇ {blendShape.Key} ºí·»µå½¦ÀÌÇÁ°¡ {blendShape.Value}À¸·Î ¼³Á¤µÇ¾ú½À´Ï´Ù!"); + } + } + + EditorUtility.SetDirty(skinnedMeshRenderer); + } + } + + Undo.CollapseUndoOperations(Undo.GetCurrentGroup()); + } + //void ModifyBlendShapes() + //{ + // foreach (GameObject obj in gameObjects) + // { + // if (obj == null) continue; + + // // SkinnedMeshRenderer ÄÄÆ÷³ÍÆ®¸¦ °¡Áø ¿ÀºêÁ§Æ® ã±â + // List skinnedMeshRenderers = FindAllSkinnedMeshRenderers(obj); + + // foreach (SkinnedMeshRenderer skinnedMeshRenderer in skinnedMeshRenderers) + // { + // if (skinnedMeshRenderer != null) + // { + // Mesh mesh = skinnedMeshRenderer.sharedMesh; + + // // ºí·»µå½¦ÀÌÇÁ À妽º ã±â + // int blendShapeIndex = FindBlendShapeIndex(mesh, blendshapeName); + + // if (blendShapeIndex != -1) + // { + // // ºí·»µå½¦ÀÌÇÁ °ª º¯°æ + // skinnedMeshRenderer.SetBlendShapeWeight(blendShapeIndex, blendshapeValue); + // Debug.Log($"{obj.name}¿¡ ÀÖ´Â {blendshapeName}(ÀÌ)°¡ {blendshapeValue}À¸·Î ¼öÁ¤µÇ¾úÀ½!"); + // } + // } + // } + + // } + //} + + List FindAllSkinnedMeshRenderers(GameObject obj) + { + List skinnedMeshRenderers = new List(); + + // ºñȰ¼ºÈ­µÈ ¿ÀºêÁ§Æ®µµ Æ÷ÇÔÇÏ¿© ¸ðµç ¿ÀºêÁ§Æ® ¼öÁý + Object[] allObjects = EditorUtility.CollectDeepHierarchy(new Object[] { obj }); + + // °¢ ¿ÀºêÁ§Æ®¿¡¼­ SkinnedMeshRenderer ÄÄÆ÷³ÍÆ® ÃßÃâ + foreach (Object o in allObjects) + { + if (o is GameObject) + { + GameObject go = (GameObject)o; + SkinnedMeshRenderer[] renderers = go.GetComponentsInChildren(true); // true¸¦ »ç¿ëÇØ ºñȰ¼ºÈ­µÈ ÀڽıîÁö Æ÷ÇÔ + skinnedMeshRenderers.AddRange(renderers); + } + } + + return skinnedMeshRenderers; + } + + // ºí·»µå½¦ÀÌÇÁÀÇ À妽º¸¦ ã´Â ÇÔ¼ö + int FindBlendShapeIndex(Mesh mesh, string blendShapeName) + { + if (mesh == null) return -1; + + // ºí·»µå½¦ÀÌÇÁ À̸§À¸·Î À妽º ã±â + for (int i = 0; i < mesh.blendShapeCount; i++) + { + if (mesh.GetBlendShapeName(i) == blendShapeName) + { + return i; + } + } + + return -1; // ÇØ´ç ºí·»µå½¦ÀÌÇÁ°¡ ¾øÀ» °æ¿ì -1 ¹Ýȯ + } + } +} +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/BlendshapeModifier.cs.meta b/Assets/Scripts/Bitd/Scripts/BlendshapeModifier.cs.meta new file mode 100644 index 000000000..21c4c2d4f --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/BlendshapeModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 959af977ade842e47802e70e3207b2c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/DduDda.cs b/Assets/Scripts/Bitd/Scripts/DduDda.cs new file mode 100644 index 000000000..333cacb56 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/DduDda.cs @@ -0,0 +1,94 @@ +#if UNITY_EDITOR +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace Bitd +{ + public class DduDda : EditorWindow + { + private GameObject gameObject1; + private GameObject gameObject2; + private string suffix = string.Empty; + private bool exceptBreast = false; + + [MenuItem("Bitd/뜌땨 v16", false, 1)] + public static void ShowWindow() + { + GetWindow("뜌뜌땨?뜌?"); + } + + private void OnGUI() + { + GUILayout.Label("뜌뜌땨땨", EditorStyles.boldLabel); + + gameObject1 = (GameObject)EditorGUILayout.ObjectField("ì›ë³¸ 아마추어", gameObject1, typeof(GameObject), true); + gameObject2 = (GameObject)EditorGUILayout.ObjectField("ì˜ìƒì˜ 아마추어", gameObject2, typeof(GameObject), true); + + suffix = EditorGUILayout.TextField("ë’¤ì— ë¶™ì¼ ë¬¸êµ¬", suffix); + exceptBreast = EditorGUILayout.Toggle("ê°€ìŠ´ë³¸ì€ ë„£ì§€ ë§ê¹Œìš”?", exceptBreast); + + if (GUILayout.Button("병합하기")) + { + MergeGameObjects(); + } + } + + private void MergeGameObjects() + { + if (gameObject1 == null || gameObject2 == null) + { + Debug.LogWarning("ë‘ ê°œ 다 제대로 넣어주세요."); + return; + } + + Undo.IncrementCurrentGroup(); + int undoGroup = Undo.GetCurrentGroup(); + + List children2 = GetAllChildren(gameObject2); + List children1 = GetAllChildren(gameObject1); + + foreach (GameObject child2 in children2) + { + bool isBreast = child2.name.Contains("breast") || child2.name.Contains("Breast"); + + if (!(exceptBreast && isBreast)) + { + foreach (GameObject child1 in children1) + { + if (child1.name == child2.name) + { + // ì´ë¦„ì´ ê°™ì€ ê²½ìš°, child2를 child1ì˜ ìžì‹ìœ¼ë¡œ ì´ë™ + Undo.SetTransformParent(child2.transform, child1.transform, "Merge GameObjects"); + break; + } + } + } + + // 모든 child2 오브ì íŠ¸ì— ì ‘ë¯¸ì‚¬ 추가 + Undo.RecordObject(child2, "Rename GameObject"); + child2.name += suffix; + } + + // Undo 그룹 종료 ë° ë³‘í•© + Undo.CollapseUndoOperations(undoGroup); + + gameObject2 = null; + + Debug.Log("Merging completed."); + } + + private List GetAllChildren(GameObject parent) + { + List children = new List(); + foreach (Transform child in parent.transform) + { + children.Add(child.gameObject); + children.AddRange(GetAllChildren(child.gameObject)); + } + return children; + } + } +} + +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/DduDda.cs.meta b/Assets/Scripts/Bitd/Scripts/DduDda.cs.meta new file mode 100644 index 000000000..f5b11dec7 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/DduDda.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6934676cd7b0e2849bbce7d053db3f5d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/FunctionAdder.cs b/Assets/Scripts/Bitd/Scripts/FunctionAdder.cs new file mode 100644 index 000000000..5cb9049a8 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/FunctionAdder.cs @@ -0,0 +1,292 @@ + +#if UNITY_EDITOR +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using UnityEditor.Animations; + +namespace Bitd +{ + public class FunctionAdder : EditorWindow + { + AnimatorController animatorController; + string layerName = string.Empty; + string parameterName = string.Empty; + List animationClips = new List(); // List·Î º¯°æÇÏ¿© µ¿ÀûÀ¸·Î °ü¸® + AnimationClip onAnimationClip = null; // On ¾Ö´Ï¸ÞÀÌ¼Ç + AnimationClip offAnimationClip = null; // Off ¾Ö´Ï¸ÞÀÌ¼Ç + bool isOnOffMode = false; // ¿Â¿ÀÇÁ ¸ðµå ¿©ºÎ¸¦ °áÁ¤ÇÏ´Â º¯¼ö + private bool isHair = false; + private bool isClothes = false; + + [MenuItem("Bitd/¾Ö´Ï¸ÞÀÌÅÍ ±â´É µî·Ï", false, 51)] + public static void ShowWindow() + { + GetWindow("‹x~"); + } + + void OnGUI() + { + GUILayout.Label("±â´É µî·Ï Åø", EditorStyles.boldLabel); + + // ¾Ö´Ï¸ÞÀÌÅÍ ¼±Åà Çʵå + animatorController = (AnimatorController)EditorGUILayout.ObjectField("Ÿ°Ù ¾Ö´Ï¸ÞÀÌÅÍ", animatorController, typeof(AnimatorController), false); + + isHair = EditorGUILayout.Toggle("Çì¾îÀΰ¡¿ä?", isHair); + isClothes = EditorGUILayout.Toggle("¿ÊÀΰ¡¿ä?", isClothes); + GUILayout.Space(5); + layerName = EditorGUILayout.TextField("·¹À̾î À̸§", layerName); + parameterName = EditorGUILayout.TextField("ÆÄ¶ó¹ÌÅÍ À̸§", parameterName); + GUILayout.Space(5); + if (isHair) + { + layerName = "Hair Change"; + parameterName = "HairIndex"; + } + else if (isClothes) + { + layerName = "Clothes Change"; + parameterName = "ClothesIndex"; + } + + isOnOffMode = EditorGUILayout.Toggle("¿Â¿ÀÇÁÀΰ¡¿ä?", isOnOffMode); + + // ¿Â¿ÀÇÁ ¸ðµå¿¡ µû¸¥ UI ó¸® + if (isOnOffMode) + { + // ¿Â¿ÀÇÁ ¸ðµåÀÏ ¶§ On, Off ¾Ö´Ï¸ÞÀÌ¼Ç ¼±Åà ¿µ¿ª + onAnimationClip = (AnimationClip)EditorGUILayout.ObjectField("On ¾Ö´Ï¸ÞÀ̼Ç", onAnimationClip, typeof(AnimationClip), false); + offAnimationClip = (AnimationClip)EditorGUILayout.ObjectField("Off ¾Ö´Ï¸ÞÀ̼Ç", offAnimationClip, typeof(AnimationClip), false); + } + else + { + // µå·¡±× ¾Ø µå·Ó ±¸¿ª »ý¼º + GUILayout.Space(10); + EditorGUILayout.HelpBox("¾Ö´Ï¸ÞÀÌ¼Ç Å¬¸³À» µå·¡±×ÇÏ¿© Ãß°¡Çϼ¼¿ä.", MessageType.Info); + Rect dropArea = GUILayoutUtility.GetRect(0, 50, GUILayout.ExpandWidth(true)); + GUI.Box(dropArea, "¿©±â¿¡ ³Ö¾îÁÖ¼¼¿ä", EditorStyles.helpBox); + HandleDragAndDrop(dropArea); + + // µå·¡±×µÈ ¾Ö´Ï¸ÞÀÌ¼Ç Å¬¸³ Ç¥½Ã + GUILayout.Label("Ãß°¡µÈ ¾Ö´Ï¸ÞÀÌ¼Ç Å¬¸³:", EditorStyles.boldLabel); + for (int i = 0; i < animationClips.Count; i++) + { + EditorGUILayout.ObjectField(animationClips[i], typeof(AnimationClip), false); + } + } + + if (GUILayout.Button("Àû¿ë")) + { + if (animatorController != null) + { + if (isOnOffMode && onAnimationClip != null && offAnimationClip != null) + { + AddLayerAndSetupOnOffAnimations(animatorController, layerName, onAnimationClip, offAnimationClip, parameterName); + } + else if (!isOnOffMode && animationClips.Count > 0) + { + AddLayerAndSetupAnimations(animatorController, layerName, animationClips.ToArray(), parameterName); + animationClips = new List(); + } + else + { + Debug.LogWarning("¾Ö´Ï¸ÞÀÌÅͳª ¾Ö´Ï¸ÞÀÌ¼Ç Å¬¸³ÀÌ ºÎÁ·ÇÕ´Ï´Ù."); + } + } + } + } + void HandleDragAndDrop(Rect dropArea) + { + Event evt = Event.current; + + switch (evt.type) + { + case EventType.DragUpdated: + case EventType.DragPerform: + if (!dropArea.Contains(evt.mousePosition)) + return; + + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + + if (evt.type == EventType.DragPerform) + { + DragAndDrop.AcceptDrag(); + + foreach (Object draggedObject in DragAndDrop.objectReferences) + { + if (draggedObject is AnimationClip) + { + animationClips.Add((AnimationClip)draggedObject); // ¾Ö´Ï¸ÞÀÌ¼Ç Å¬¸³ Ãß°¡ + } + } + + evt.Use(); + } + break; + } + } + + // ¿Â¿ÀÇÁ ¾Ö´Ï¸ÞÀÌ¼Ç ¼³Á¤ + void AddLayerAndSetupOnOffAnimations(AnimatorController animatorController, string layerName, AnimationClip onClip, AnimationClip offClip, string parameterName) + { + // ·¹À̾ Á¸ÀçÇÏ´ÂÁö È®ÀÎ + AnimatorControllerLayer targetLayer = null; + foreach (var layer in animatorController.layers) + { + if (layer.name == layerName) + { + targetLayer = layer; + break; + } + } + + // ·¹À̾ ¾øÀ¸¸é »õ·Î »ý¼º + if (targetLayer == null) + { + targetLayer = new AnimatorControllerLayer + { + name = layerName, + stateMachine = new AnimatorStateMachine(), + defaultWeight = 1 + }; + animatorController.AddLayer(targetLayer); + + targetLayer.stateMachine.name = $"{layerName}_StateMachine"; + + // »ý¼ºÇÑ stateMachineÀ» ¾Ö¼ÂÀ¸·Î ÀúÀå + AssetDatabase.AddObjectToAsset(targetLayer.stateMachine, animatorController); + } + else if (targetLayer.stateMachine == null) // ±âÁ¸ ·¹À̾ ÀÖÁö¸¸ stateMachineÀÌ ¾øÀ¸¸é »õ·Î »ý¼º + { + targetLayer.stateMachine = new AnimatorStateMachine(); + targetLayer.stateMachine.name = $"{layerName}_StateMachine"; + AssetDatabase.AddObjectToAsset(targetLayer.stateMachine, animatorController); + } + + // ¾Ö¼ÂÀ» ÀúÀåÇÏ¿© À¯´ÏƼ ¿¡µðÅͰ¡ º¯°æ»çÇ×À» ÀÒÁö ¾Êµµ·Ï º¸Àå + AssetDatabase.SaveAssets(); + + // StateMachine ÂüÁ¶ + AnimatorStateMachine stateMachine = targetLayer.stateMachine; + + // ÆÄ¶ó¹ÌÅͰ¡ ÀÖ´ÂÁö È®ÀÎÇÏ°í ¾øÀ¸¸é »ý¼º (bool ŸÀÔ) + if (!HasParameter(animatorController, parameterName)) + { + animatorController.AddParameter(parameterName, AnimatorControllerParameterType.Bool); + } + + // On »óÅ Ãß°¡ + AnimatorState onState = stateMachine.AddState(onClip.name); + onState.motion = onClip; + + // Off »óÅ Ãß°¡ + AnimatorState offState = stateMachine.AddState(offClip.name); + offState.motion = offClip; + + // On¿¡¼­ Off·ÎÀÇ Æ®·£Áö¼Ç Ãß°¡ (falseÀÏ ¶§) + AnimatorStateTransition onToOffTransition = onState.AddTransition(offState); + onToOffTransition.exitTime = 0; + onToOffTransition.hasExitTime = false; + onToOffTransition.hasFixedDuration = false; + onToOffTransition.duration = 0; + onToOffTransition.AddCondition(AnimatorConditionMode.IfNot, 0, parameterName); // ÆÄ¶ó¹ÌÅͰ¡ falseÀÏ ¶§ + + // Off¿¡¼­ OnÀ¸·ÎÀÇ Æ®·£Áö¼Ç Ãß°¡ (trueÀÏ ¶§) + AnimatorStateTransition offToOnTransition = offState.AddTransition(onState); + offToOnTransition.exitTime = 0; + offToOnTransition.hasExitTime = false; + offToOnTransition.hasFixedDuration = false; + offToOnTransition.duration = 0; + offToOnTransition.AddCondition(AnimatorConditionMode.If, 0, parameterName); // ÆÄ¶ó¹ÌÅͰ¡ trueÀÏ ¶§ + + Debug.Log("On/Off ¾Ö´Ï¸ÞÀÌ¼Ç ¼¼ÆÃ ¿Ï·á."); + } + void AddLayerAndSetupAnimations(AnimatorController animatorController, string layerName, AnimationClip[] animationClips, string parameterName) + { + // ·¹À̾ Á¸ÀçÇÏ´ÂÁö È®ÀÎ + AnimatorControllerLayer targetLayer = null; + foreach (var layer in animatorController.layers) + { + if (layer.name == layerName) + { + targetLayer = layer; + break; + } + } + + // ·¹À̾ ¾øÀ¸¸é »õ·Î »ý¼º + if (targetLayer == null) + { + targetLayer = new AnimatorControllerLayer + { + name = layerName, + stateMachine = new AnimatorStateMachine(), + defaultWeight = 1 + }; + animatorController.AddLayer(targetLayer); + + targetLayer.stateMachine.name = $"{layerName}_StateMachine"; + + // »ý¼ºÇÑ stateMachineÀ» ¾Ö¼ÂÀ¸·Î ÀúÀå + AssetDatabase.AddObjectToAsset(targetLayer.stateMachine, animatorController); + } + else if (targetLayer.stateMachine == null) // ±âÁ¸ ·¹À̾ ÀÖÁö¸¸ stateMachineÀÌ ¾øÀ¸¸é »õ·Î »ý¼º + { + targetLayer.stateMachine = new AnimatorStateMachine(); + targetLayer.stateMachine.name = $"{layerName}_StateMachine"; + AssetDatabase.AddObjectToAsset(targetLayer.stateMachine, animatorController); + } + + // ¾Ö¼ÂÀ» ÀúÀåÇÏ¿© À¯´ÏƼ ¿¡µðÅͰ¡ º¯°æ»çÇ×À» ÀÒÁö ¾Êµµ·Ï º¸Àå + AssetDatabase.SaveAssets(); + + // Any State·ÎºÎÅÍÀÇ ÀüȯÀ» À§ÇÑ StateMachine ÂüÁ¶ + AnimatorStateMachine stateMachine = targetLayer.stateMachine; + + // ÆÄ¶ó¹ÌÅͰ¡ ÀÖ´ÂÁö È®ÀÎÇÏ°í ¾øÀ¸¸é »ý¼º + if (!HasParameter(animatorController, parameterName)) + { + animatorController.AddParameter(parameterName, AnimatorControllerParameterType.Int); + } + + // ±âÁ¸ ·¹À̾îÀÇ ¾Ö´Ï¸ÞÀÌ¼Ç »óÅ °³¼ö È®ÀÎ + int existingStateCount = stateMachine.states.Length; + + // ¾Ö´Ï¸ÞÀÌ¼Ç »óÅ »ý¼º ¹× ¼³Á¤ + for (int i = 0; i < animationClips.Length; i++) + { + AnimationClip clip = animationClips[i]; + + // ¾Ö´Ï¸ÞÀÌ¼Ç »óÅ Ãß°¡ + AnimatorState state = stateMachine.AddState(clip.name); + state.motion = clip; + + // Any State¿¡¼­ ÇØ´ç ¾Ö´Ï¸ÞÀÌ¼Ç »óÅ·ΠÀüȯ Ãß°¡ + AnimatorStateTransition transition = stateMachine.AddAnyStateTransition(state); + transition.exitTime = 0; + transition.hasExitTime = false; + transition.hasFixedDuration = false; + transition.duration = 0; + + // ±âÁ¸ »óÅ °³¼ö¸¦ °í·ÁÇÏ¿© À妽º¸¦ ¼³Á¤ + transition.AddCondition(AnimatorConditionMode.Equals, existingStateCount + i, parameterName); + } + Debug.Log("Layer and animations successfully set up."); + } + + // ÆÄ¶ó¹ÌÅͰ¡ ÀÌ¹Ì ÀÖ´ÂÁö È®ÀÎÇÏ´Â ÇÔ¼ö + bool HasParameter(AnimatorController animatorController, string paramName) + { + foreach (var param in animatorController.parameters) + { + if (param.name == paramName) + { + return true; + } + } + return false; + } + } + +} +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/FunctionAdder.cs.meta b/Assets/Scripts/Bitd/Scripts/FunctionAdder.cs.meta new file mode 100644 index 000000000..3ef906e02 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/FunctionAdder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5ca74b97d9f52c041877b917361b3bd6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/LiltoonOutlineModifier.cs b/Assets/Scripts/Bitd/Scripts/LiltoonOutlineModifier.cs new file mode 100644 index 000000000..7c791cad7 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/LiltoonOutlineModifier.cs @@ -0,0 +1,145 @@ +#if UNITY_EDITOR +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; + +namespace Bitd +{ + public class LiltoonOutlineModifier : EditorWindow + { + private List gameObjects = new List(); // µå·¡±× ¾Ø µå·ÓÀ¸·Î ¹ÞÀº GameObject ¸ñ·Ï + private string shaderNameToCheck = "lilToon"; // È®ÀÎÇÒ ½¦ÀÌ´õ À̸§ + private string parameterNameToCheck = "_OutlineWidth"; // È®ÀÎÇÒ ÆÄ¶ó¹ÌÅÍ À̸§ + private float parameterValue = 0; + + [MenuItem("Bitd/(¸±Å÷)¾Æ¿ô¶óÀÎ ¼öÁ¤±â", false, 101)] + public static void ShowWindow() + { + GetWindow("¾Æ¿ô¶óÀÎ ¼öÁ¤±â"); + } + + void OnGUI() + { + parameterValue = EditorGUILayout.Slider("¾Æ¿ô¶óÀÎ °ª", parameterValue, 0f, 1f); + + + GUILayout.Label("¾Æ·¡¿¡ °ÔÀÓ¿ÀºêÁ§Æ®µéÀ» ³Ö¾îÁÖ¼¼¿ä", EditorStyles.boldLabel); + + // µå·¡±× ¾Ø µå·Ó ±¸¿ª »ý¼º + GUILayout.Space(10); + GUILayout.Label("¼öÁ¤ÇÒ °ÔÀÓ¿ÀºêÁ§Æ®µé:", EditorStyles.helpBox); + Rect dropArea = GUILayoutUtility.GetRect(0, 50, GUILayout.ExpandWidth(true)); + HandleDragAndDrop(dropArea); + + // µå·¡±×µÈ °ÔÀÓ ¿ÀºêÁ§Æ® ¸®½ºÆ® Ç¥½Ã + GUILayout.Label("Ãß°¡µÈ °ÔÀÓ¿ÀºêÁ§Æ®:", EditorStyles.boldLabel); + foreach (var go in gameObjects) + { + EditorGUILayout.ObjectField(go, typeof(GameObject), true); + } + GUILayout.Space(5); + // Àû¿ë ¹öư + if (GUILayout.Button("¾Æ¿ô¶óÀÎ Àϰý¼öÁ¤Çϱâ")) + { + ModifyMaterials(); + gameObjects.Clear(); + } + } + + // µå·¡±× ¾Ø µå·Ó ó¸® + void HandleDragAndDrop(Rect dropArea) + { + Event evt = Event.current; + + switch (evt.type) + { + case EventType.DragUpdated: + case EventType.DragPerform: + if (!dropArea.Contains(evt.mousePosition)) + return; + + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + + if (evt.type == EventType.DragPerform) + { + DragAndDrop.AcceptDrag(); + + foreach (Object draggedObject in DragAndDrop.objectReferences) + { + if (draggedObject is GameObject) + { + gameObjects.Add((GameObject)draggedObject); // °ÔÀÓ ¿ÀºêÁ§Æ® Ãß°¡ + } + } + + evt.Use(); + } + break; + } + } + + // MaterialÀ» ã¾Æ¼­ ÆÄ¶ó¹ÌÅ͸¦ ¼öÁ¤ÇÏ´Â ÇÔ¼ö + void ModifyMaterials() + { + foreach (GameObject go in gameObjects) + { + if (go == null) continue; + + // °ÔÀÓ ¿ÀºêÁ§Æ®¿Í ÀÚ½Ä ¿ÀºêÁ§Æ®µé °¡Á®¿À±â + List renderers = FindAllRenderers(go); + foreach (Renderer renderer in renderers) + { + // °¢ ·»´õ·¯¿¡¼­ »ç¿ëÇÏ´Â ¸ðµç ¸ÓƼ¸®¾ó È®ÀÎ + foreach (Material material in renderer.sharedMaterials) + { + if (material != null && material.shader != null) + { + // ƯÁ¤ ½¦ÀÌ´õÀÎÁö È®ÀÎ + if (material.shader.name.Contains(shaderNameToCheck)) + { + // ÆÄ¶ó¹ÌÅͰ¡ Á¸ÀçÇÏ´ÂÁö È®ÀÎÇÏ°í ¼öÁ¤ + if (material.HasProperty(parameterNameToCheck)) + { + material.SetFloat(parameterNameToCheck, parameterValue); + Debug.Log($"{go.name}¿¡ ÀÖ´Â {material.name} ¸ÓƼ¸®¾óÀÌ ¼öÁ¤µÇ¾ú¾î¿ä!"); + } + else + { + Debug.Log($"{go.name}ÀÇ {material.name} ¸ÓƼ¸®¾ó¿¡´Â ÇØ´ç °ªÀÌ ¾ø¾ú¾î¿ä!"); + } + } + } + } + } + } + + // º¯°æ »çÇ× ÀúÀå + AssetDatabase.SaveAssets(); + } + + // ºñȰ¼ºÈ­µÈ ¿ÀºêÁ§Æ®±îÁö Æ÷ÇÔÇÑ ¸ðµç ·»´õ·¯¸¦ ã´Â ÇÔ¼ö + List FindAllRenderers(GameObject obj) + { + List allRenderers = new List(); + + // ºñȰ¼ºÈ­µÈ ¿ÀºêÁ§Æ®µµ Æ÷ÇÔÇÏ¿© ¸ðµç ¿ÀºêÁ§Æ® ¼öÁý + Object[] allObjects = EditorUtility.CollectDeepHierarchy(new Object[] { obj }); + + // °¢ ¿ÀºêÁ§Æ®¿¡¼­ Renderer ÄÄÆ÷³ÍÆ® ÃßÃâ + foreach (Object o in allObjects) + { + if (o is GameObject) + { + GameObject go = (GameObject)o; + Renderer[] renderers = go.GetComponentsInChildren(true); // true¸¦ »ç¿ëÇØ ºñȰ¼ºÈ­µÈ ÀڽıîÁö Æ÷ÇÔ + allRenderers.AddRange(renderers); + } + } + + return allRenderers; + } + } + +} + +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/LiltoonOutlineModifier.cs.meta b/Assets/Scripts/Bitd/Scripts/LiltoonOutlineModifier.cs.meta new file mode 100644 index 000000000..d4b620bc8 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/LiltoonOutlineModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf1e066993613ba43abbfc12d2dca351 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/LiltoonRimLightModifier.cs b/Assets/Scripts/Bitd/Scripts/LiltoonRimLightModifier.cs new file mode 100644 index 000000000..44a341b3e --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/LiltoonRimLightModifier.cs @@ -0,0 +1,278 @@ +#if UNITY_EDITOR +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using System.Collections.Generic; + +namespace Bitd +{ + public class LiltoonRimLightModifier : EditorWindow + { + private enum RimBlendMode { 표준, 가산, 스í¬ë¦°, 곱하기 } + private List gameObjects = new List(); // 드래그 앤 드롭으로 ë°›ì€ GameObject ëª©ë¡ + private ReorderableList gameObjectsList; + + private string shaderNameToCheck = "lilToon"; // 확ì¸í•  ì‰ì´ë” ì´ë¦„ + + private string param_useRim = "_UseRim"; + + private bool useRim = true; + + private string param_rimColor = "_RimColor"; + private string param_rimMainStrength = "_RimMainStrength"; + private string param_rimEnableLighting = "_RimEnableLighting"; + private string param_rimShadowMask = "_RimShadowMask"; + private string param_rimBackfaceMask = "_RimBackfaceMask"; + private string param_rimApplyTransparency = "_RimApplyTransparency"; + private string param_rimBlendMode = "_RimBlendMode"; + + private Color rimColor = Color.white; + private float rimColorAlpha = 1f; + private float rimMainStrength = 0f; + private float rimEnableLighting = 1f; + private float rimShadowMask = 1f; + private bool rimBackfaceMask = false; + private bool rimApplyTransparency = true; + private RimBlendMode rimBlendMode = RimBlendMode.가산; + + private string param_rimDirStrength = "_RimDirStrength"; + private string param_rimBorder = "_RimBorder"; + private string param_rimBlur = "_RimBlur"; + private string param_rimNormalStrength = "_RimNormalStrength"; + private string param_rimFresnelPower = "_RimFresnelPower"; + private string param_rimVRParallaxStrength = "_RimVRParallaxStrength"; + + private float rimDirStrength = 0f; + private float rimBorder = 0.4f; + private float rimBlur = 0f; + private float rimNormalStrength = 0f; + private float rimFresnelPower = 2f; + private float rimVRParallaxStrength = 0f; + + [MenuItem("Bitd/(릴툰)림ë¼ì´íЏ 수정기", false, 104)] + public static void ShowWindow() + { + LiltoonRimLightModifier window = GetWindow("림ë¼ì´íЏ 수정기"); + window.position = new Rect(100, 100, 400, 700); + } + + private void OnEnable() + { + // ReorderableList 초기화 + gameObjectsList = new ReorderableList(gameObjects, typeof(GameObject), true, true, true, true); + gameObjectsList.drawHeaderCallback = (Rect rect) => + { + EditorGUI.LabelField(rect, "ì¶”ê°€ëœ ê²Œìž„ì˜¤ë¸Œì íЏ 목ë¡"); + }; + gameObjectsList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => + { + gameObjects[index] = (GameObject)EditorGUI.ObjectField( + new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), + gameObjects[index], typeof(GameObject), true); + }; + } + + void OnGUI() + { + GUILayout.Label("ì•„ëž˜ì— ê²Œìž„ì˜¤ë¸Œì íŠ¸ë“¤ì„ ë„£ì–´ì£¼ì„¸ìš”", EditorStyles.boldLabel); + GUILayout.Label("ì†í•˜ëŠ” ë¨¸í‹°ë¦¬ì–¼ì˜ \"림ë¼ì´íЏ\" ê°’ì´ ì¼ê´„ 수정ë©ë‹ˆë‹¤.", EditorStyles.helpBox); + + // 드래그 앤 드롭 구역 ìƒì„± + GUILayout.Space(10); + EditorGUILayout.HelpBox("드래그 앤 드롭으로 게임 오브ì íŠ¸ë¥¼ 추가하세요", MessageType.Info); + Rect dropArea = GUILayoutUtility.GetRect(0, 50, GUILayout.ExpandWidth(true)); + GUI.Box(dropArea, "ì—¬ê¸°ì— ë“œëž˜ê·¸í•˜ì„¸ìš”", EditorStyles.helpBox); + HandleDragAndDrop(dropArea); + + // ë“œëž˜ê·¸ëœ ê²Œìž„ 오브ì íЏ 리스트 표시 + GUILayout.Label("ì¶”ê°€ëœ ê²Œìž„ì˜¤ë¸Œì íЏ:", EditorStyles.boldLabel); + foreach (var go in gameObjects) + { + EditorGUILayout.ObjectField(go, typeof(GameObject), true); + } + GUILayout.Space(10); + + useRim = EditorGUILayout.Toggle("림ë¼ì´íЏ 활성화", useRim); + + if (useRim) + { + rimColor = EditorGUILayout.ColorField("색", rimColor); + rimColorAlpha = EditorGUILayout.Slider("투명ë„", rimColorAlpha, 0, 1f); + rimMainStrength = EditorGUILayout.Slider("ë©”ì¸ ì»¬ëŸ¬ì˜ ê°•ë„", rimMainStrength, 0, 1f); + rimEnableLighting = EditorGUILayout.Slider("ë¼ì´íŒ…ì„ ì ìš©", rimEnableLighting, 0, 1f); + rimShadowMask = EditorGUILayout.Slider("ê·¸ë¦¼ìž ì†ì—서 무효화", rimShadowMask, 0, 1f); + rimBackfaceMask = EditorGUILayout.Toggle("후면ì—서 무효화", rimBackfaceMask); + rimApplyTransparency = EditorGUILayout.Toggle("íˆ¬ëª…ë„ ì ìš©", rimApplyTransparency); + rimBlendMode = (RimBlendMode)EditorGUILayout.EnumPopup("합성 모드", rimBlendMode); + GUILayout.Space(5); + rimDirStrength = EditorGUILayout.Slider("ë¼ì´íЏ ë°©í–¥ì˜ ì˜í–¥ë„", rimDirStrength, 0, 1f); + rimBorder = EditorGUILayout.Slider("범위", rimBorder, 0, 1f); + rimBlur = EditorGUILayout.Slider("í리게", rimBlur, 0, 1f); + rimNormalStrength = EditorGUILayout.Slider("노멀 ë§µ ê°•ë„", rimNormalStrength, 0, 1f); + rimFresnelPower = EditorGUILayout.Slider("림 ë¼ì´íŠ¸ì˜ ë²Œê¸ˆ", rimFresnelPower, 0, 50f); + rimVRParallaxStrength = EditorGUILayout.Slider("VR Parallax Strength", rimVRParallaxStrength, 0, 1f); + + } + + GUILayout.Space(10); + + // ì ìš© 버튼 + if (GUILayout.Button("림ë¼ì´íЏ ì „ë¶€ 수정하기")) + { + ModifyMaterials(); + gameObjects.Clear(); + } + } + + // 드래그 앤 드롭 처리 + //void HandleDragAndDrop(Rect dropArea) + //{ + // Event evt = Event.current; + + // switch (evt.type) + // { + // case EventType.DragUpdated: + // case EventType.DragPerform: + // if (!dropArea.Contains(evt.mousePosition)) + // return; + + // DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + + // if (evt.type == EventType.DragPerform) + // { + // DragAndDrop.AcceptDrag(); + + // foreach (Object draggedObject in DragAndDrop.objectReferences) + // { + // if (draggedObject is GameObject) + // { + // gameObjects.Add((GameObject)draggedObject); // 게임 오브ì íЏ 추가 + // } + // } + + // evt.Use(); + // } + // break; + // } + //} + void HandleDragAndDrop(Rect dropArea) + { + Event evt = Event.current; + if ((evt.type == EventType.DragUpdated || evt.type == EventType.DragPerform) && dropArea.Contains(evt.mousePosition)) + { + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + if (evt.type == EventType.DragPerform) + { + DragAndDrop.AcceptDrag(); + foreach (Object draggedObject in DragAndDrop.objectReferences) + { + if (draggedObject is GameObject) + { + gameObjects.Add((GameObject)draggedObject); + } + } + evt.Use(); + } + } + } + + // Materialì„ ì°¾ì•„ì„œ 파ë¼ë¯¸í„°ë¥¼ 수정하는 함수 + void ModifyMaterials() + { + foreach (GameObject go in gameObjects) + { + if (go == null) continue; + + // 게임 오브ì íŠ¸ì™€ ìžì‹ 오브ì íŠ¸ë“¤ 가져오기 + List renderers = FindAllRenderers(go); + foreach (Renderer renderer in renderers) + { + // ê° ë Œë”러ì—서 사용하는 모든 머티리얼 í™•ì¸ + foreach (Material material in renderer.sharedMaterials) + { + if (material != null && material.shader != null) + { + // 특정 ì‰ì´ë”ì¸ì§€ í™•ì¸ + if (material.shader.name.Contains(shaderNameToCheck)) + { + // 파ë¼ë¯¸í„°ê°€ 존재하는지 확ì¸í•˜ê³  수정 + if (material.HasProperty(param_useRim)) + { + material.SetFloat(param_useRim, useRim ? 1f : 0f); + if (useRim) + { + if (material.HasProperty(param_rimColor)) + material.SetColor(param_rimColor, + new Color(rimColor.r, rimColor.g, rimColor.b, rimColorAlpha)); + if (material.HasProperty(param_rimMainStrength)) + material.SetFloat(param_rimMainStrength, rimMainStrength); + if (material.HasProperty(param_rimEnableLighting)) + material.SetFloat(param_rimEnableLighting, rimEnableLighting); + if (material.HasProperty(param_rimShadowMask)) + material.SetFloat(param_rimShadowMask, rimShadowMask); + if (material.HasProperty(param_rimBackfaceMask)) + material.SetFloat(param_rimBackfaceMask, rimBackfaceMask ? 1f : 0f); + if (material.HasProperty(param_rimApplyTransparency)) + material.SetFloat(param_rimApplyTransparency, rimApplyTransparency ? 1f : 0f); + if (material.HasProperty(param_rimBlendMode)) + material.SetInt(param_rimBlendMode, + rimBlendMode == RimBlendMode.표준 ? 0 : + rimBlendMode == RimBlendMode.가산 ? 1 : + rimBlendMode == RimBlendMode.스í¬ë¦° ? 2 : 3); + + if (material.HasProperty(param_rimDirStrength)) + material.SetFloat(param_rimDirStrength, rimDirStrength); + if (material.HasProperty(param_rimBorder)) + material.SetFloat(param_rimBorder, 1f - rimBorder); + if (material.HasProperty(param_rimBlur)) + material.SetFloat(param_rimBlur, rimBlur); + if (material.HasProperty(param_rimNormalStrength)) + material.SetFloat(param_rimNormalStrength, rimNormalStrength); + if (material.HasProperty(param_rimFresnelPower)) + material.SetFloat(param_rimFresnelPower, rimFresnelPower); + if (material.HasProperty(param_rimVRParallaxStrength)) + material.SetFloat(param_rimVRParallaxStrength, rimVRParallaxStrength); + } + + + Debug.Log($"{go.name}ì— ìžˆëŠ” {material.name} ë¨¸í‹°ë¦¬ì–¼ì´ ìˆ˜ì •ë˜ì—ˆì–´ìš”!"); + } + else + { + Debug.Log($"{go.name}ì˜ {material.name} 머티리얼ì—는 해당 ê°’ì´ ì—†ì—ˆì–´ìš”!"); + } + } + } + } + } + } + + // 변경 사항 저장 + AssetDatabase.SaveAssets(); + } + + // ë¹„í™œì„±í™”ëœ ì˜¤ë¸Œì íŠ¸ê¹Œì§€ í¬í•¨í•œ 모든 ë Œë”러를 찾는 함수 + List FindAllRenderers(GameObject obj) + { + List allRenderers = new List(); + + // ë¹„í™œì„±í™”ëœ ì˜¤ë¸Œì íŠ¸ë„ í¬í•¨í•˜ì—¬ 모든 오브ì íЏ 수집 + Object[] allObjects = EditorUtility.CollectDeepHierarchy(new Object[] { obj }); + + // ê° ì˜¤ë¸Œì íЏì—서 Renderer ì»´í¬ë„ŒíЏ 추출 + foreach (Object o in allObjects) + { + if (o is GameObject) + { + GameObject go = (GameObject)o; + Renderer[] renderers = go.GetComponentsInChildren(true); // true를 사용해 ë¹„í™œì„±í™”ëœ ìžì‹ê¹Œì§€ í¬í•¨ + allRenderers.AddRange(renderers); + } + } + + return allRenderers; + } + } + +} +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/LiltoonRimLightModifier.cs.meta b/Assets/Scripts/Bitd/Scripts/LiltoonRimLightModifier.cs.meta new file mode 100644 index 000000000..65b937088 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/LiltoonRimLightModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cc0f2dcf5794b5b4281923adcf1a8e9d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/LiltoonShadowAdder.cs b/Assets/Scripts/Bitd/Scripts/LiltoonShadowAdder.cs new file mode 100644 index 000000000..1d343c81e --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/LiltoonShadowAdder.cs @@ -0,0 +1,142 @@ +#if UNITY_EDITOR +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; + +namespace Bitd +{ + public class LiltoonShadowAdder : EditorWindow + { + private List gameObjects = new List(); // µå·¡±× ¾Ø µå·ÓÀ¸·Î ¹ÞÀº GameObject ¸ñ·Ï + private string shaderNameToCheck = "lilToon"; // È®ÀÎÇÒ ½¦ÀÌ´õ À̸§ + private string parameterNameToCheck = "_ShadowReceive"; // È®ÀÎÇÒ ÆÄ¶ó¹ÌÅÍ À̸§ + [Range(0, 1f)] private float parameterValue = 1f; + + [MenuItem("Bitd/(¸±Å÷)±×¸²ÀÚ »ý¼º±â", false, 102)] + public static void ShowWindow() + { + GetWindow("±×¸²ÀÚ »ý¼º±â"); + } + + void OnGUI() + { + GUILayout.Label("¾Æ·¡¿¡ °ÔÀÓ¿ÀºêÁ§Æ®µéÀ» ³Ö¾îÁÖ¼¼¿ä", EditorStyles.boldLabel); + GUILayout.Label("¼ÓÇÏ´Â ¸ÓƼ¸®¾óÀÇ \"±×¸²ÀÚ¸¦ ¹Þ´Â\" °ªÀÌ Àϰý ¼öÁ¤µË´Ï´Ù.", EditorStyles.helpBox); + + // µå·¡±× ¾Ø µå·Ó ±¸¿ª »ý¼º + GUILayout.Space(10); + GUILayout.Label("¼öÁ¤ÇÒ °ÔÀÓ¿ÀºêÁ§Æ®µé:", EditorStyles.helpBox); + Rect dropArea = GUILayoutUtility.GetRect(0, 50, GUILayout.ExpandWidth(true)); + HandleDragAndDrop(dropArea); + + // µå·¡±×µÈ °ÔÀÓ ¿ÀºêÁ§Æ® ¸®½ºÆ® Ç¥½Ã + GUILayout.Label("Ãß°¡µÈ °ÔÀÓ¿ÀºêÁ§Æ®:", EditorStyles.boldLabel); + foreach (var go in gameObjects) + { + EditorGUILayout.ObjectField(go, typeof(GameObject), true); + } + GUILayout.Space(5); + // Àû¿ë ¹öư + if (GUILayout.Button("±×¸²ÀÚ¸¦ ¹Þ´Â = 1·Î ¸¸µé±â")) + { + ModifyMaterials(); + gameObjects.Clear(); + } + } + + // µå·¡±× ¾Ø µå·Ó ó¸® + void HandleDragAndDrop(Rect dropArea) + { + Event evt = Event.current; + + switch (evt.type) + { + case EventType.DragUpdated: + case EventType.DragPerform: + if (!dropArea.Contains(evt.mousePosition)) + return; + + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + + if (evt.type == EventType.DragPerform) + { + DragAndDrop.AcceptDrag(); + + foreach (Object draggedObject in DragAndDrop.objectReferences) + { + if (draggedObject is GameObject) + { + gameObjects.Add((GameObject)draggedObject); // °ÔÀÓ ¿ÀºêÁ§Æ® Ãß°¡ + } + } + + evt.Use(); + } + break; + } + } + + // MaterialÀ» ã¾Æ¼­ ÆÄ¶ó¹ÌÅ͸¦ ¼öÁ¤ÇÏ´Â ÇÔ¼ö + void ModifyMaterials() + { + foreach (GameObject go in gameObjects) + { + if (go == null) continue; + + // °ÔÀÓ ¿ÀºêÁ§Æ®¿Í ÀÚ½Ä ¿ÀºêÁ§Æ®µé °¡Á®¿À±â + List renderers = FindAllRenderers(go); + foreach (Renderer renderer in renderers) + { + // °¢ ·»´õ·¯¿¡¼­ »ç¿ëÇÏ´Â ¸ðµç ¸ÓƼ¸®¾ó È®ÀÎ + foreach (Material material in renderer.sharedMaterials) + { + if (material != null && material.shader != null) + { + // ƯÁ¤ ½¦ÀÌ´õÀÎÁö È®ÀÎ + if (material.shader.name.Contains(shaderNameToCheck)) + { + // ÆÄ¶ó¹ÌÅͰ¡ Á¸ÀçÇÏ´ÂÁö È®ÀÎÇÏ°í ¼öÁ¤ + if (material.HasProperty(parameterNameToCheck)) + { + material.SetFloat(parameterNameToCheck, parameterValue); + Debug.Log($"{go.name}¿¡ ÀÖ´Â {material.name} ¸ÓƼ¸®¾óÀÌ ¼öÁ¤µÇ¾ú¾î¿ä!"); + } + else + { + Debug.Log($"{go.name}ÀÇ {material.name} ¸ÓƼ¸®¾ó¿¡´Â ÇØ´ç °ªÀÌ ¾ø¾ú¾î¿ä!"); + } + } + } + } + } + } + + // º¯°æ »çÇ× ÀúÀå + AssetDatabase.SaveAssets(); + } + + // ºñȰ¼ºÈ­µÈ ¿ÀºêÁ§Æ®±îÁö Æ÷ÇÔÇÑ ¸ðµç ·»´õ·¯¸¦ ã´Â ÇÔ¼ö + List FindAllRenderers(GameObject obj) + { + List allRenderers = new List(); + + // ºñȰ¼ºÈ­µÈ ¿ÀºêÁ§Æ®µµ Æ÷ÇÔÇÏ¿© ¸ðµç ¿ÀºêÁ§Æ® ¼öÁý + Object[] allObjects = EditorUtility.CollectDeepHierarchy(new Object[] { obj }); + + // °¢ ¿ÀºêÁ§Æ®¿¡¼­ Renderer ÄÄÆ÷³ÍÆ® ÃßÃâ + foreach (Object o in allObjects) + { + if (o is GameObject) + { + GameObject go = (GameObject)o; + Renderer[] renderers = go.GetComponentsInChildren(true); // true¸¦ »ç¿ëÇØ ºñȰ¼ºÈ­µÈ ÀڽıîÁö Æ÷ÇÔ + allRenderers.AddRange(renderers); + } + } + + return allRenderers; + } + } + +} +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/LiltoonShadowAdder.cs.meta b/Assets/Scripts/Bitd/Scripts/LiltoonShadowAdder.cs.meta new file mode 100644 index 000000000..ff718ed66 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/LiltoonShadowAdder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8d556e6ad11eaac44a8177fb35848fac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/LiltoonShadowModifier.cs b/Assets/Scripts/Bitd/Scripts/LiltoonShadowModifier.cs new file mode 100644 index 000000000..61cf11288 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/LiltoonShadowModifier.cs @@ -0,0 +1,287 @@ +#if UNITY_EDITOR +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using System.Collections.Generic; + +namespace Bitd +{ + public class LiltoonShadowModifier : EditorWindow + { + private List gameObjects = new List(); // 드래그 앤 드롭으로 ë°›ì€ GameObject ëª©ë¡ + private ReorderableList gameObjectsList; + + private string shaderNameToCheck = "lilToon"; // 확ì¸í•  ì‰ì´ë” ì´ë¦„ + + private string param_useShadow = "_UseShadow"; + private string param_shadowStrength = "_ShadowStrength"; + + private bool useShadow = true; // 토글로 설정할 bool ê°’ + private float shadowStrength = 1f; + + private string param_shadowColor = "_ShadowColor"; + private string param_shadowBorder = "_ShadowBorder"; + private string param_shadowBlur = "_ShadowBlur"; + private string param_shadowNormalStrength = "_ShadowNormalStrength"; + private string param_shadowReceive = "_ShadowReceive"; + + private Color shadowColor = Color.white; + private float shadowBorder = 0.5f; + private float shadowBlur = 0.0002f; + private float shadowNormalStrength = 0f; + private float shadowReceive = 0f; + + private string param_shadow2ndColor = "_Shadow2ndColor"; + private string param_shadow2ndBorder = "_Shadow2ndBorder"; + private string param_shadow2ndBlur = "_Shadow2ndBlur"; + private string param_shadow2ndNormalStrength = "_Shadow2ndNormalStrength"; + private string param_shadow2ndReceive = "_Shadow2ndReceive"; + + private Color shadow2ndColor = Color.white; + private float shadow2ndColorAlpha = 1f; + private float shadow2ndBorder = 0.15f; + private float shadow2ndBlur = 0.1f; + private float shadow2ndNormalStrength = 0f; + private float shadow2ndReceive = 0f; + + private string param_shadowBorderColor = "_ShadowBorderColor"; + private string param_shadowBorderRange = "_ShadowBorderRange"; + private string param_shadowMainStrength = "_ShadowMainStrength"; + private string param_shadowEnvStrength = "_ShadowEnvStrength"; + + private Color shadowBorderColor = Color.black; + private float shadowBorderRange = 0.003f; + private float shadowMainStrength = 0.5f; + private float shadowEnvStrength = 0f; + + [MenuItem("Bitd/(릴툰)ê·¸ë¦¼ìž ìˆ˜ì •ê¸°", false, 103)] + public static void ShowWindow() + { + LiltoonShadowModifier window = GetWindow("ê·¸ë¦¼ìž ìˆ˜ì •ê¸°"); + window.position = new Rect(100, 100, 400, 700); + } + private void OnEnable() + { + // ReorderableList 초기화 + gameObjectsList = new ReorderableList(gameObjects, typeof(GameObject), true, true, true, true); + gameObjectsList.drawHeaderCallback = (Rect rect) => + { + EditorGUI.LabelField(rect, "ì¶”ê°€ëœ ê²Œìž„ì˜¤ë¸Œì íЏ 목ë¡"); + }; + gameObjectsList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => + { + gameObjects[index] = (GameObject)EditorGUI.ObjectField( + new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), + gameObjects[index], typeof(GameObject), true); + }; + } + void OnGUI() + { + GUILayout.Label("ì•„ëž˜ì— ê²Œìž„ì˜¤ë¸Œì íŠ¸ë“¤ì„ ë„£ì–´ì£¼ì„¸ìš”", EditorStyles.boldLabel); + GUILayout.Label("ì†í•˜ëŠ” ë¨¸í‹°ë¦¬ì–¼ì˜ \"그림ìž\" ê°’ì´ ì¼ê´„ 수정ë©ë‹ˆë‹¤.", EditorStyles.helpBox); + + // 드래그 앤 드롭 구역 ìƒì„± + GUILayout.Space(10); + EditorGUILayout.HelpBox("드래그 앤 드롭으로 게임 오브ì íŠ¸ë¥¼ 추가하세요", MessageType.Info); + Rect dropArea = GUILayoutUtility.GetRect(0, 50, GUILayout.ExpandWidth(true)); + GUI.Box(dropArea, "ì—¬ê¸°ì— ë“œëž˜ê·¸í•˜ì„¸ìš”", EditorStyles.helpBox); + HandleDragAndDrop(dropArea); + + // ë“œëž˜ê·¸ëœ ê²Œìž„ 오브ì íЏ 리스트 표시 + GUILayout.Label("ì¶”ê°€ëœ ê²Œìž„ì˜¤ë¸Œì íЏ:", EditorStyles.boldLabel); + foreach (var go in gameObjects) + { + EditorGUILayout.ObjectField(go, typeof(GameObject), true); + } + GUILayout.Space(10); + + useShadow = EditorGUILayout.Toggle("ê·¸ë¦¼ìž ë°›ê¸° 활성화", useShadow); + + if (useShadow) + { + shadowStrength = EditorGUILayout.Slider("ê·¸ë¦¼ìž ê°•ë„", shadowStrength, 0, 1f); + GUILayout.Space(5); + shadowColor = EditorGUILayout.ColorField("ê·¸ë¦¼ìž ìƒ‰ 1", shadowColor); + shadowBorder = EditorGUILayout.Slider("범위", shadowBorder, 0, 1f); + shadowBlur = EditorGUILayout.Slider("í리게", shadowBlur, 0, 1f); + shadowNormalStrength = EditorGUILayout.Slider("노멀 ë§µ ê°•ë„", shadowNormalStrength, 0, 1f); + shadowReceive = EditorGUILayout.Slider("그림ìžë¥¼ë°›ëŠ”", shadowReceive, 0, 1f); + GUILayout.Space(5); + shadow2ndColor = EditorGUILayout.ColorField("ê·¸ë¦¼ìž ìƒ‰ 2", shadow2ndColor); + shadow2ndColorAlpha = EditorGUILayout.Slider("투명ë„", shadow2ndColorAlpha, 0, 1f); + shadow2ndBorder = EditorGUILayout.Slider("범위", shadow2ndBorder, 0, 1f); + shadow2ndBlur = EditorGUILayout.Slider("í리게", shadow2ndBlur, 0, 1f); + shadow2ndNormalStrength = EditorGUILayout.Slider("노멀 ë§µ ê°•ë„", shadow2ndNormalStrength, 0, 1f); + shadow2ndReceive = EditorGUILayout.Slider("그림ìžë¥¼ë°›ëŠ”", shadow2ndReceive, 0, 1f); + GUILayout.Space(5); + shadowBorderColor = EditorGUILayout.ColorField("ê²½ê³„ì˜ ìƒ‰", shadowBorderColor); + shadowBorderRange = EditorGUILayout.Slider("ê²½ê³„ì˜ í­", shadowBorderRange, 0, 1f); + shadowMainStrength = EditorGUILayout.Slider("콘트ë¼ìŠ¤íŠ¸", shadowMainStrength, 0, 1f); + shadowEnvStrength = EditorGUILayout.Slider("ê·¸ë¦¼ìž ìƒ‰ì— í™˜ê²½ ê´‘ì˜ ì˜í–¥", shadowEnvStrength, 0, 1f); + } + + GUILayout.Space(10); + + // ì ìš© 버튼 + if (GUILayout.Button("ê·¸ë¦¼ìž ì „ë¶€ 수정하기")) + { + ModifyMaterials(); + gameObjects.Clear(); + } + } + + // 드래그 앤 드롭 처리 + //void HandleDragAndDrop(Rect dropArea) + //{ + // Event evt = Event.current; + + // switch (evt.type) + // { + // case EventType.DragUpdated: + // case EventType.DragPerform: + // if (!dropArea.Contains(evt.mousePosition)) + // return; + + // DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + + // if (evt.type == EventType.DragPerform) + // { + // DragAndDrop.AcceptDrag(); + + // foreach (Object draggedObject in DragAndDrop.objectReferences) + // { + // if (draggedObject is GameObject) + // { + // gameObjects.Add((GameObject)draggedObject); // 게임 오브ì íЏ 추가 + // } + // } + + // evt.Use(); + // } + // break; + // } + //} + void HandleDragAndDrop(Rect dropArea) + { + Event evt = Event.current; + if ((evt.type == EventType.DragUpdated || evt.type == EventType.DragPerform) && dropArea.Contains(evt.mousePosition)) + { + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + if (evt.type == EventType.DragPerform) + { + DragAndDrop.AcceptDrag(); + foreach (Object draggedObject in DragAndDrop.objectReferences) + { + if (draggedObject is GameObject) + { + gameObjects.Add((GameObject)draggedObject); + } + } + evt.Use(); + } + } + } + + // Materialì„ ì°¾ì•„ì„œ 파ë¼ë¯¸í„°ë¥¼ 수정하는 함수 + void ModifyMaterials() + { + foreach (GameObject go in gameObjects) + { + if (go == null) continue; + + // 게임 오브ì íŠ¸ì™€ ìžì‹ 오브ì íŠ¸ë“¤ 가져오기 + List renderers = FindAllRenderers(go); + foreach (Renderer renderer in renderers) + { + // ê° ë Œë”러ì—서 사용하는 모든 머티리얼 í™•ì¸ + foreach (Material material in renderer.sharedMaterials) + { + if (material != null && material.shader != null) + { + // 특정 ì‰ì´ë”ì¸ì§€ í™•ì¸ + if (material.shader.name.Contains(shaderNameToCheck)) + { + // 파ë¼ë¯¸í„°ê°€ 존재하는지 확ì¸í•˜ê³  수정 + if (material.HasProperty(param_useShadow)) + { + material.SetFloat(param_useShadow, useShadow ? 1f : 0f); + if (useShadow) + { + if (material.HasProperty(param_shadowStrength)) + material.SetFloat(param_shadowStrength, shadowStrength); + + if (material.HasProperty(param_shadowColor)) + material.SetColor(param_shadowColor, shadowColor); + if (material.HasProperty(param_shadowBorder)) + material.SetFloat(param_shadowBorder, shadowBorder); + if (material.HasProperty(param_shadowBlur)) + material.SetFloat(param_shadowBlur, shadowBlur); + if (material.HasProperty(param_shadowNormalStrength)) + material.SetFloat(param_shadowNormalStrength, shadowNormalStrength); + if (material.HasProperty(param_shadowReceive)) + material.SetFloat(param_shadowReceive, shadowReceive); + + if (material.HasProperty(param_shadow2ndColor)) + material.SetColor(param_shadow2ndColor, + new Color(shadow2ndColor.r, shadow2ndColor.g, shadow2ndColor.b, shadow2ndColorAlpha)); + if (material.HasProperty(param_shadow2ndBorder)) + material.SetFloat(param_shadow2ndBorder, shadow2ndBorder); + if (material.HasProperty(param_shadow2ndBlur)) + material.SetFloat(param_shadow2ndBlur, shadow2ndBlur); + if (material.HasProperty(param_shadow2ndNormalStrength)) + material.SetFloat(param_shadow2ndNormalStrength, shadow2ndNormalStrength); + if (material.HasProperty(param_shadow2ndReceive)) + material.SetFloat(param_shadow2ndReceive, shadow2ndReceive); + + if (material.HasProperty(param_shadowBorderColor)) + material.SetColor(param_shadowBorderColor, shadowBorderColor); + if (material.HasProperty(param_shadowBorderRange)) + material.SetFloat(param_shadowBorderRange, shadowBorderRange); + if (material.HasProperty(param_shadowMainStrength)) + material.SetFloat(param_shadowMainStrength, shadowMainStrength); + if (material.HasProperty(param_shadowEnvStrength)) + material.SetFloat(param_shadowEnvStrength, shadowEnvStrength); + } + + + Debug.Log($"{go.name}ì— ìžˆëŠ” {material.name} ë¨¸í‹°ë¦¬ì–¼ì´ ìˆ˜ì •ë˜ì—ˆì–´ìš”!"); + } + else + { + Debug.Log($"{go.name}ì˜ {material.name} 머티리얼ì—는 해당 ê°’ì´ ì—†ì—ˆì–´ìš”!"); + } + } + } + } + } + } + + // 변경 사항 저장 + AssetDatabase.SaveAssets(); + } + + // ë¹„í™œì„±í™”ëœ ì˜¤ë¸Œì íŠ¸ê¹Œì§€ í¬í•¨í•œ 모든 ë Œë”러를 찾는 함수 + List FindAllRenderers(GameObject obj) + { + List allRenderers = new List(); + + // ë¹„í™œì„±í™”ëœ ì˜¤ë¸Œì íŠ¸ë„ í¬í•¨í•˜ì—¬ 모든 오브ì íЏ 수집 + Object[] allObjects = EditorUtility.CollectDeepHierarchy(new Object[] { obj }); + + // ê° ì˜¤ë¸Œì íЏì—서 Renderer ì»´í¬ë„ŒíЏ 추출 + foreach (Object o in allObjects) + { + if (o is GameObject) + { + GameObject go = (GameObject)o; + Renderer[] renderers = go.GetComponentsInChildren(true); // true를 사용해 ë¹„í™œì„±í™”ëœ ìžì‹ê¹Œì§€ í¬í•¨ + allRenderers.AddRange(renderers); + } + } + + return allRenderers; + } + } + +} +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/LiltoonShadowModifier.cs.meta b/Assets/Scripts/Bitd/Scripts/LiltoonShadowModifier.cs.meta new file mode 100644 index 000000000..bccf47d11 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/LiltoonShadowModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 36576f34a2f43194b9907e84631d4089 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/LiltoonStencilPassSetter.cs b/Assets/Scripts/Bitd/Scripts/LiltoonStencilPassSetter.cs new file mode 100644 index 000000000..7ee53073d --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/LiltoonStencilPassSetter.cs @@ -0,0 +1,143 @@ +#if UNITY_EDITOR +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; + +namespace Bitd +{ + public class LiltoonStencilPassSetter : EditorWindow + { + private List gameObjects = new List(); // 드래그 앤 드롭으로 ë°›ì€ GameObject ëª©ë¡ + private string shaderNameToCheck = "lilToon"; // 확ì¸í•  ì‰ì´ë” ì´ë¦„ + private string parameterNameToCheck = "_StencilPass"; // 확ì¸í•  파ë¼ë¯¸í„° ì´ë¦„ + private int parameterValue = 2; // = Replace + + [MenuItem("Bitd/(릴툰)스탠실 Replace 설정기", false, 105)] + public static void ShowWindow() + { + GetWindow("Replace 설정"); + } + + void OnGUI() + { + GUILayout.Label("ì•„ëž˜ì— ê²Œìž„ì˜¤ë¸Œì íŠ¸ë“¤ì„ ë„£ì–´ì£¼ì„¸ìš”", EditorStyles.boldLabel); + GUILayout.Label("ì†í•˜ëŠ” ë¨¸í‹°ë¦¬ì–¼ì˜ \"Stencil Pass\" ê°’ì´ Replace로 ì¼ê´„ 수정ë©ë‹ˆë‹¤.", EditorStyles.helpBox); + + // 드래그 앤 드롭 구역 ìƒì„± + GUILayout.Space(10); + GUILayout.Label("수정할 게임오브ì íŠ¸ë“¤:", EditorStyles.helpBox); + Rect dropArea = GUILayoutUtility.GetRect(0, 50, GUILayout.ExpandWidth(true)); + HandleDragAndDrop(dropArea); + + // ë“œëž˜ê·¸ëœ ê²Œìž„ 오브ì íЏ 리스트 표시 + GUILayout.Label("ì¶”ê°€ëœ ê²Œìž„ì˜¤ë¸Œì íЏ:", EditorStyles.boldLabel); + foreach (var go in gameObjects) + { + EditorGUILayout.ObjectField(go, typeof(GameObject), true); + } + GUILayout.Space(5); + // ì ìš© 버튼 + if (GUILayout.Button("Replace로 세팅하기")) + { + ModifyMaterials(); + gameObjects.Clear(); + } + } + + // 드래그 앤 드롭 처리 + void HandleDragAndDrop(Rect dropArea) + { + Event evt = Event.current; + + switch (evt.type) + { + case EventType.DragUpdated: + case EventType.DragPerform: + if (!dropArea.Contains(evt.mousePosition)) + return; + + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + + if (evt.type == EventType.DragPerform) + { + DragAndDrop.AcceptDrag(); + + foreach (Object draggedObject in DragAndDrop.objectReferences) + { + if (draggedObject is GameObject) + { + gameObjects.Add((GameObject)draggedObject); // 게임 오브ì íЏ 추가 + } + } + + evt.Use(); + } + break; + } + } + + // Materialì„ ì°¾ì•„ì„œ 파ë¼ë¯¸í„°ë¥¼ 수정하는 함수 + void ModifyMaterials() + { + foreach (GameObject go in gameObjects) + { + if (go == null) continue; + + // 게임 오브ì íŠ¸ì™€ ìžì‹ 오브ì íŠ¸ë“¤ 가져오기 + List renderers = FindAllRenderers(go); + foreach (Renderer renderer in renderers) + { + // ê° ë Œë”러ì—서 사용하는 모든 머티리얼 í™•ì¸ + foreach (Material material in renderer.sharedMaterials) + { + if (material != null && material.shader != null) + { + // 특정 ì‰ì´ë”ì¸ì§€ í™•ì¸ + if (material.shader.name.Contains(shaderNameToCheck)) + { + // 파ë¼ë¯¸í„°ê°€ 존재하는지 확ì¸í•˜ê³  수정 + if (material.HasProperty(parameterNameToCheck)) + { + material.SetInt(parameterNameToCheck, parameterValue); + Debug.Log($"{go.name}ì— ìžˆëŠ” {material.name} ë¨¸í‹°ë¦¬ì–¼ì´ ìˆ˜ì •ë˜ì—ˆì–´ìš”!"); + } + else + { + Debug.Log($"{go.name}ì˜ {material.name} 머티리얼ì—는 해당 ê°’ì´ ì—†ì—ˆì–´ìš”!"); + } + } + } + } + } + } + + // 변경 사항 저장 + AssetDatabase.SaveAssets(); + } + + // ë¹„í™œì„±í™”ëœ ì˜¤ë¸Œì íŠ¸ê¹Œì§€ í¬í•¨í•œ 모든 ë Œë”러를 찾는 함수 + List FindAllRenderers(GameObject obj) + { + List allRenderers = new List(); + + // ë¹„í™œì„±í™”ëœ ì˜¤ë¸Œì íŠ¸ë„ í¬í•¨í•˜ì—¬ 모든 오브ì íЏ 수집 + Object[] allObjects = EditorUtility.CollectDeepHierarchy(new Object[] { obj }); + + // ê° ì˜¤ë¸Œì íЏì—서 Renderer ì»´í¬ë„ŒíЏ 추출 + foreach (Object o in allObjects) + { + if (o is GameObject) + { + GameObject go = (GameObject)o; + Renderer[] renderers = go.GetComponentsInChildren(true); // true를 사용해 ë¹„í™œì„±í™”ëœ ìžì‹ê¹Œì§€ í¬í•¨ + allRenderers.AddRange(renderers); + } + } + + return allRenderers; + } + } + +} + +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/LiltoonStencilPassSetter.cs.meta b/Assets/Scripts/Bitd/Scripts/LiltoonStencilPassSetter.cs.meta new file mode 100644 index 000000000..e37e8609b --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/LiltoonStencilPassSetter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 954a85dc30338b442aecf5c6005c71ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/MatsReplacer.cs b/Assets/Scripts/Bitd/Scripts/MatsReplacer.cs new file mode 100644 index 000000000..0f56ffc7b --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/MatsReplacer.cs @@ -0,0 +1,274 @@ +#if UNITY_EDITOR + +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace Bitd +{ + public struct sRendererInfo + { + public Renderer RendererRef; // Renderer 참조 + public int MaterialIndex; // Materials ë°°ì—´ì—ì„œì˜ ì¸ë±ìФ + + // ìƒì„±ìž ì •ì˜ (편리하게 초기화할 수 있ë„ë¡) + public sRendererInfo(Renderer rendererRef, int materialIndex) + { + MaterialIndex = materialIndex; + RendererRef = rendererRef; + } + } + + public class MatsReplacerWindow : EditorWindow + { + private GameObject targetPrefab; + private GameObject previousTargetPrefab; + private List uniqueMaterials; + private List> uniqueRenderers; + private List materialUsage; + private List newMaterials; + private List previousNewMaterials; + private Dictionary uniqueMaterialSetting; + private Dictionary> materialGroupWithInfo; + private bool applyClicked = false; + private int undoGroup = 0; + + [MenuItem("Bitd/(ëš)머티리얼 ì¸ì‹ê¸°", false, 252)] + public static void ShowWindow() + { + var window = GetWindow("Mats Replacer"); + window.minSize = new Vector2(600, 300); + } + + void OnGUI() + { + GUILayout.Label("ë¨¸í‹°ë¦¬ì–¼ì„ ìž¬ë°°ì¹˜í•©ë‹ˆë‹¤", EditorStyles.boldLabel); + + targetPrefab = (GameObject)EditorGUILayout.ObjectField("타겟 부모 오브ì íЏ", targetPrefab, typeof(GameObject), true); + + // targetPrefabì´ ë³€ê²½ë˜ì—ˆëŠ”ì§€ í™•ì¸ + if (targetPrefab != previousTargetPrefab) + { + previousTargetPrefab = targetPrefab; + InitializeMaterials(); + } + + if (targetPrefab != null) + { + if (uniqueMaterials == null || uniqueMaterials.Count == 0) + { + InitializeMaterials(); + } + + // UIì—서 ê° ë§ˆí…Œë¦¬ì–¼ 필드 ìƒì„± + for (int i = 0; i < uniqueMaterials.Count; i++) + { + GUILayout.Label($"사용처: {materialUsage[i]}", EditorStyles.label); + EditorGUILayout.BeginHorizontal(); + + // 왼쪽: 기존 머티리얼 (ì½ê¸° ì „ìš©) + GUI.enabled = false; // ì½ê¸° ì „ìš© ìƒíƒœë¡œ 전환 + EditorGUILayout.ObjectField(uniqueMaterials[i], typeof(Material), false, GUILayout.Width(150)); + GUI.enabled = true; // 다시 활성화 + + // 화살표 추가 + GUILayout.Label("→", GUILayout.Width(20), GUILayout.ExpandWidth(false)); + + // 오른쪽: 새 머티리얼 + newMaterials[i] = (Material)EditorGUILayout.ObjectField(newMaterials[i], typeof(Material), true); + + EditorGUILayout.EndHorizontal(); + } + + if (!AreMaterialListsEqual(newMaterials, previousNewMaterials)) + { + PreviewReplaceMaterials(targetPrefab.GetComponentsInChildren()); + previousNewMaterials = new List(newMaterials); + } + + if (GUILayout.Button("Replace Materials")) + { + ReplaceMaterials(targetPrefab.GetComponentsInChildren()); + } + } + else + { + GUILayout.Label("Please select a target prefab."); + } + } + + void InitializeMaterials() + { + if (targetPrefab == null) return; + Debug.Log("InitializeMaterials"); + + if (undoGroup > 0) + { + // Undo 그룹 ë + Undo.CollapseUndoOperations(undoGroup); + undoGroup = 0; + } + + applyClicked = false; + materialGroupWithInfo = new Dictionary>(); + + Renderer[] renderers = targetPrefab.GetComponentsInChildren(); + Dictionary> materialUsageDict = new Dictionary>(); + uniqueMaterialSetting = new Dictionary(); + + foreach (var renderer in renderers) + { + uniqueMaterialSetting.Add(renderer, renderer.sharedMaterials); + + for (int i = 0; i < renderer.sharedMaterials.Length; i++) + { + Material material = renderer.sharedMaterials[i]; + if (material != null) + { + if (!materialUsageDict.ContainsKey(material)) + { + materialUsageDict[material] = new List(); + materialGroupWithInfo[material] = new List(); + } + materialUsageDict[material].Add(renderer.gameObject.name); + materialGroupWithInfo[material].Add(new sRendererInfo(renderer, i)); + } + } + } + + uniqueMaterials = new List(materialUsageDict.Keys); + uniqueRenderers = new List>(); + for (int i = 0; i < uniqueMaterials.Count; i++) + { + uniqueRenderers.Add(new List()); + } + + materialUsage = new List(); + + for (int i = 0; i < uniqueMaterials.Count; i++) + { + materialUsage.Add(string.Join(", ", materialUsageDict[uniqueMaterials[i]])); + } + + newMaterials = new List(uniqueMaterials); + previousNewMaterials = new List(newMaterials); + + // Undo 그룹 시작 + Undo.IncrementCurrentGroup(); + undoGroup = Undo.GetCurrentGroup(); + } + + void ReplaceMaterials(Renderer[] renderers) + { + foreach (var renderer in renderers) + { + // Renderer ì»´í¬ë„ŒíŠ¸ë¥¼ Undo ê¸°ë¡ + Undo.RecordObject(renderer, "Replace Materials"); + // 기존 sharedMaterials ë°°ì—´ 복사 + Material[] materials = uniqueMaterialSetting[renderer].Clone() as Material[]; + if (materials == null) continue; + + for (int i = 0; i < materials.Length; i++) + { + foreach (var materialRef in materialGroupWithInfo.Keys) + { + if (materials[i] == materialRef) + { + int index = uniqueMaterials.IndexOf(materialRef); + if (index >= 0) + { + materials[i] = newMaterials[index]; // 새 마테리얼로 êµì²´ + } + } + } + } + renderer.sharedMaterials = materials; // ìˆ˜ì •ëœ ë§ˆí…Œë¦¬ì–¼ ë°°ì—´ì„ ë‹¤ì‹œ 할당 + } + + if (targetPrefab != null) + { + Undo.RecordObject(targetPrefab, "Replace Materials"); + EditorUtility.SetDirty(targetPrefab); + } + + // Undo 그룹 ë + Undo.CollapseUndoOperations(undoGroup); + + applyClicked = true; + + // ì•Œë¦¼ì°½ì„ ë„ìš´ 후 윈ë„ìš° 닫기 + EditorUtility.DisplayDialog("Mats Replacer", "성공ì ìœ¼ë¡œ 변환ë˜ì—ˆìŠµë‹ˆë‹¤.", "OK"); + Close(); + } + + void PreviewReplaceMaterials(Renderer[] renderers) + { + Debug.Log("PreviewReplaceMaterials"); + + foreach (var renderer in renderers) + { + // Renderer ì»´í¬ë„ŒíŠ¸ë¥¼ Undo ê¸°ë¡ + Undo.RecordObject(renderer, "Replace Materials"); + + // 기존 sharedMaterials ë°°ì—´ 복사 + Material[] materials = uniqueMaterialSetting[renderer].Clone() as Material[]; + if (materials == null) continue; + + for (int i = 0; i < materials.Length; i++) + { + foreach (var materialRef in materialGroupWithInfo.Keys) + { + if (materials[i] == materialRef) + { + int index = uniqueMaterials.IndexOf(materialRef); + if (index >= 0) + { + materials[i] = newMaterials[index]; // 새 마테리얼로 êµì²´ + } + } + } + } + renderer.sharedMaterials = materials; // ìˆ˜ì •ëœ ë§ˆí…Œë¦¬ì–¼ ë°°ì—´ì„ ë‹¤ì‹œ 할당 + } + Undo.RecordObject(targetPrefab, "Replace Materials"); + EditorUtility.SetDirty(targetPrefab); + } + + bool AreMaterialListsEqual(List list1, List list2) + { + if (list1 == null || list2 == null || list1.Count != list2.Count) + { + return false; + } + + for (int i = 0; i < list1.Count; i++) + { + if (list1[i] != list2[i]) + { + return false; + } + } + + return true; + } + + private void OnDisable() + { + if (!applyClicked) + { + foreach (var setting in uniqueMaterialSetting) + { + setting.Key.sharedMaterials = setting.Value; + } + + if (undoGroup > 0) + { + Undo.RevertAllDownToGroup(undoGroup); + } + } + } + } + +} + +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/MatsReplacer.cs.meta b/Assets/Scripts/Bitd/Scripts/MatsReplacer.cs.meta new file mode 100644 index 000000000..21159503a --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/MatsReplacer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5fa869d3a07c9a640b3dc018f1a829c9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/MissingScriptRemover.cs b/Assets/Scripts/Bitd/Scripts/MissingScriptRemover.cs new file mode 100644 index 000000000..b0abd4403 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/MissingScriptRemover.cs @@ -0,0 +1,100 @@ +#if UNITY_EDITOR + +using UnityEngine; +using UnityEditor; +using System.Linq; + +namespace Bitd +{ + public class EditorHelpers : Editor + { + // Remove Missing Scripts 메뉴 항목 유효성 검사 + [MenuItem("GameObject/Bitd/미싱 스í¬ë¦½íЏ 지우개", true, 0)] + private static bool RemoveMissingScripts_OnPrefabs_Validate() + { + return Selection.objects != null && Selection.objects.All(x => x is GameObject); + } + + // Remove Missing Scripts 메뉴 항목 + [MenuItem("GameObject/Bitd/미싱 스í¬ë¦½íЏ 지우개", false, 0)] + private static void RemoveMissingScripts_OnPrefabs() + { + GameObject[] selectedObjects = Selection.gameObjects; + + if (selectedObjects.Length == 0) + { + Debug.LogWarning("ì–´í—ˆ 게임오브ì íЏ 제대로 ì„ íƒí•˜ì§€ 못할까...! ê°ˆ!!!!!!!"); + return; + } + + int totalRemovedCount = 0; + + foreach (var gameObject in selectedObjects) + { + int removedCount = RemoveMissingScripts_OnPrefabs_Recursive(gameObject); + totalRemovedCount += removedCount; + } + + if (totalRemovedCount == 0) + { + Debug.Log("와! 미싱 스í¬ë¦½íŠ¸ê°€ í•˜ë‚˜ë„ ì—†ì—ˆì–´ìš”! 문제는 다른 ê³³ì— ìžˆëŠ” 것 같아요!"); + } + else + { + Debug.Log($"ì „ë¶€ ì‚­ì œ 완료했습니다. ì´ {totalRemovedCount}ê°œì˜ ë¯¸ì‹± 스í¬ë¦½íŠ¸ë¥¼ 제거했습니다."); + } + } + + private static int RemoveMissingScripts_OnPrefabs_Recursive(GameObject obj) + { + // Remove missing scripts from the current object + int removedCount = GameObjectUtility.RemoveMonoBehavioursWithMissingScript(obj); + if (removedCount > 0) + { + Debug.Log($"{obj.name} ì•ˆì— ìžˆëŠ” {removedCount}ê°œì˜ ë¯¸ì‹± 스í¬ë¦½íŠ¸ë¥¼ 삭제했어요!"); + } + + // Recursively scan children + foreach (Transform child in obj.transform) + { + removedCount += RemoveMissingScripts_OnPrefabs_Recursive(child.gameObject); + } + + return removedCount; + } + + // List Missing Scripts 메뉴 항목 유효성 검사 + [MenuItem("GameObject/Bitd/미싱 스í¬ë¦½íЏ 검색", true, 0)] + private static bool ListMissingScripts_OnPrefabs_Validate() + { + return Selection.objects != null && Selection.objects.All(x => x is GameObject); + } + + // List Missing Scripts 메뉴 항목 + [MenuItem("GameObject/Bitd/미싱 스í¬ë¦½íЏ 검색", false, 0)] + private static void ListMissingScripts_OnPrefabs() + { + foreach (var obj in Selection.gameObjects) + { + ListMissingScripts_OnPrefabs_Recursive(obj); + } + } + + private static void ListMissingScripts_OnPrefabs_Recursive(GameObject obj) + { + // List missing scripts on this object + int missingCount = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(obj); + if (missingCount > 0) + { + Debug.Log($"{obj.name} ì•ˆì— ìžˆëŠ” {missingCount}ê°œì˜ ë¯¸ì‹± 스í¬ë¦½íŠ¸ë¥¼ 삭제했어요!"); + } + + // Recursively scan children + foreach (Transform child in obj.transform) + { + ListMissingScripts_OnPrefabs_Recursive(child.gameObject); + } + } + } +} +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/MissingScriptRemover.cs.meta b/Assets/Scripts/Bitd/Scripts/MissingScriptRemover.cs.meta new file mode 100644 index 000000000..d85738e12 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/MissingScriptRemover.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 29e3ef4277ba85146a21fd1b5620a728 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/MultiUnitypackageInstaller.cs b/Assets/Scripts/Bitd/Scripts/MultiUnitypackageInstaller.cs new file mode 100644 index 000000000..560db898c --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/MultiUnitypackageInstaller.cs @@ -0,0 +1,122 @@ +#if UNITY_EDITOR + +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; +using System.IO; + +namespace Bitd +{ + public class MultiUnitypackageInstaller : EditorWindow + { + private string folderPath = ""; + private Queue packageQueue = new Queue(); + private bool isImporting = false; + private float checkInterval = 3f; // ìž„í¬íЏ ìƒíƒœë¥¼ ì²´í¬í•  주기 (ì´ˆ) + private float timer = 0f; + + [MenuItem("Bitd/패키지 ìž„í¬íЏ 개빡ì³", false, 201)] + public static void ShowWindow() + { + GetWindow("뜌....뜌땨..."); + } + + void OnGUI() + { + GUILayout.Label("화나니까 눌러ë‘ê³  쉬ìž", EditorStyles.boldLabel); + + if (GUILayout.Button("í´ë” ì„ íƒ")) + { + folderPath = EditorUtility.OpenFolderPanel("í´ë” ì„ íƒí•˜ê¸°", "", ""); + } + + if (!string.IsNullOrEmpty(folderPath)) + { + GUILayout.Label(folderPath + " í´ë” ì„ íƒë¨"); + } + + if (GUILayout.Button("ìž„í¬íЏ 시작")) + { + StartImporting(folderPath); + } + } + + void StartImporting(string path) + { + if (string.IsNullOrEmpty(path)) return; + + // 모든 í´ë”와 하위 í´ë”ì—서 .unitypackage íŒŒì¼ ì°¾ê¸° + string[] packageFiles = GetAllUnityPackages(path); + + foreach (string packageFile in packageFiles) + { + packageQueue.Enqueue(packageFile); + } + + if (packageQueue.Count > 0) + { + isImporting = true; + EditorApplication.update += ImportNextPackage; + } + } + + // 재귀ì ìœ¼ë¡œ í´ë”와 하위 í´ë”ì˜ .unitypackage 파ì¼ë“¤ì„ 찾는 메서드 + string[] GetAllUnityPackages(string path) + { + // 현재 í´ë” ì•ˆì˜ .unitypackage 파ì¼ë“¤ + List packageFiles = new List(Directory.GetFiles(path, "*.unitypackage")); + + // 하위 í´ë”ë“¤ì„ ê°€ì ¸ì˜´ + string[] subdirectories = Directory.GetDirectories(path); + + // ê° í•˜ìœ„ í´ë”ë„ ìž¬ê·€ì ìœ¼ë¡œ íƒìƒ‰ + foreach (string subdirectory in subdirectories) + { + packageFiles.AddRange(GetAllUnityPackages(subdirectory)); + } + + return packageFiles.ToArray(); + } + + void ImportNextPackage() + { + if (packageQueue.Count == 0) + { + // 모든 패키지 ìž„í¬íЏ 완료 + isImporting = false; + EditorApplication.update -= ImportNextPackage; + Debug.Log("모든 패키지가 ìž„í¬íЏ 완료ë˜ì—ˆìŠµë‹ˆë‹¤."); + return; + } + + string nextPackage = packageQueue.Dequeue(); + AssetDatabase.ImportPackage(nextPackage, false); // ìžë™ìœ¼ë¡œ 패키지 설치, Import ì°½ ì—†ì´ ì§„í–‰ + + // ìž„í¬íЏ ìƒíƒœë¥¼ ì²´í¬í•˜ê¸° 위해 타ì´ë¨¸ 리셋 + timer = checkInterval; + EditorApplication.update -= ImportNextPackage; + EditorApplication.update += CheckImportStatus; + } + + void CheckImportStatus() + { + timer -= Time.deltaTime; + + // ì¼ì • 주기마다 ìœ ë‹ˆí‹°ì˜ ìƒíƒœë¥¼ ì²´í¬ + if (timer <= 0f) + { + timer = checkInterval; + + // 유니티가 ì—ì…‹ì„ ì²˜ë¦¬ 중ì¸ì§€ í™•ì¸ (로딩 ìƒíƒœ) + if (!EditorApplication.isCompiling && !EditorApplication.isUpdating) + { + // ìž„í¬íŠ¸ê°€ 완료ë˜ì—ˆìœ¼ë©´ ë‹¤ìŒ íŒ¨í‚¤ì§€ë¥¼ ìž„í¬íЏ + EditorApplication.update -= CheckImportStatus; + EditorApplication.update += ImportNextPackage; + } + } + } + } +} + +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/MultiUnitypackageInstaller.cs.meta b/Assets/Scripts/Bitd/Scripts/MultiUnitypackageInstaller.cs.meta new file mode 100644 index 000000000..0d3659721 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/MultiUnitypackageInstaller.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e3e376ce4bd65d144b11bb54cbac2f7e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Bitd/Scripts/NilotoonMaterialMatcapSetter.cs b/Assets/Scripts/Bitd/Scripts/NilotoonMaterialMatcapSetter.cs new file mode 100644 index 000000000..8bf8851eb --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/NilotoonMaterialMatcapSetter.cs @@ -0,0 +1,213 @@ +#if UNITY_EDITOR +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; + +namespace Bitd +{ + public struct stMatcapInfo + { + public bool _UseMatCap; + public Texture _MatCapTex; + public Color _MatCapColor; + public Texture _MatCapBlendMask; + public int _MatCapBlendMode; + + public stMatcapInfo(bool _useMatCap) + { + _UseMatCap = _useMatCap; + _MatCapTex = null; + _MatCapColor = Color.white; + _MatCapBlendMask = null; + _MatCapBlendMode = 0; + } + + public stMatcapInfo(bool _useMatCap, Texture _matCapTex, Color _matCapColor + , Texture _matCapBlendMask, int _matCapBlendMode) + { + _UseMatCap = _useMatCap; + _MatCapTex = _matCapTex; + _MatCapColor = _matCapColor; + _MatCapBlendMask = _matCapBlendMask; + _MatCapBlendMode = _matCapBlendMode; + } + } + + public class NiloMaterialMatcapSetter : EditorWindow + { + private List materials = new List(); // 드래그 앤 드롭으로 ë°›ì€ Material ëª©ë¡ + private string pEnableName_Front = "_BaseMapStackingLayer"; // ì›ë³¸ ì†ì„± + private string pEnableName_Back = "Enable"; + private const string targetShaderName = "lilToon"; + + private Vector2 scrollPosObjects; // 오브ì íЏ ëª©ë¡ ìŠ¤í¬ë¡¤ 위치 + + [MenuItem("Bitd/ë‹ë¡œíˆ° 매트캡 ìžë™ ì¸ì‹ê¸°", false, 153)] + public static void ShowWindow() + { + GetWindow("ë‹ë¡œíˆ° 매트캡 ìžë™ ì¸ì‹ê¸°"); + } + + void OnGUI() + { + GUILayout.Label("ì•„ëž˜ì— ë‹ë¡œíˆ° ë¨¸í‹°ë¦¬ì–¼ë“¤ì„ ë„£ì–´ì£¼ì„¸ìš”", EditorStyles.boldLabel); + GUILayout.Label("ì„ íƒí•œ ë‹ë¡œíˆ°ì—서 릴툰 매트캡 ê°’ì„ ì°¾ì•„ ë‹ë¡œíˆ°ì— ìžë™ ë°˜ì˜í•©ë‹ˆë‹¤", EditorStyles.helpBox); + + GUILayout.Space(10); + GUILayout.Label("수정할 머티리얼들:", EditorStyles.helpBox); + Rect dropArea = GUILayoutUtility.GetRect(0, 50, GUILayout.ExpandWidth(true)); + HandleDragAndDrop(dropArea); + + GUILayout.Label("ì¶”ê°€ëœ ë¨¸í‹°ë¦¬ì–¼:", EditorStyles.boldLabel); + scrollPosObjects = EditorGUILayout.BeginScrollView(scrollPosObjects, GUILayout.Height(100)); // 최대 ë†’ì´ ì œí•œ + foreach (var mat in materials) + { + EditorGUILayout.ObjectField(mat, typeof(Material), true); + } + EditorGUILayout.EndScrollView(); + GUILayout.Space(5); + if (GUILayout.Button("ìžë™ 복사 실행")) + { + ProcessMaterials(); + materials.Clear(); + } + } + + void HandleDragAndDrop(Rect dropArea) + { + Event evt = Event.current; + switch (evt.type) + { + case EventType.DragUpdated: + case EventType.DragPerform: + if (!dropArea.Contains(evt.mousePosition)) + return; + + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + + if (evt.type == EventType.DragPerform) + { + DragAndDrop.AcceptDrag(); + foreach (Object draggedObject in DragAndDrop.objectReferences) + { + if (draggedObject is Material mat) + { + materials.Add(mat); + } + } + evt.Use(); + } + break; + } + } + + void ProcessMaterials() + { + Shader lilToonShader = Shader.Find(targetShaderName); + if (lilToonShader == null) + { + Debug.LogError("lilToon Shader를 ì°¾ì„ ìˆ˜ 없습니다. 먼저 프로ì íŠ¸ì— ì¶”ê°€í•´ì£¼ì„¸ìš”."); + return; + } + + foreach (Material originalMaterial in materials) + { + if (originalMaterial == null) continue; + + // ì›ë³¸ 머티리얼 복사 + Material clonedMaterial = Object.Instantiate(originalMaterial); + clonedMaterial.shader = lilToonShader; + + // ì›ë³¸ ë¨¸í‹°ë¦¬ì–¼ì„ ìˆ˜ì •í•˜ëŠ” 코드는 ì´í›„ 사용ìžê°€ 추가할 예정 + + List matcapInfoList = new List(); + + stMatcapInfo newInfo1 = GetMatcapInfoByName(clonedMaterial, "_UseMatCap", true); + stMatcapInfo newInfo2 = GetMatcapInfoByName(clonedMaterial, "_UseMatCap2nd", false); + + if (newInfo1._UseMatCap) matcapInfoList.Add(newInfo1); + if (newInfo2._UseMatCap) matcapInfoList.Add(newInfo2); + + foreach (stMatcapInfo matcapInfo in matcapInfoList) + { + int targetLayerNumber = 0; + for (int i = 1; i <= 10; i++) + { + if (originalMaterial.GetFloat(pEnableName_Front + i.ToString() + pEnableName_Back) < 0.5f) + { + targetLayerNumber = i; + originalMaterial.SetFloat(pEnableName_Front + i.ToString() + pEnableName_Back, 1f); + break; + } + } + + // ê°ì¢… ê°’ 초기화 + originalMaterial.SetVector("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "TexUVCenterPivotScalePos", new Vector4(1, 1, 0, 0)); + originalMaterial.SetVector("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "TexUVScaleOffset", new Vector4(1, 1, 0, 0)); + originalMaterial.SetVector("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "TexUVAnimSpeed", new Vector4(0, 0, 0, 0)); + originalMaterial.SetVector("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "MaskTexChannel", new Vector4(0, 1, 0, 0)); + originalMaterial.SetFloat("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "TexUVRotatedAngle", 0); + originalMaterial.SetFloat("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "TexUVRotateSpeed", 0); + originalMaterial.SetFloat("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "MaskUVIndex", 0); + originalMaterial.SetFloat("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "MaskInvertColor", 0); + originalMaterial.SetFloat("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "TexIgnoreAlpha", 0); + + // 블렌드모드 ì„ íƒ + originalMaterial.SetFloat("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "ColorBlendMode" + , matcapInfo._MatCapBlendMode == 0 ? 0 : // 표준 + matcapInfo._MatCapBlendMode == 1 ? 2 : // 가산 + matcapInfo._MatCapBlendMode == 2 ? 3 : // 스í¬ë¦° + matcapInfo._MatCapBlendMode == 3 ? 4 : 5); // 곱하기 + + // 매트캡 í…ìŠ¤ì³ ë„£ì–´ì£¼ê¸° + originalMaterial.SetTexture("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "Tex" + , matcapInfo._MatCapTex); + + // 매트캡 컬러 넣어주기 + originalMaterial.SetColor("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "TintColor" + , new Color(matcapInfo._MatCapColor.r, matcapInfo._MatCapColor.g, matcapInfo._MatCapColor.b, 1f)); + + // 매트캡 íˆ¬ëª…ë„ ë„£ì–´ì£¼ê¸° + originalMaterial.SetFloat("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "MasterStrength" + , matcapInfo._MatCapColor.a); + + // UV 종류 MatcapUV로 바꿔주기 + originalMaterial.SetFloat("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "TexUVIndex" + , 4); + + // 매트캡 ë§ˆìŠ¤í¬ ë„£ì–´ì£¼ê¸° + originalMaterial.SetTexture("_BaseMapStackingLayer" + targetLayerNumber.ToString() + "MaskTex" + , matcapInfo._MatCapBlendMask); + } + + + + + + + + + + + // í´ë¡  머티리얼 ì‚­ì œ + DestroyImmediate(clonedMaterial); + } + + AssetDatabase.SaveAssets(); + } + + private stMatcapInfo GetMatcapInfoByName(Material mat, string propertyName, bool isFirst) + { + string plusName = string.Empty; + if (!isFirst) plusName = "2nd"; + + if (mat.HasProperty(propertyName) && mat.GetInt(propertyName) == 1) + { + return new stMatcapInfo(true, mat.GetTexture("_MatCap" + plusName + "Tex"), mat.GetColor("_MatCap" + plusName + "Color") + , mat.GetTexture("_MatCap" + plusName + "BlendMask"), mat.GetInt("_MatCap" + plusName + "BlendMode")); + } + return new stMatcapInfo(false); + } + } +} +#endif \ No newline at end of file diff --git a/Assets/Scripts/Bitd/Scripts/NilotoonMaterialMatcapSetter.cs.meta b/Assets/Scripts/Bitd/Scripts/NilotoonMaterialMatcapSetter.cs.meta new file mode 100644 index 000000000..4414d3f74 --- /dev/null +++ b/Assets/Scripts/Bitd/Scripts/NilotoonMaterialMatcapSetter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bbec06221f57ede4e807d21c751edfa8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/BlendShapesRename.meta b/Assets/Scripts/BlendShapesRename.meta new file mode 100644 index 000000000..3d02f8b30 --- /dev/null +++ b/Assets/Scripts/BlendShapesRename.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ef3155ee64b15e6409cfc4be6103a81c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/BlendShapesRename/BlendShapesRename.cs b/Assets/Scripts/BlendShapesRename/BlendShapesRename.cs new file mode 100644 index 000000000..fdd089fa9 --- /dev/null +++ b/Assets/Scripts/BlendShapesRename/BlendShapesRename.cs @@ -0,0 +1,112 @@ +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +public class BlendShapeRenamer : EditorWindow +{ + private SkinnedMeshRenderer targetMeshRenderer; + private Dictionary newNames; + private Vector2 scrollPos; // 스í¬ë¡¤ 위치 저장 변수 + private bool hasChanges = false; + + [MenuItem("Tools/BlendShape Renamer")] + public static void ShowWindow() + { + GetWindow("BlendShape Renamer"); + } + + private void OnGUI() + { + GUILayout.Label("Rename BlendShapes", EditorStyles.boldLabel); + + // ëŒ€ìƒ SkinnedMeshRenderer 오브ì íŠ¸ë¥¼ ì„ íƒí•  수 있는 필드 + targetMeshRenderer = (SkinnedMeshRenderer)EditorGUILayout.ObjectField("Face Object", targetMeshRenderer, typeof(SkinnedMeshRenderer), true); + + if (targetMeshRenderer != null) + { + Mesh mesh = targetMeshRenderer.sharedMesh; + if (mesh != null) + { + // BlendShape ì´ë¦„ì´ ì´ˆê¸°í™”ë˜ì§€ 않았거나 BlendShape 개수가 변한 경우 ì´ë¦„ 초기화 + if (newNames == null || newNames.Count != mesh.blendShapeCount) + { + InitializeNames(mesh); + } + + EditorGUILayout.Space(); + EditorGUILayout.LabelField("BlendShape Names", EditorStyles.boldLabel); + + // 스í¬ë¡¤ 가능 ì˜ì—­ 설정 + scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(300)); // 300ì€ ìŠ¤í¬ë¡¤ ë·°ì˜ ë†’ì´ + + for (int i = 0; i < mesh.blendShapeCount; i++) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(mesh.GetBlendShapeName(i), GUILayout.MaxWidth(200)); + newNames[i] = EditorGUILayout.TextField(newNames[i]); + EditorGUILayout.EndHorizontal(); + } + + EditorGUILayout.EndScrollView(); // 스í¬ë¡¤ ë·° ë + + EditorGUILayout.Space(); + if (GUILayout.Button("Rename")) + { + ApplyRenaming(mesh); + } + + // Undo 버튼 추가 + if (hasChanges && GUILayout.Button("Undo Last Change")) + { + Undo.PerformUndo(); + } + } + else + { + EditorGUILayout.HelpBox("The selected object does not have a valid mesh.", MessageType.Warning); + } + } + else + { + EditorGUILayout.HelpBox("Please assign a SkinnedMeshRenderer object.", MessageType.Info); + } + } + + // BlendShape ì´ë¦„ 초기화 + private void InitializeNames(Mesh mesh) + { + newNames = new Dictionary(); + for (int i = 0; i < mesh.blendShapeCount; i++) + { + newNames[i] = mesh.GetBlendShapeName(i); + } + } + + // ì´ë¦„ ì ìš© ë¡œì§ + private void ApplyRenaming(Mesh mesh) + { + Undo.RecordObject(mesh, "Rename BlendShapes"); + + for (int i = 0; i < mesh.blendShapeCount; i++) + { + string oldName = mesh.GetBlendShapeName(i); + string newName = newNames[i]; + + if (oldName != newName) + { + RenameBlendShape(mesh, i, newName); + } + } + + hasChanges = true; + AssetDatabase.SaveAssets(); + EditorUtility.SetDirty(mesh); + } + + // BlendShape ì´ë¦„ì„ ë³€ê²½í•˜ëŠ” ë¡œì§ (실제 êµ¬í˜„ì€ ë©”ì‹œ ì‹œìŠ¤í…œì— ë”°ë¼ ë‹¤ë¦„) + private void RenameBlendShape(Mesh mesh, int index, string newName) + { + // ë©”ì‹œì˜ BlendShape ì´ë¦„ì„ ì‹¤ì œë¡œ 변경하는 로ì§ì„ 구현할 수 있습니다. + Debug.Log($"Renaming BlendShape {index} from '{mesh.GetBlendShapeName(index)}' to '{newName}'"); + } +} diff --git a/Assets/Scripts/BlendShapesRename/BlendShapesRename.cs.meta b/Assets/Scripts/BlendShapesRename/BlendShapesRename.cs.meta new file mode 100644 index 000000000..51caa2507 --- /dev/null +++ b/Assets/Scripts/BlendShapesRename/BlendShapesRename.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e41104d3b99832b40ac695d5685e4b9f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Camera Composition.meta b/Assets/Scripts/Camera Composition.meta new file mode 100644 index 000000000..81d0afc02 --- /dev/null +++ b/Assets/Scripts/Camera Composition.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e9b5b49ef0a4edd4099c096a54a218e5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Camera Composition/Camera Composition.zip b/Assets/Scripts/Camera Composition/Camera Composition.zip new file mode 100644 index 000000000..9e0f40629 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Camera Composition.zip @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67e4501b4f85c217feeaeaca3509722ebc4534b58949669f11214e8d0438f395 +size 5704148 diff --git a/Assets/Scripts/Camera Composition/Camera Composition.zip.meta b/Assets/Scripts/Camera Composition/Camera Composition.zip.meta new file mode 100644 index 000000000..931f4987d --- /dev/null +++ b/Assets/Scripts/Camera Composition/Camera Composition.zip.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7a76ec1c32272a242936808ac20449ad +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Camera Composition/CameraComposition.pdf b/Assets/Scripts/Camera Composition/CameraComposition.pdf new file mode 100644 index 000000000..46e6eb728 --- /dev/null +++ b/Assets/Scripts/Camera Composition/CameraComposition.pdf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16b0641b54ae143a2e8ce2795efb70721cb504bd5feee78908ac5e992a50ae40 +size 5654553 diff --git a/Assets/Scripts/Camera Composition/CameraComposition.pdf.meta b/Assets/Scripts/Camera Composition/CameraComposition.pdf.meta new file mode 100644 index 000000000..a57d3db49 --- /dev/null +++ b/Assets/Scripts/Camera Composition/CameraComposition.pdf.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 403187bd32b8502488efe4583bc51110 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 202816 + packageName: Camera Composition - Grid Overlay Tool + packageVersion: 1.0.2 + assetPath: Assets/Camera Composition/CameraComposition.pdf + uploadId: 471102 diff --git a/Assets/Scripts/Camera Composition/Changelog.txt b/Assets/Scripts/Camera Composition/Changelog.txt new file mode 100644 index 000000000..b5fd1040b --- /dev/null +++ b/Assets/Scripts/Camera Composition/Changelog.txt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bdb5d180193adc4421cff16151687dac42d3e56808cd3463b7c8ae46c81956f4 +size 960 diff --git a/Assets/Scripts/Camera Composition/Changelog.txt.meta b/Assets/Scripts/Camera Composition/Changelog.txt.meta new file mode 100644 index 000000000..79dc174d3 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Changelog.txt.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 1c03e5c3741df0b408c8e81db15780ef +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 202816 + packageName: Camera Composition - Grid Overlay Tool + packageVersion: 1.0.2 + assetPath: Assets/Camera Composition/Changelog.txt + uploadId: 471102 diff --git a/Assets/Scripts/Camera Composition/README.txt b/Assets/Scripts/Camera Composition/README.txt new file mode 100644 index 000000000..89abbbacd --- /dev/null +++ b/Assets/Scripts/Camera Composition/README.txt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e8df6843bc26057564de1a1a8c21e6b4d4f7678cc023895adb97b0e267d4747 +size 812 diff --git a/Assets/Scripts/Camera Composition/README.txt.meta b/Assets/Scripts/Camera Composition/README.txt.meta new file mode 100644 index 000000000..77029f511 --- /dev/null +++ b/Assets/Scripts/Camera Composition/README.txt.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 583d2b0c7a3fb5146baec6c15b419b8b +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 202816 + packageName: Camera Composition - Grid Overlay Tool + packageVersion: 1.0.2 + assetPath: Assets/Camera Composition/README.txt + uploadId: 471102 diff --git a/Assets/Scripts/Camera Composition/Scripts.meta b/Assets/Scripts/Camera Composition/Scripts.meta new file mode 100644 index 000000000..8e9e090b7 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3a53342f3b4a81240ada88d8ca085116 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Camera Composition/Scripts/CameraComposition.asmdef b/Assets/Scripts/Camera Composition/Scripts/CameraComposition.asmdef new file mode 100644 index 000000000..5da521217 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/CameraComposition.asmdef @@ -0,0 +1,14 @@ +{ + "name": "CameraComposition", + "rootNamespace": "", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/Assets/Scripts/Camera Composition/Scripts/CameraComposition.asmdef.meta b/Assets/Scripts/Camera Composition/Scripts/CameraComposition.asmdef.meta new file mode 100644 index 000000000..1d5a6fa85 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/CameraComposition.asmdef.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: a2f7da84f307c3f4bbb7fed78a3a71b6 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 202816 + packageName: Camera Composition - Grid Overlay Tool + packageVersion: 1.0.2 + assetPath: Assets/Camera Composition/Scripts/CameraComposition.asmdef + uploadId: 471102 diff --git a/Assets/Scripts/Camera Composition/Scripts/CompositionOverlay.cs b/Assets/Scripts/Camera Composition/Scripts/CompositionOverlay.cs new file mode 100644 index 000000000..50a94a485 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/CompositionOverlay.cs @@ -0,0 +1,81 @@ +/* This file is part of the "Camera Composition" editor tool by Jordan Cassady. + * You are only permitted to use this software if purchased and downloaded from + * the Unity Asset Store. You shall not sell, license, transfer, distribute or + * otherwise make this software available to any third party. + */ + + // You are only permitted to use this package if purchased and downloaded + +using UnityEngine; +using UnityEngine.UI; + +namespace JordanCassady +{ + /// + /// Provide access to the composition overlay properties and methods for + /// manipulating the Image component from the editor window. + /// + [RequireComponent(typeof(Image))] + public class CompositionOverlay : MonoBehaviour + { + #region PROPERTIES + public bool IsActive { get { return GetComponent().enabled; } } + public float Opacity { get { return GetComponent().color.a; } } + #endregion + + public void Activate(bool activate) + { + GetComponent().enabled = activate; + } + + /// + /// Invert line color from white to black or vice versa. + /// + /// + /// + public bool InvertLineColor(bool invert) + { + if (invert) + { + GetComponent().color = Color.black; + } else { + GetComponent().color = Color.white; + } + return invert; + } + + /// + /// Update the grid overlay opacity by changing the Image alpha value. + /// + /// + public void UpdateOpacity(float alpha) + { + var image = GetComponent(); + GetComponent().color = new Color(image.color.r, image.color.g, image.color.b, alpha); + } + + /// + /// Update the orientation of the overlay image. + /// + /// / + public void Position(string orientation) + { + if (orientation == "Bottom Right") + { + GetComponent().transform.rotation = Quaternion.Euler(0, 0, 0); + } + else if (orientation == "Bottom Left") + { + GetComponent().transform.rotation = Quaternion.Euler(-180, 0, -180); + } + else if (orientation == "Top Right") + { + GetComponent().transform.rotation = Quaternion.Euler(-180, 0, 0); + } + else if (orientation == "Top Left") + { + GetComponent().transform.rotation = Quaternion.Euler(0, 0, -180); + } + } + } +} diff --git a/Assets/Scripts/Camera Composition/Scripts/CompositionOverlay.cs.meta b/Assets/Scripts/Camera Composition/Scripts/CompositionOverlay.cs.meta new file mode 100644 index 000000000..02a670258 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/CompositionOverlay.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 98b784d50a6597540a070c89dc4b72d0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 202816 + packageName: Camera Composition - Grid Overlay Tool + packageVersion: 1.0.2 + assetPath: Assets/Camera Composition/Scripts/CompositionOverlay.cs + uploadId: 471102 diff --git a/Assets/Scripts/Camera Composition/Scripts/Editor.meta b/Assets/Scripts/Camera Composition/Scripts/Editor.meta new file mode 100644 index 000000000..41703df4d --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cff1447509629e94e8a9944a36f9ab42 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Camera Composition/Scripts/Editor/CameraComposition.cs b/Assets/Scripts/Camera Composition/Scripts/Editor/CameraComposition.cs new file mode 100644 index 000000000..8f27e2ba2 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Editor/CameraComposition.cs @@ -0,0 +1,236 @@ +#if UNITY_EDITOR +using UnityEngine; +using UnityEditor; + +namespace JordanCassady +{ + public class CameraComposition : EditorWindow + { + #region PROPERTIES + private GameObject compositionObject; + private GUIStyle guiStyle; + private int tabIndex; + private GameObject targetCamera; + private Vector3 revertCameraPosition; + private Quaternion revertCameraRotation; + #endregion + + private readonly string[] tabNames = { "Rule of Thirds", "Diagonal", "Golden Ratio", "Golden Spiral", "Cross" }; + private Color greyColor = new Color(56f / 255f, 56f / 255f, 56f / 255f, 1f); + + [MenuItem("Tools/Camera Composition")] + public static void ShowWindow() + { + var window = GetWindow("Camera Composition"); + window.minSize = new Vector2(370, 186); + } + + private void OnEnable() + { + InitGUIStyle(); + } + + private void OnDestroy() + { + if (compositionObject != null) + { + DestroyImmediate(compositionObject); + } + } + + private void OnGUI() + { + if (compositionObject == null) + { + compositionObject = Instantiate(Resources.Load("Prefabs/Camera Composition")); + } + + DrawTabSection(); + DrawOverrideSection(); + DrawCameraSection(); + } + + private void InitGUIStyle() + { + guiStyle = new GUIStyle + { + fontSize = 12, + fontStyle = FontStyle.Bold, + normal = { textColor = Color.white } + }; + } + + private void DrawTabSection() + { + tabIndex = GUILayout.Toolbar(tabIndex, tabNames); + GUILayout.Space(10); + + if (compositionObject == null) return; + + GameObject overlayObject = compositionObject.transform.GetChild(tabIndex).gameObject; + + DrawGridSection(overlayObject); + DrawColorSection(overlayObject); + DrawOpacitySection(overlayObject); + + if (tabIndex == 3) // Golden Spiralë§Œ 회전 ì§€ì› + { + DrawRotationSection(overlayObject); + } + } + + private void DrawGridSection(GameObject overlayObject) + { + GUILayout.Label("Grid", guiStyle); + GUILayout.BeginHorizontal(); + + if (GUILayout.Button("On", GUILayout.Height(20))) + overlayObject.GetComponent().Activate(true); + + if (GUILayout.Button("Off", GUILayout.Height(20))) + overlayObject.GetComponent().Activate(false); + + GUILayout.EndHorizontal(); + GUILayout.Space(10); + } + + private void DrawRotationSection(GameObject overlayObject) + { + GUILayout.Label("Rotation", guiStyle); + GUILayout.BeginHorizontal(); + + if (GUILayout.Button("↶ Top Left", GUILayout.Height(30))) + { + overlayObject.GetComponent().Position("Top Left"); + ToggleGrid(overlayObject); + } + + if (GUILayout.Button("↷ Top Right", GUILayout.Height(30))) + { + overlayObject.GetComponent().Position("Top Right"); + ToggleGrid(overlayObject); + } + + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(); + + if (GUILayout.Button("↶ Bottom Left", GUILayout.Height(30))) + { + overlayObject.GetComponent().Position("Bottom Left"); + ToggleGrid(overlayObject); + } + + if (GUILayout.Button("↷ Bottom Right", GUILayout.Height(30))) + { + overlayObject.GetComponent().Position("Bottom Right"); + ToggleGrid(overlayObject); + } + + GUILayout.EndHorizontal(); + GUILayout.Space(10); + } + + private void DrawColorSection(GameObject overlayObject) + { + GUILayout.Label("Color", guiStyle); + GUILayout.BeginHorizontal(); + + if (GUILayout.Button("White", GUILayout.Height(20))) + { + overlayObject.GetComponent().InvertLineColor(false); + ToggleGrid(overlayObject); + } + + if (GUILayout.Button("Black", GUILayout.Height(20))) + { + overlayObject.GetComponent().InvertLineColor(true); + ToggleGrid(overlayObject); + } + + GUILayout.EndHorizontal(); + GUILayout.Space(10); + } + + private void DrawOpacitySection(GameObject overlayObject) + { + GUILayout.Label("Opacity", guiStyle); + + var opacity = overlayObject.GetComponent().Opacity; + opacity = EditorGUILayout.Slider(opacity, 0f, 1f); + overlayObject.GetComponent().UpdateOpacity(opacity); + ToggleGrid(overlayObject); + + GUILayout.Space(10); + } + + private void DrawOverrideSection() + { + GUILayout.Label("Overrides", guiStyle); + + if (GUILayout.Button("Turn Off All Grids", GUILayout.Height(20))) + { + if (compositionObject != null) + { + foreach (Transform overlayObject in compositionObject.transform) + { + overlayObject.gameObject.GetComponent().Activate(false); + } + } + } + GUILayout.Space(10); + } + + private void DrawCameraSection() + { + GUILayout.Label("Target Camera", guiStyle); + targetCamera = (GameObject)EditorGUILayout.ObjectField(targetCamera, typeof(GameObject), true); + + if (targetCamera == null) + { + EditorGUILayout.HelpBox("Select a target camera to adjust position & rotation.", MessageType.Info); + return; + } + + GUILayout.Space(10); + GUILayout.Label("Position", guiStyle); + Undo.RecordObject(targetCamera.transform, "Camera Position Change"); + targetCamera.transform.position = EditorGUILayout.Vector3Field("", targetCamera.transform.position); + + GUILayout.Label("Rotation", guiStyle); + Undo.RecordObject(targetCamera.transform, "Camera Rotation Change"); + Vector3 rotationVector = EditorGUILayout.Vector3Field("", targetCamera.transform.rotation.eulerAngles); + targetCamera.transform.rotation = Quaternion.Euler(rotationVector); + + GUILayout.Space(10); + GUILayout.BeginHorizontal(); + + if (GUILayout.Button("Align Camera With Scene View", GUILayout.Height(25))) + { + revertCameraPosition = targetCamera.transform.position; + revertCameraRotation = targetCamera.transform.rotation; + + SceneView sceneView = SceneView.lastActiveSceneView; + targetCamera.transform.position = sceneView.camera.transform.position; + targetCamera.transform.rotation = sceneView.camera.transform.rotation; + } + + if (GUILayout.Button("Revert", GUILayout.Height(25))) + { + targetCamera.transform.position = revertCameraPosition; + targetCamera.transform.rotation = revertCameraRotation; + } + + GUILayout.EndHorizontal(); + } + + private void ToggleGrid(GameObject overlayObject) + { + if (overlayObject.GetComponent().IsActive) + { + overlayObject.GetComponent().Activate(false); + overlayObject.GetComponent().Activate(true); + } + } + } +} +#endif diff --git a/Assets/Scripts/Camera Composition/Scripts/Editor/CameraComposition.cs.meta b/Assets/Scripts/Camera Composition/Scripts/Editor/CameraComposition.cs.meta new file mode 100644 index 000000000..d82f112f0 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Editor/CameraComposition.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: ebd5b4dd87acf5d4fb4708e7f8254391 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 202816 + packageName: Camera Composition - Grid Overlay Tool + packageVersion: 1.0.2 + assetPath: Assets/Camera Composition/Scripts/Editor/CameraComposition.cs + uploadId: 471102 diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources.meta b/Assets/Scripts/Camera Composition/Scripts/Resources.meta new file mode 100644 index 000000000..37c35ea4d --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dd7470611f8359d44bade60d577c1b3a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays.meta b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays.meta new file mode 100644 index 000000000..2b1d733b7 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f82d8fb0476d4ec49ba51d3ccc9bb995 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.cross.png b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.cross.png new file mode 100644 index 000000000..b1bcc6267 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.cross.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0781d34d98d5a38902b8908d2977d54863bb04292f07ac98844ed9fe74f1aed4 +size 37593 diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.cross.png.meta b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.cross.png.meta new file mode 100644 index 000000000..56459e7a1 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.cross.png.meta @@ -0,0 +1,117 @@ +fileFormatVersion: 2 +guid: 8d77b5e9fb0b60042bf500b550408d4a +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 0 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.diagonal.png b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.diagonal.png new file mode 100644 index 000000000..23d641c3a --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.diagonal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0e2ac1e3a6d3b4a52d72e26b27ee8ca036e9453ff6d5c4084b946aded85a469 +size 68094 diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.diagonal.png.meta b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.diagonal.png.meta new file mode 100644 index 000000000..931318902 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.diagonal.png.meta @@ -0,0 +1,115 @@ +fileFormatVersion: 2 +guid: c9d95680f7765924597092167a372bb2 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 0 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 4096 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 4096 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 202816 + packageName: Camera Composition - Grid Overlay Tool + packageVersion: 1.0.2 + assetPath: Assets/Camera Composition/Scripts/Resources/Overlays/overlays.diagonal.png + uploadId: 471102 diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenratio.png b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenratio.png new file mode 100644 index 000000000..12e2a5885 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenratio.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f18815b39da43c7f9222410fd8f14282390d97971ab6cb0c5fded639a4849c71 +size 37715 diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenratio.png.meta b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenratio.png.meta new file mode 100644 index 000000000..69a598d7e --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenratio.png.meta @@ -0,0 +1,115 @@ +fileFormatVersion: 2 +guid: 79b9b80aefa75f64b9d5a30ea126eea5 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 0 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 4096 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 4096 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 202816 + packageName: Camera Composition - Grid Overlay Tool + packageVersion: 1.0.2 + assetPath: Assets/Camera Composition/Scripts/Resources/Overlays/overlays.goldenratio.png + uploadId: 471102 diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenspiral.png b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenspiral.png new file mode 100644 index 000000000..227404634 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenspiral.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dacd30bddc99217b3c6e905f11d7cbcab1437a35f54fc164adc39389a79d7584 +size 93744 diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenspiral.png.meta b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenspiral.png.meta new file mode 100644 index 000000000..dc964c2f0 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.goldenspiral.png.meta @@ -0,0 +1,115 @@ +fileFormatVersion: 2 +guid: 1d42720af587c634194e68d63a6ab372 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 0 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 4096 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 4096 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 202816 + packageName: Camera Composition - Grid Overlay Tool + packageVersion: 1.0.2 + assetPath: Assets/Camera Composition/Scripts/Resources/Overlays/overlays.goldenspiral.png + uploadId: 471102 diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.ruleofthirds.png b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.ruleofthirds.png new file mode 100644 index 000000000..9f80d4f4b --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.ruleofthirds.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b94d1e8f7f4a987d60c21e7ef067f6603564887a2151fe7901ea78a610a536a +size 37678 diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.ruleofthirds.png.meta b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.ruleofthirds.png.meta new file mode 100644 index 000000000..17a134c8e --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Overlays/overlays.ruleofthirds.png.meta @@ -0,0 +1,115 @@ +fileFormatVersion: 2 +guid: 73733fe54b9af5542add1b1dcda3fe6e +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 0 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 4096 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 4096 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 202816 + packageName: Camera Composition - Grid Overlay Tool + packageVersion: 1.0.2 + assetPath: Assets/Camera Composition/Scripts/Resources/Overlays/overlays.ruleofthirds.png + uploadId: 471102 diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Prefabs.meta b/Assets/Scripts/Camera Composition/Scripts/Resources/Prefabs.meta new file mode 100644 index 000000000..09d7243da --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3da72fa5689b23e4db4a26f4614a4f37 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Prefabs/Camera Composition.prefab b/Assets/Scripts/Camera Composition/Scripts/Resources/Prefabs/Camera Composition.prefab new file mode 100644 index 000000000..11d434309 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Prefabs/Camera Composition.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb95e9844c3b0eb574c144c779bd6f20f00d38cf047547d9fcb0a36fb68c576d +size 15686 diff --git a/Assets/Scripts/Camera Composition/Scripts/Resources/Prefabs/Camera Composition.prefab.meta b/Assets/Scripts/Camera Composition/Scripts/Resources/Prefabs/Camera Composition.prefab.meta new file mode 100644 index 000000000..e2ce62660 --- /dev/null +++ b/Assets/Scripts/Camera Composition/Scripts/Resources/Prefabs/Camera Composition.prefab.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 95ddfacf554c2f24c977dafaf03affcd +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 202816 + packageName: Camera Composition - Grid Overlay Tool + packageVersion: 1.0.2 + assetPath: Assets/Camera Composition/Scripts/Resources/Prefabs/Camera Composition.prefab + uploadId: 471102 diff --git a/Assets/Scripts/Editor.meta b/Assets/Scripts/Editor.meta new file mode 100644 index 000000000..5341b656a --- /dev/null +++ b/Assets/Scripts/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 933c14437a47644f59d857bae047394e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/MMD2UnityToolMenu.cs b/Assets/Scripts/Editor/MMD2UnityToolMenu.cs new file mode 100644 index 000000000..e0e9ba793 --- /dev/null +++ b/Assets/Scripts/Editor/MMD2UnityToolMenu.cs @@ -0,0 +1,41 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +public static class MMD2UnityToolMenu +{ + //[MenuItem("Assets/MMD2UnityTool/Export Vmd To Fbx")] + public static void SpliteMMDFbxMotionToHumainMotionFbx() + { + var selected = Selection.activeObject; + string selectPath = AssetDatabase.GetAssetPath(selected); + if (!string.IsNullOrEmpty(selectPath)) + { + FbxConverterTool.SpliteFbxMotion2Anim(selectPath); + } + else + { + Debug.LogError("没有选中文件或文件夹"); + } + } + + [MenuItem("Assets/MMD2UnityTool/Export Camera Vmd To Anim")] + public static void ExportCameraVmdToAnim() + { + var selected = Selection.activeObject; + string selectPath = AssetDatabase.GetAssetPath(selected); + if (!string.IsNullOrEmpty(selectPath)) + { + CameraVmdAgent camera_agent = new CameraVmdAgent(selectPath); + camera_agent.CreateAnimationClip(); + Debug.LogFormat("[{0}]:Export Camera Vmd Success!", System.DateTime.Now); + } + else + { + Debug.LogError("没有选中文件或文件夹"); + } + } + + +} diff --git a/Assets/Scripts/Editor/MMD2UnityToolMenu.cs.meta b/Assets/Scripts/Editor/MMD2UnityToolMenu.cs.meta new file mode 100644 index 000000000..5dfc6c91e --- /dev/null +++ b/Assets/Scripts/Editor/MMD2UnityToolMenu.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a8e5eaa97dd4747388e0e19686ce50ff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Private.meta b/Assets/Scripts/Editor/Private.meta new file mode 100644 index 000000000..f83748daf --- /dev/null +++ b/Assets/Scripts/Editor/Private.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0a46a49821585407b924d826eb4f1fe3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Private/CameraVmdAgent.cs b/Assets/Scripts/Editor/Private/CameraVmdAgent.cs new file mode 100644 index 000000000..24cbd76c0 --- /dev/null +++ b/Assets/Scripts/Editor/Private/CameraVmdAgent.cs @@ -0,0 +1,43 @@ +using System.Collections; +using System.Collections.Generic; +using System.IO; +using UnityEditor; +using UnityEngine; + +public class CameraVmdAgent +{ + string _vmdFile; + MMD.VMD.VMDFormat format_; + + public CameraVmdAgent(string filePath) + { + _vmdFile = filePath; + + } + + public void CreateAnimationClip() + { + if (null == format_) + { + format_ = VMDLoaderScript.Import(_vmdFile); + } + + AnimationClip animation_clip = VMDCameraConverter.CreateAnimationClip(format_); + if (animation_clip == null) + { + throw new System.Exception("Cannot create AnimationClip"); + } + + string vmd_folder = Path.GetDirectoryName(_vmdFile); + string anima_file = Path.Combine(vmd_folder, animation_clip.name + ".anim"); + + if (File.Exists(anima_file)) + AssetDatabase.DeleteAsset(anima_file); + + AssetDatabase.CreateAsset(animation_clip, anima_file); + + AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(animation_clip)); + + //AssetDatabase.Refresh(); + } +} diff --git a/Assets/Scripts/Editor/Private/CameraVmdAgent.cs.meta b/Assets/Scripts/Editor/Private/CameraVmdAgent.cs.meta new file mode 100644 index 000000000..9e7ea4c0d --- /dev/null +++ b/Assets/Scripts/Editor/Private/CameraVmdAgent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 378d93e894cfb4722b77ca45677e13bf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Private/FbxConverterTool.cs b/Assets/Scripts/Editor/Private/FbxConverterTool.cs new file mode 100644 index 000000000..743dffee1 --- /dev/null +++ b/Assets/Scripts/Editor/Private/FbxConverterTool.cs @@ -0,0 +1,41 @@ +using System.Collections; +using System.Collections.Generic; +using System.IO; +using UnityEditor; +using UnityEngine; + +public static class FbxConverterTool +{ + //å°†Fbxå†…çš„åŠ¨ç”»æ–‡ä»¶åˆ†ç¦»å‡ºæ¥ + public static void SpliteFbxMotion2Anim(string fbxPath) + { + Object[] objects = AssetDatabase.LoadAllAssetsAtPath(fbxPath); //加载FBX里所有物体 + if (objects != null && objects.Length > 0) + { + string targetPath = Application.dataPath + "/AnimationClip"; //目录AnimationClip + if (!Directory.Exists(targetPath)) + { + Directory.CreateDirectory(targetPath); //如果目录ä¸å­˜åœ¨å°±åˆ›å»ºä¸€ä¸ª + } + + foreach (Object obj in objects) //é历选择的物体 + { + AnimationClip fbxClip = obj as AnimationClip; + if (fbxClip != null) + { + AnimationClip clip = new AnimationClip(); //new一个AnimationClip存放生æˆçš„AnimationClip + EditorUtility.CopySerialized(fbxClip, clip); //å¤åˆ¶ + AssetDatabase.CreateAsset(clip, "Assets/AnimationClip/" + fbxClip.name + ".anim"); //ç”Ÿæˆæ–‡ä»¶ + } + else + { + Debug.Log("当å‰é€‰æ‹©çš„æ–‡ä»¶ä¸æ˜¯å¸¦æœ‰AnimationClipçš„FBX文件"); + } + } + + } + + + } + +} diff --git a/Assets/Scripts/Editor/Private/FbxConverterTool.cs.meta b/Assets/Scripts/Editor/Private/FbxConverterTool.cs.meta new file mode 100644 index 000000000..ed7275d51 --- /dev/null +++ b/Assets/Scripts/Editor/Private/FbxConverterTool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 68bd6b02f80a7470980b8a4a2e7a10ff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Private/VMDCameraConverter.cs b/Assets/Scripts/Editor/Private/VMDCameraConverter.cs new file mode 100644 index 000000000..2ea6ef61f --- /dev/null +++ b/Assets/Scripts/Editor/Private/VMDCameraConverter.cs @@ -0,0 +1,317 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using MMD.VMD; +using UnityEditor; +using UnityEngine; + +public class VMDCameraConverter +{ + public static AnimationClip CreateAnimationClip(VMDFormat format) + { + VMDCameraConverter converter = new VMDCameraConverter(); + return converter.CreateAnimationClip_(format); + } + + private AnimationClip CreateAnimationClip_(VMDFormat format) + { + + AnimationClip clip = new AnimationClip(); + clip.name = format.name; + + CreateKeysForCamera(format, clip); + + return clip; + } + + void CreateKeysForCamera(VMDFormat format, AnimationClip clip) + { + const float tick_time = 1f / 30f; + const float mmd4unity_unit = 0.085f; + + Keyframe[] posX_keyframes = new Keyframe[format.camera_list.camera_count]; + Keyframe[] posY_keyframes = new Keyframe[format.camera_list.camera_count]; + Keyframe[] posZ_keyframes = new Keyframe[format.camera_list.camera_count]; + + Keyframe[] rotX_keyframes = new Keyframe[format.camera_list.camera_count]; + Keyframe[] rotY_keyframes = new Keyframe[format.camera_list.camera_count]; + Keyframe[] rotZ_keyframes = new Keyframe[format.camera_list.camera_count]; + + Keyframe[] fov_keyframes = new Keyframe[format.camera_list.camera_count]; + + //æ¨¡æ‹Ÿä¸€ä¸ªç›¸æœºçš„å˜æ¢,ç”¨çŸ©é˜µå˜æ¢ä¹Ÿå¯ä»¥,ä»Žä¸–ç•Œåæ ‡è½¬å±€éƒ¨å标会很麻烦 + var cameraWorldObj = new GameObject(); + var cameraLocalObj = new GameObject(); + var cameraWorldTrans = cameraWorldObj.transform; + var cameraLocalTrans = cameraLocalObj.transform; + cameraLocalTrans.SetParent(cameraWorldTrans); + + for (int i = 0; i < format.camera_list.camera_count; i++) + { + VMDFormat.CameraData cameraData = format.camera_list.camera[i]; + + //ä½ç½® + cameraWorldTrans.localPosition = new Vector3( + cameraData.location.x * mmd4unity_unit, + cameraData.location.y * mmd4unity_unit, + cameraData.location.z * mmd4unity_unit); + + //旋转 + //localEulerAngleså–值åŽå°†è§’度设置为ç»å¯¹å€¼, + //https://docs.unity3d.com/cn/2017.4/ScriptReference/Transform-localEulerAngles.html + Vector3 rotationAsix = new Vector3( + -(cameraData.rotation.x) * Mathf.Rad2Deg, + -(cameraData.rotation.y) * Mathf.Rad2Deg, + -(cameraData.rotation.z) * Mathf.Rad2Deg); + cameraWorldTrans.localEulerAngles = rotationAsix; + + //è·ç¦»,ä¿®æ”¹å±€éƒ¨åæ ‡çš„Z值 + cameraLocalTrans.localEulerAngles = Vector3.zero; + cameraLocalTrans.localPosition = new Vector3(0, 0, (cameraData.length) * mmd4unity_unit);//Z相åè½´,但这里实际值已ç»ç»è¿‡å–åå¤„ç† + + float frameTime = cameraData.frame_no * tick_time; + posX_keyframes[i] = new Keyframe(frameTime, cameraLocalTrans.position.x); + posY_keyframes[i] = new Keyframe(frameTime, cameraLocalTrans.position.y); + posZ_keyframes[i] = new Keyframe(frameTime, cameraLocalTrans.position.z); + + //åšåŠ¨ç”»æ—¶æœ€å¥½ç”¨åŽŸå€¼,localEulerAngleså–值åŽå°†è§’度设置为ç»å¯¹å€¼,在åšè¡¥é—´æ›²çº¿ä¼šå‡ºé—®é¢˜ + rotX_keyframes[i] = new Keyframe(frameTime, rotationAsix.x); + rotY_keyframes[i] = new Keyframe(frameTime, rotationAsix.y); + rotZ_keyframes[i] = new Keyframe(frameTime, rotationAsix.z); + + //视角fov + fov_keyframes[i] = new Keyframe(frameTime, cameraData.viewing_angle); + } + + UnityEngine.Object.DestroyImmediate(cameraWorldObj); + + //NOTE:这里"è·ç¦»"å·²ç»ä¸Žpositionèžåˆäº†,所以没法åšè¡¥é—´ + AnimationCurve posX_curve = ToAnimationCurveWithTangentMode(1, AnimationUtility.TangentMode.Free, posX_keyframes, format.camera_list); + AnimationCurve posY_curve = ToAnimationCurveWithTangentMode(2, AnimationUtility.TangentMode.Free, posY_keyframes, format.camera_list); + AnimationCurve posZ_curve = ToAnimationCurveWithTangentMode(3, AnimationUtility.TangentMode.Free, posZ_keyframes, format.camera_list); + AnimationCurve rotX_curve = ToAnimationCurveWithTangentMode(4, AnimationUtility.TangentMode.Free, rotX_keyframes, format.camera_list); + AnimationCurve rotY_curve = ToAnimationCurveWithTangentMode(4, AnimationUtility.TangentMode.Free, rotY_keyframes, format.camera_list); + AnimationCurve rotZ_curve = ToAnimationCurveWithTangentMode(4, AnimationUtility.TangentMode.Free, rotZ_keyframes, format.camera_list); + AnimationCurve fov_curve = ToAnimationCurveWithTangentMode(6, AnimationUtility.TangentMode.Free, fov_keyframes, format.camera_list); + + + AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve("", typeof(Transform), "m_LocalPosition.x"), posX_curve); + AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve("", typeof(Transform), "m_LocalPosition.y"), posY_curve); + AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve("", typeof(Transform), "m_LocalPosition.z"), posZ_curve); + AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve("", typeof(Transform), "localEulerAnglesRaw.x"), rotX_curve); //采用欧拉角æ’å€¼æ–¹å¼ + AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve("", typeof(Transform), "localEulerAnglesRaw.y"), rotY_curve); + AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve("", typeof(Transform), "localEulerAnglesRaw.z"), rotZ_curve); + + + AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve("", typeof(Camera), "field of view"), fov_curve); + } + + //ç»è¿‡è§‚察得知interpolationå‰å››ä½åˆ†åˆ«æ˜¯(x1,x2)(y1,y2) + //总共6*4点,分别是[Xè½´,Yè½´,Zè½´,旋转,è·ç¦»,视角] + //都是以左下角为原点 + Tuple GetInterpolationPoints(byte[] interpolation, int type) + { + int row = (type - 1) * 4; + Vector2 p1 = new Vector2(interpolation[row + 0], interpolation[row + 2]); + Vector2 p2 = new Vector2(interpolation[row + 1], interpolation[row + 3]); + + return new Tuple(p1, p2); + } + + //把MMD补间曲线中p1,p2的点映射回Curve中去 + Tuple ConvertToFramekeyControllerPoint(Vector2 p1, Vector2 p2, Keyframe outKeyframe, Keyframe inKeyframe) + { + var dX = inKeyframe.time - outKeyframe.time; + var dY = inKeyframe.value - outKeyframe.value; + + var newP1 = new Vector2(outKeyframe.time + p1.x / 127 * dX, outKeyframe.value + p1.y / 127 * dY); + var newP2 = new Vector2(outKeyframe.time + p2.x / 127 * dX, outKeyframe.value + p2.y / 127 * dY); + + //因为ä¸å­˜åœ¨90度的情况,这里è¦è¶‹è¿‘,但是也ä¸èƒ½å¤ªè¶‹è¿‘,ä¸ç„¶è¡¥é—´å‰å‡ å¸§ä¼šå˜çš„陡峭 + if (Mathf.Approximately(outKeyframe.time, newP1.x)) newP1.x += 0.1f; + if (Mathf.Approximately(inKeyframe.time, newP2.x)) newP2.x -= 0.1f; + + return new Tuple(newP1, newP2); + } + + private static float Tangent(in Vector2 from, in Vector2 to) + { + Vector2 vec = to - from; + return vec.y / vec.x; + } + + private static float Weight(in Vector2 from, in Vector2 to, float length) + { + return (to.x - from.x) / length; + } + + //æ ¹æ®å››ä¸ªæŽ§åˆ¶ç‚¹è®¡ç®—三次è´å¡žå°”曲线的系数 + //æ’值:è´å¡žå°”曲线æ’值(四个点) + //https://blog.csdn.net/seizeF/article/details/96368503 + //return {outTangent,outWeight,inTangent,inWeight) + float[] CalculateBezierCoefficient(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3) + { + float p30Length = (p3.x - p0.x); + + float outTangent = Tangent(p0, p1); + float outWeight = Weight(p0, p1, p30Length); + + float inTangent = Tangent(p2, p3); + float inWeight = Weight(p2, p3, p30Length); + + return new float[] { outTangent, outWeight, inTangent, inWeight }; + } + + void SetKeyfreamTweenCurve(int index, int type, Keyframe[] keyframes, VMDFormat.CameraList cameraList) + { + if (index <= 0) + return; + + VMDFormat.CameraData curCameraData = cameraList.camera[index]; + VMDFormat.CameraData lastCameraData = cameraList.camera[index - 1]; + + Keyframe outKeyframe = keyframes[index - 1]; + Keyframe inKeyframe = keyframes[index]; + + var dX = inKeyframe.time - outKeyframe.time; + var dY = inKeyframe.value - outKeyframe.value; + + outKeyframe.weightedMode = WeightedMode.Both; + inKeyframe.weightedMode = WeightedMode.Both; + if (Mathf.Approximately(dY, 0f) || Mathf.Approximately(dX, 1 / 30f)) //没有å˜åŒ–的就ä¸éœ€è¦è¡¥é—´æ’值了 + { + outKeyframe.outTangent = 0; + outKeyframe.outWeight = 0; + + inKeyframe.inTangent = 0; + inKeyframe.inWeight = 0; + } + else + { + //æ’值计算[0~127] + //å‚考https://www.jianshu.com/p/ae312fb53fc3 + Vector2 p0 = new Vector2(outKeyframe.time, outKeyframe.value); + Vector2 p3 = new Vector2(inKeyframe.time, inKeyframe.value); + Vector2 p1 = Vector2.zero; + Vector2 p2 = Vector2.zero; + var intTuple = GetInterpolationPoints(curCameraData.interpolation, type); + var ptTuple = ConvertToFramekeyControllerPoint(intTuple.Item1, intTuple.Item2, outKeyframe, inKeyframe); //转化为keyFrame的控制点 + p1 = ptTuple.Item1; + p2 = ptTuple.Item2; + + float[] coeffs = CalculateBezierCoefficient(p0, p1, p2, p3); + outKeyframe.outTangent = coeffs[0]; + outKeyframe.outWeight = coeffs[1]; + inKeyframe.inTangent = coeffs[2]; + inKeyframe.inWeight = coeffs[3]; + } + + //因为是结构体,所以需è¦é‡æ–°èµ‹å€¼ + keyframes[index - 1] = outKeyframe; + keyframes[index] = inKeyframe; + } + + AnimationCurve ToAnimationCurveWithTangentMode(int type, AnimationUtility.TangentMode mode, Keyframe[] keyframes, VMDFormat.CameraList cameraList) + { + if (mode == AnimationUtility.TangentMode.Free) + { + for (int i = 0; i < keyframes.Length; i++) + { + SetKeyfreamTweenCurve(i, type, keyframes, cameraList); + } + } + + var newKeyFrames = OptimizedCurves(type, keyframes, cameraList); + + AnimationCurve curve = new AnimationCurve(newKeyFrames); + for (int i = 0; i < curve.keys.Length; i++) + { + if (mode == AnimationUtility.TangentMode.Free) + AnimationUtility.SetKeyBroken(curve, i, true); + + AnimationUtility.SetKeyLeftTangentMode(curve, i, mode); + AnimationUtility.SetKeyRightTangentMode(curve, i, mode); + + } + return curve; + } + + ////由于Unity自带的æ’å€¼æ›²çº¿å¹³æ»‘æ•ˆæžœä¸æ˜¯å¾ˆå¥½,å¯ä»¥é€šè¿‡æ’入关键帧的方å¼å¹³æ»‘曲线 + //三次è´å¡žå°”曲线æ’值 + Vector2 EvaluteThire(float t, Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3) + { + return Mathf.Pow(1 - t, 3) * p0 + 3 * Mathf.Pow(1 - t, 2) * t * p1 + 3 * (1 - t) * Mathf.Pow(t, 2) * p2 + Mathf.Pow(t, 3) * p3; + } + + //补间æ’值æ’入关键帧 + List CalculateInterpolationKeyframe(int type, byte[] interpolation, Keyframe outKeyframe, Keyframe inKeyframe, float density = 0.05f) + { + density = Mathf.Min(1f, density); + density = Mathf.Max(0f, density); + var p0 = new Vector2(outKeyframe.time, outKeyframe.value); + var p3 = new Vector2(inKeyframe.time, inKeyframe.value); + var intTuple = GetInterpolationPoints(interpolation, type); + var ptTuple = ConvertToFramekeyControllerPoint(intTuple.Item1, intTuple.Item2, outKeyframe, inKeyframe); //转化为keyFrame的控制点 + var p1 = ptTuple.Item1; + var p2 = ptTuple.Item2; + + var dX = inKeyframe.time - outKeyframe.time; + var dY = inKeyframe.value - outKeyframe.value; + float stepTime = (1 / 30f) / density; + List interpolationKeyframes = new List(); + if (!Mathf.Approximately(dY, 0f)) + { + if (stepTime > 0f && stepTime >= (1 / 30f)) + { + for (float time = outKeyframe.time + stepTime; time < inKeyframe.time; time += stepTime) + { + float t = (time - outKeyframe.time) / dX; + var pt = EvaluteThire(t, p0, p1, p2, p3); + + var newKeyframe = new Keyframe(pt.x, pt.y); + interpolationKeyframes.Add(newKeyframe); + } + } + + } + + return interpolationKeyframes; + } + + Keyframe[] OptimizedCurves(int type, Keyframe[] keyframes, VMDFormat.CameraList cameraList) + { + List framesList = new List(); + + //曲线优化 + for (int i = 0; i < keyframes.Length; i++) + { + //if (i > 0) + //{ + // var lastKeyFrame = keyframes[i - 1]; + // var curKeyFrame = keyframes[i]; + + // VMDFormat.CameraData curCameraData = cameraList.camera[i]; + // var exKeyFrames = CalculateInterpolationKeyframe(type, curCameraData.interpolation, lastKeyFrame, curKeyFrame); + // framesList.AddRange(exKeyFrames); + //} + var keyframe = keyframes[i]; + framesList.Add(keyframe); + } + + //é’ˆå¯¹åªæœ‰ä¸€å¸§çš„进行优化 + if (framesList.Count == 1) + { + Keyframe[] newKeyframes = new Keyframe[2]; + newKeyframes[0] = keyframes[0]; + newKeyframes[1] = keyframes[0]; + newKeyframes[1].time += 0.001f / 60f;//1[ms] + newKeyframes[0].outTangent = 0f; + newKeyframes[1].inTangent = 0f; + + framesList.Clear(); + framesList.AddRange(newKeyframes); + } + + return framesList.ToArray(); + } +} diff --git a/Assets/Scripts/Editor/Private/VMDCameraConverter.cs.meta b/Assets/Scripts/Editor/Private/VMDCameraConverter.cs.meta new file mode 100644 index 000000000..0928caf69 --- /dev/null +++ b/Assets/Scripts/Editor/Private/VMDCameraConverter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d442fd3ddd0a34461a4543f3a0f2bc09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/FindUnusedBones.meta b/Assets/Scripts/FindUnusedBones.meta new file mode 100644 index 000000000..7ee326081 --- /dev/null +++ b/Assets/Scripts/FindUnusedBones.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b05835dece7e63047b88ac591fcc3408 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/FindUnusedBones/FindUnusedBones.cs b/Assets/Scripts/FindUnusedBones/FindUnusedBones.cs new file mode 100644 index 000000000..a53fa1a79 --- /dev/null +++ b/Assets/Scripts/FindUnusedBones/FindUnusedBones.cs @@ -0,0 +1,109 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +public class FindUnusedBones : EditorWindow +{ + private List excludeStrings = new List(); // 제외할 문ìžì—´ 리스트 + + [MenuItem("Tools/Find Unused Bones")] + public static void ShowWindow() + { + GetWindow("Find Unused Bones"); + } + + private void OnGUI() + { + GUILayout.Label("Exclude Strings", EditorStyles.boldLabel); + + // ë™ì ìœ¼ë¡œ 문ìžì—´ ìž…ë ¥ 필드와 + - ë²„íŠ¼ì„ ì¶”ê°€ + for (int i = 0; i < excludeStrings.Count; i++) + { + GUILayout.BeginHorizontal(); + excludeStrings[i] = EditorGUILayout.TextField($"Exclude String {i + 1}", excludeStrings[i]); + + if (GUILayout.Button("-", GUILayout.Width(20))) + { + excludeStrings.RemoveAt(i); + } + GUILayout.EndHorizontal(); + } + + if (GUILayout.Button("+", GUILayout.Width(20))) + { + excludeStrings.Add(string.Empty); // 빈 문ìžì—´ ìž…ë ¥ 필드 추가 + } + + GUILayout.Space(20); + + if (GUILayout.Button("Find and Select Unused Bones")) + { + FindAndSelectUnusedBones(); + } + } + + private void FindAndSelectUnusedBones() + { + if (Selection.activeGameObject == null) + { + Debug.LogWarning("No GameObject selected!"); + return; + } + + Transform root = Selection.activeGameObject.transform; + SkinnedMeshRenderer[] skinnedMeshRenderers = root.GetComponentsInChildren(); + + HashSet usedBones = new HashSet(); + HashSet excludedObjects = new HashSet(); + + // Add all bones used by SkinnedMeshRenderers to usedBones set + foreach (var skinnedMeshRenderer in skinnedMeshRenderers) + { + foreach (var bone in skinnedMeshRenderer.bones) + { + usedBones.Add(bone); + } + // Add the SkinnedMeshRenderer's gameObject and its parents to excludedObjects set + Transform current = skinnedMeshRenderer.transform; + while (current != null) + { + excludedObjects.Add(current); + current = current.parent; + } + } + + List unusedBones = new List(); + Transform[] allBones = root.GetComponentsInChildren(); + foreach (var bone in allBones) + { + // 문ìžì—´ í•„í„°ë§: 사용ìžê°€ 입력한 문ìžì—´ì„ í¬í•¨í•œ 오브ì íŠ¸ëŠ” 제외 + bool excludeBone = false; + foreach (var excludeString in excludeStrings) + { + if (!string.IsNullOrEmpty(excludeString) && bone.name.ToLower().Contains(excludeString.ToLower())) + { + excludeBone = true; + break; + } + } + + if (!usedBones.Contains(bone) && + !excludedObjects.Contains(bone) && + bone != root && + !excludeBone) // í•„í„°ë§ëœ 오브ì íЏ 제외 + { + unusedBones.Add(bone); + } + } + + if (unusedBones.Count > 0) + { + Selection.objects = unusedBones.ConvertAll(b => b.gameObject).ToArray(); + Debug.Log($"Found {unusedBones.Count} unused bones. Selected in the hierarchy."); + } + else + { + Debug.Log("No unused bones found."); + } + } +} diff --git a/Assets/Scripts/FindUnusedBones/FindUnusedBones.cs.meta b/Assets/Scripts/FindUnusedBones/FindUnusedBones.cs.meta new file mode 100644 index 000000000..97ddfc150 --- /dev/null +++ b/Assets/Scripts/FindUnusedBones/FindUnusedBones.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 893eb3d42574b394d82065f5781ac45f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/MaterialAndTextureCollectorWindow.cs b/Assets/Scripts/MaterialAndTextureCollectorWindow.cs new file mode 100644 index 000000000..a16150c16 --- /dev/null +++ b/Assets/Scripts/MaterialAndTextureCollectorWindow.cs @@ -0,0 +1,248 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.IO; + +public class MaterialAndTextureTool : EditorWindow +{ + private GameObject targetPrefab; + private string materialOutputPath = "Assets/DuplicatedMaterials"; + private string textureOutputPath = "Assets/DuplicatedTextures"; + + private Dictionary> duplicateMaterialMap = new Dictionary>(); + private Dictionary> duplicateTextureMap = new Dictionary>(); + private Dictionary materialCopies = new Dictionary(); + private Dictionary textureCopies = new Dictionary(); + private HashSet collectedMaterials = new HashSet(); + private HashSet collectedTextures = new HashSet(); + private Vector2 scroll; + + [MenuItem("Tools/Material & Texture Tool")] + public static void ShowWindow() + { + var window = GetWindow("MatTex Tool"); + window.minSize = new Vector2(600, 500); + } + + private void OnGUI() + { + GUILayout.Label("\uD83C\uDF1F 머테리얼 & í…스처 유틸리티", EditorStyles.boldLabel); + + targetPrefab = (GameObject)EditorGUILayout.ObjectField("\uD83D\uDCE6 타겟 프리팹", targetPrefab, typeof(GameObject), true); + materialOutputPath = EditorGUILayout.TextField("\uD83D\uDCC2 머테리얼 저장 경로", materialOutputPath); + textureOutputPath = EditorGUILayout.TextField("\uD83D\uDCC2 í…스처 저장 경로", textureOutputPath); + + if (GUILayout.Button("\uD83D\uDCCB 중복 ì´ë¦„ 검사")) CollectDuplicates(); + if (GUILayout.Button("\uD83D\uDD04 중복 ì´ë¦„ ìžë™ 변경")) RenameDuplicateAssets(); + if (GUILayout.Button("\uD83D\uDD04 머테리얼 ë° í…스처 복사")) DuplicateMaterialsAndTextures(); + + scroll = EditorGUILayout.BeginScrollView(scroll); + GUILayout.Space(10); + GUILayout.Label("\u26A0\uFE0F ì¤‘ë³µëœ ì´ë¦„ì˜ ë¨¸í…Œë¦¬ì–¼", EditorStyles.boldLabel); + DrawDuplicateList(duplicateMaterialMap); + + GUILayout.Space(10); + GUILayout.Label("\u26A0\uFE0F ì¤‘ë³µëœ ì´ë¦„ì˜ í…스처", EditorStyles.boldLabel); + DrawDuplicateList(duplicateTextureMap); + + GUILayout.Space(10); + GUILayout.Label("\uD83D\uDD0D ì°¸ì¡°ëœ ëª¨ë“  머테리얼", EditorStyles.boldLabel); + foreach (var mat in collectedMaterials) + { + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(mat.name, GUILayout.Width(200))) + { + EditorGUIUtility.PingObject(mat); + } + EditorGUILayout.ObjectField(mat, typeof(Material), false); + EditorGUILayout.EndHorizontal(); + } + + GUILayout.Space(10); + GUILayout.Label("\uD83D\uDD0D ì°¸ì¡°ëœ ëª¨ë“  í…스처", EditorStyles.boldLabel); + foreach (var tex in collectedTextures) + { + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button(tex.name, GUILayout.Width(200))) + { + EditorGUIUtility.PingObject(tex); + } + EditorGUILayout.ObjectField(tex, typeof(Texture), false); + EditorGUILayout.EndHorizontal(); + } + + EditorGUILayout.EndScrollView(); + } + + void CollectDuplicates() + { + duplicateMaterialMap.Clear(); + duplicateTextureMap.Clear(); + collectedMaterials.Clear(); + collectedTextures.Clear(); + + if (targetPrefab == null) return; + + HashSet seenMaterials = new HashSet(); + HashSet seenTextures = new HashSet(); + + var renderers = targetPrefab.GetComponentsInChildren(true); + + foreach (var renderer in renderers) + { + foreach (var mat in renderer.sharedMaterials) + { + if (mat == null || seenMaterials.Contains(mat)) continue; + seenMaterials.Add(mat); + collectedMaterials.Add(mat); + + if (!duplicateMaterialMap.ContainsKey(mat.name)) + duplicateMaterialMap[mat.name] = new List(); + duplicateMaterialMap[mat.name].Add(mat); + + Shader shader = mat.shader; + int count = ShaderUtil.GetPropertyCount(shader); + for (int i = 0; i < count; i++) + { + string propName = ShaderUtil.GetPropertyName(shader, i); + Texture tex = mat.GetTexture(propName); + if (tex == null || seenTextures.Contains(tex)) continue; + seenTextures.Add(tex); + collectedTextures.Add(tex); + + if (!duplicateTextureMap.ContainsKey(tex.name)) + duplicateTextureMap[tex.name] = new List(); + duplicateTextureMap[tex.name].Add(tex); + } + } + } + } + + void DrawDuplicateList(Dictionary> map) where T : Object + { + foreach (var pair in map) + { + if (pair.Value.Count < 2) continue; + GUILayout.Label("\u26A0\uFE0F " + pair.Key + " (" + pair.Value.Count + "ê°œ)", GetRedStyle()); + foreach (var obj in pair.Value) + { + EditorGUILayout.ObjectField(obj, typeof(T), false); + } + } + } + + void RenameDuplicateAssets() + { + Dictionary renameCount = new Dictionary(); + + RenameAssetGroup(duplicateMaterialMap, ".mat", renameCount); + RenameAssetGroup(duplicateTextureMap, null, renameCount); + + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + + void RenameAssetGroup(Dictionary> map, string extOverride, Dictionary counter) where T : Object + { + foreach (var pair in map) + { + if (pair.Value.Count < 2) continue; + foreach (var obj in pair.Value) + { + string path = AssetDatabase.GetAssetPath(obj); + if (string.IsNullOrEmpty(path)) continue; + + if (!counter.ContainsKey(pair.Key)) counter[pair.Key] = 1; + else counter[pair.Key] += 1; + + string newName = pair.Key + "_" + counter[pair.Key]; + string result = AssetDatabase.RenameAsset(path, newName); + if (result != "") + { + Debug.LogWarning("리네ì´ë° 실패: " + result); + } + } + } + } + + void DuplicateMaterialsAndTextures() + { + if (targetPrefab == null) return; + + materialCopies.Clear(); + textureCopies.Clear(); + + if (!AssetDatabase.IsValidFolder(materialOutputPath)) AssetDatabase.CreateFolder("Assets", "DuplicatedMaterials"); + if (!AssetDatabase.IsValidFolder(textureOutputPath)) AssetDatabase.CreateFolder("Assets", "DuplicatedTextures"); + + Renderer[] renderers = targetPrefab.GetComponentsInChildren(true); + + foreach (var renderer in renderers) + { + Material[] newMats = new Material[renderer.sharedMaterials.Length]; + + for (int i = 0; i < newMats.Length; i++) + { + Material orig = renderer.sharedMaterials[i]; + if (orig == null) continue; + + if (!materialCopies.ContainsKey(orig)) + { + Material newMat = new Material(orig); + string matPath = AssetDatabase.GenerateUniqueAssetPath(materialOutputPath + "/" + orig.name + "_Copy.mat"); + AssetDatabase.CreateAsset(newMat, matPath); + materialCopies[orig] = newMat; + CopyTextures(orig, newMat); + EditorUtility.SetDirty(newMat); + } + newMats[i] = materialCopies[orig]; + } + + Undo.RecordObject(renderer, "Apply Copied Materials"); + renderer.sharedMaterials = newMats; + } + + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + + void CopyTextures(Material original, Material copy) + { + Shader shader = original.shader; + int count = ShaderUtil.GetPropertyCount(shader); + + string[] maskProps = { "_MaskMap", "_OcclusionMap", "_DetailMask", "_RoughnessMap", "_MetallicGlossMap" }; + + for (int i = 0; i < count; i++) + { + string prop = ShaderUtil.GetPropertyName(shader, i); + Texture tex = original.GetTexture(prop); + if (tex == null) continue; + + bool isTexEnv = ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv; + bool isMask = System.Array.IndexOf(maskProps, prop) >= 0; + + if (isTexEnv || isMask) + { + if (!textureCopies.ContainsKey(tex)) + { + string path = AssetDatabase.GetAssetPath(tex); + string newPath = AssetDatabase.GenerateUniqueAssetPath(textureOutputPath + "/" + tex.name + "_Copy" + Path.GetExtension(path)); + AssetDatabase.CopyAsset(path, newPath); + Texture newTex = AssetDatabase.LoadAssetAtPath(newPath); + textureCopies[tex] = newTex; + } + + copy.SetTexture(prop, textureCopies[tex]); + EditorUtility.SetDirty(copy); + } + } + } + + GUIStyle GetRedStyle() + { + var style = new GUIStyle(EditorStyles.label); + style.normal.textColor = Color.red; + return style; + } +} diff --git a/Assets/Scripts/MaterialAndTextureCollectorWindow.cs.meta b/Assets/Scripts/MaterialAndTextureCollectorWindow.cs.meta new file mode 100644 index 000000000..af9e65a5b --- /dev/null +++ b/Assets/Scripts/MaterialAndTextureCollectorWindow.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: f78b1b0726fa6b243b6fd33cb00a67b8 \ No newline at end of file diff --git a/Assets/Scripts/MaterialMover.cs b/Assets/Scripts/MaterialMover.cs new file mode 100644 index 000000000..433f6b1fa --- /dev/null +++ b/Assets/Scripts/MaterialMover.cs @@ -0,0 +1,287 @@ +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; +using System.Linq; +using System.IO; + +public class MaterialAndTextureMover : EditorWindow +{ + public List targetObjects = new List(); + public string targetFolder = "Assets/"; + private List foundMaterials = new List(); + private List materialSelectionStatus = new List(); + private List foundTextures = new List(); + private List textureSelectionStatus = new List(); + private bool materialsSearched = false; + + private Vector2 scrollPos; + + [MenuItem("Tools/Material and Texture Mover")] + public static void ShowWindow() + { + GetWindow("Material & Texture Mover"); + } + + private void OnGUI() + { + GUILayout.Label("Step 1: Select Target Objects and Search Materials and Textures", EditorStyles.boldLabel); + + int removeIndex = -1; + for (int i = 0; i < targetObjects.Count; i++) + { + GUILayout.BeginHorizontal(); + targetObjects[i] = (GameObject)EditorGUILayout.ObjectField(targetObjects[i], typeof(GameObject), true); + if (GUILayout.Button("Remove", GUILayout.Width(60))) + { + removeIndex = i; + } + GUILayout.EndHorizontal(); + } + + if (removeIndex >= 0) + { + targetObjects.RemoveAt(removeIndex); + } + + if (GUILayout.Button("Add Target Object")) + { + targetObjects.Add(null); + } + + GUILayout.Space(10); + + if (GUILayout.Button("Search Materials and Textures")) + { + SearchMaterialsAndTextures(); + materialsSearched = true; + } + + GUILayout.Space(10); + + if (materialsSearched) + { + if (GUILayout.Button("Resolve Duplicated Names")) + { + ResolveDuplicatedNames(); + } + + GUILayout.Space(10); + } + + scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(300)); + + if (materialsSearched && foundMaterials.Count > 0) + { + GUILayout.Label("Remapped Materials", EditorStyles.boldLabel); + + for (int i = 0; i < foundMaterials.Count; i++) + { + GUILayout.BeginHorizontal(); + materialSelectionStatus[i] = EditorGUILayout.ToggleLeft(foundMaterials[i] ? foundMaterials[i].name : "None", materialSelectionStatus[i], GUILayout.Width(200)); + if (foundMaterials[i] != null && GUILayout.Button("Ping", GUILayout.Width(50))) + { + EditorGUIUtility.PingObject(foundMaterials[i]); + } + GUILayout.EndHorizontal(); + } + } + + GUILayout.Space(10); + + if (materialsSearched && foundTextures.Count > 0) + { + GUILayout.Label("Remapped Textures", EditorStyles.boldLabel); + + for (int i = 0; i < foundTextures.Count; i++) + { + GUILayout.BeginHorizontal(); + textureSelectionStatus[i] = EditorGUILayout.ToggleLeft(foundTextures[i] ? foundTextures[i].name : "None", textureSelectionStatus[i], GUILayout.Width(200)); + if (foundTextures[i] != null && GUILayout.Button("Ping", GUILayout.Width(50))) + { + EditorGUIUtility.PingObject(foundTextures[i]); + } + GUILayout.EndHorizontal(); + } + } + + EditorGUILayout.EndScrollView(); + + GUILayout.Space(20); + GUILayout.Label("Step 2: Select Target Folder and Move Materials and Textures", EditorStyles.boldLabel); + + GUILayout.BeginHorizontal(); + EditorGUILayout.LabelField("Folder Path:", targetFolder); + if (GUILayout.Button("Select Folder", GUILayout.Width(100))) + { + string selectedPath = EditorUtility.OpenFolderPanel("Select Target Folder", "Assets/", ""); + if (!string.IsNullOrEmpty(selectedPath)) + { + if (selectedPath.StartsWith(Application.dataPath)) + { + targetFolder = "Assets" + selectedPath.Substring(Application.dataPath.Length); + } + else + { + Debug.LogError("Please select a folder within the Assets directory."); + } + } + } + GUILayout.EndHorizontal(); + + GUILayout.Space(10); + + if (GUILayout.Button("Move Materials and Textures")) + { + MoveMaterialsAndTextures(); + } + } + + private void SearchMaterialsAndTextures() +{ + foundMaterials.Clear(); + materialSelectionStatus.Clear(); + foundTextures.Clear(); + textureSelectionStatus.Clear(); + + foreach (var obj in targetObjects) + { + if (obj == null) continue; + + Renderer[] renderers = obj.GetComponentsInChildren(); + foreach (var renderer in renderers) + { + foreach (var mat in renderer.sharedMaterials) + { + if (mat != null && !foundMaterials.Contains(mat)) + { + foundMaterials.Add(mat); + materialSelectionStatus.Add(true); + + // 모든 í…스처 검색 + Shader shader = mat.shader; + for (int j = 0; j < ShaderUtil.GetPropertyCount(shader); j++) + { + if (ShaderUtil.GetPropertyType(shader, j) == ShaderUtil.ShaderPropertyType.TexEnv) + { + string propertyName = ShaderUtil.GetPropertyName(shader, j); + Texture texture = mat.GetTexture(propertyName); + if (texture != null && !foundTextures.Contains(texture)) + { + foundTextures.Add(texture); + textureSelectionStatus.Add(true); + } + } + } + + // ì‚¬ìš©ìž ì •ì˜ ì†ì„± ì§ì ‘ 검색 + foreach (string propertyName in mat.GetTexturePropertyNames()) + { + Texture texture = mat.GetTexture(propertyName); + if (texture != null && !foundTextures.Contains(texture)) + { + foundTextures.Add(texture); + textureSelectionStatus.Add(true); + } + } + } + } + } + } + + Debug.Log("Materials and Textures found and listed."); +} + + + private void ResolveDuplicatedNames() + { + HashSet usedNames = new HashSet(); + + for (int i = 0; i < foundMaterials.Count; i++) + { + Material mat = foundMaterials[i]; + string originalName = mat.name; + int counter = 1; + + while (usedNames.Contains(mat.name)) + { + mat.name = $"{originalName}_{counter}"; + counter++; + } + + usedNames.Add(mat.name); + } + + for (int i = 0; i < foundTextures.Count; i++) + { + Texture tex = foundTextures[i]; + string originalName = tex.name; + int counter = 1; + + while (usedNames.Contains(tex.name)) + { + tex.name = $"{originalName}_{counter}"; + counter++; + } + + usedNames.Add(tex.name); + } + + Debug.Log("Duplicated names resolved."); + } + + private void MoveMaterialsAndTextures() + { + if (!AssetDatabase.IsValidFolder(targetFolder)) + { + Debug.LogError("Target folder does not exist or is invalid."); + return; + } + + for (int i = 0; i < foundMaterials.Count; i++) + { + if (!materialSelectionStatus[i]) continue; + + Material mat = foundMaterials[i]; + string path = AssetDatabase.GetAssetPath(mat); + string targetPath = Path.Combine(targetFolder, Path.GetFileName(path)); + + if (AssetDatabase.LoadAssetAtPath(targetPath) != null) + { + Debug.LogWarning($"Material '{mat.name}' already exists in the target folder. Skipping."); + continue; + } + + if (!string.IsNullOrEmpty(path)) + { + string uniquePath = AssetDatabase.GenerateUniqueAssetPath(targetPath); + AssetDatabase.MoveAsset(path, uniquePath); + } + } + + for (int i = 0; i < foundTextures.Count; i++) + { + if (!textureSelectionStatus[i]) continue; + + Texture tex = foundTextures[i]; + string path = AssetDatabase.GetAssetPath(tex); + string targetPath = Path.Combine(targetFolder, Path.GetFileName(path)); + + if (AssetDatabase.LoadAssetAtPath(targetPath) != null) + { + Debug.LogWarning($"Texture '{tex.name}' already exists in the target folder. Skipping."); + continue; + } + + if (!string.IsNullOrEmpty(path)) + { + string uniquePath = AssetDatabase.GenerateUniqueAssetPath(targetPath); + AssetDatabase.MoveAsset(path, uniquePath); + } + } + + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + Debug.Log("Selected materials and textures moved successfully."); + } +} diff --git a/Assets/Scripts/MaterialMover.cs.meta b/Assets/Scripts/MaterialMover.cs.meta new file mode 100644 index 000000000..22019621d --- /dev/null +++ b/Assets/Scripts/MaterialMover.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a4d444948c00f634bb8a74111035a4d6 \ No newline at end of file diff --git a/Assets/Scripts/NilotoonMaterialMatcapSetter.cs b/Assets/Scripts/NilotoonMaterialMatcapSetter.cs new file mode 100644 index 000000000..52bff61b0 --- /dev/null +++ b/Assets/Scripts/NilotoonMaterialMatcapSetter.cs @@ -0,0 +1,214 @@ +#if UNITY_EDITOR +using UnityEditor; +using UnityEngine; +using System.Collections.Generic; +using System.IO; + +public class NiloMaterialMatcapSetter : EditorWindow +{ + private List materials = new List(); + private Vector2 scrollPosObjects; + private bool enableBackup = true; + + private string pEnableName_Front = "_BaseMapStackingLayer"; + private string pEnableName_Back = "Enable"; + private const string targetShaderName = "lilToon"; + + [MenuItem("Tools/Nilotoon Matcap Auto Mapper", false, 153)] + public static void ShowWindow() + { + GetWindow("ë‹ë¡œíˆ° 매트캡 ìžë™ ì¸ì‹ê¸°"); + } + + void OnGUI() + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField("ë‹ë¡œíˆ° 매트캡 ìžë™ ì¸ì‹ê¸°", EditorStyles.boldLabel); + EditorGUILayout.HelpBox("릴툰ì—서 ë³€í™˜ëœ ë‹ë¡œíˆ° 머티리얼 중 누ë½ëœ Matcap 정보를 ë³µì›í•©ë‹ˆë‹¤.\nì„ íƒì— ë”°ë¼ ë°±ì—…ë³¸ì„ ìƒì„±í•©ë‹ˆë‹¤.", MessageType.Info); + + EditorGUILayout.Space(); + enableBackup = EditorGUILayout.ToggleLeft("💾 머티리얼 백업 ìƒì„± (권장)", enableBackup); + + EditorGUILayout.Space(); + EditorGUILayout.LabelField("💠 머티리얼 드래그 앤 드롭", EditorStyles.boldLabel); + Rect dropArea = GUILayoutUtility.GetRect(0, 50, GUILayout.ExpandWidth(true)); + GUI.Box(dropArea, "ì—¬ê¸°ì— ë¨¸í‹°ë¦¬ì–¼ì„ ë“œëž˜ê·¸ 하세요", EditorStyles.helpBox); + HandleDragAndDrop(dropArea); + + EditorGUILayout.Space(); + EditorGUILayout.LabelField("ðŸ“ ì¶”ê°€ëœ ë¨¸í‹°ë¦¬ì–¼ 목ë¡", EditorStyles.boldLabel); + scrollPosObjects = EditorGUILayout.BeginScrollView(scrollPosObjects, GUILayout.Height(150)); + foreach (var mat in materials) + { + EditorGUILayout.ObjectField(mat, typeof(Material), true); + } + EditorGUILayout.EndScrollView(); + + EditorGUILayout.Space(); + if (GUILayout.Button("ìžë™ 복사 실행", GUILayout.Height(30))) + { + ProcessMaterials(); + materials.Clear(); + } + } + + void HandleDragAndDrop(Rect dropArea) + { + Event evt = Event.current; + switch (evt.type) + { + case EventType.DragUpdated: + case EventType.DragPerform: + if (!dropArea.Contains(evt.mousePosition)) return; + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + + if (evt.type == EventType.DragPerform) + { + DragAndDrop.AcceptDrag(); + foreach (Object draggedObject in DragAndDrop.objectReferences) + { + if (draggedObject is Material mat && !materials.Contains(mat)) + { + materials.Add(mat); + } + } + evt.Use(); + } + break; + } + } + + void ProcessMaterials() + { + Shader lilToonShader = Shader.Find(targetShaderName); + if (lilToonShader == null) + { + Debug.LogError("lilToon Shader를 ì°¾ì„ ìˆ˜ 없습니다. 먼저 프로ì íŠ¸ì— ì¶”ê°€í•´ì£¼ì„¸ìš”."); + return; + } + + foreach (Material originalMaterial in materials) + { + if (originalMaterial == null) continue; + + if (enableBackup) + { + string originalPath = AssetDatabase.GetAssetPath(originalMaterial); + string originalDir = Path.GetDirectoryName(originalPath); + string backupDir = Path.Combine(originalDir, "M_Backup"); + + if (!Directory.Exists(backupDir)) + { + Directory.CreateDirectory(backupDir); + AssetDatabase.Refresh(); + } + + string backupPath = Path.Combine(backupDir, originalMaterial.name + "_Backup.mat").Replace("\\", "/"); + AssetDatabase.CopyAsset(originalPath, backupPath); + AssetDatabase.ImportAsset(backupPath); + Debug.Log($"백업 ìƒì„±ë¨: {backupPath}"); + } + + Material clonedMaterial = Object.Instantiate(originalMaterial); + clonedMaterial.shader = lilToonShader; + + List matcapInfoList = new List + { + GetMatcapInfoByName(clonedMaterial, "_UseMatCap", true), + GetMatcapInfoByName(clonedMaterial, "_UseMatCap2nd", false) + }; + + foreach (stMatcapInfo matcapInfo in matcapInfoList) + { + if (!matcapInfo._UseMatCap) continue; + + int targetLayerNumber = 0; + for (int i = 1; i <= 10; i++) + { + if (originalMaterial.GetFloat(pEnableName_Front + i + pEnableName_Back) < 0.5f) + { + targetLayerNumber = i; + originalMaterial.SetFloat(pEnableName_Front + i + pEnableName_Back, 1f); + break; + } + } + + if (targetLayerNumber == 0) + { + Debug.LogWarning($"{originalMaterial.name}: 사용할 수 있는 빈 ë ˆì´ì–´ê°€ 없습니다."); + continue; + } + + string prefix = pEnableName_Front + targetLayerNumber; + originalMaterial.SetVector(prefix + "TexUVCenterPivotScalePos", new Vector4(1, 1, 0, 0)); + originalMaterial.SetVector(prefix + "TexUVScaleOffset", new Vector4(1, 1, 0, 0)); + originalMaterial.SetVector(prefix + "TexUVAnimSpeed", Vector4.zero); + originalMaterial.SetVector(prefix + "MaskTexChannel", new Vector4(0, 1, 0, 0)); + originalMaterial.SetFloat(prefix + "TexUVRotatedAngle", 0); + originalMaterial.SetFloat(prefix + "TexUVRotateSpeed", 0); + originalMaterial.SetFloat(prefix + "MaskUVIndex", 0); + originalMaterial.SetFloat(prefix + "MaskInvertColor", 0); + originalMaterial.SetFloat(prefix + "TexIgnoreAlpha", 0); + originalMaterial.SetFloat(prefix + "ColorBlendMode", + matcapInfo._MatCapBlendMode == 0 ? 0 : + matcapInfo._MatCapBlendMode == 1 ? 2 : + matcapInfo._MatCapBlendMode == 2 ? 3 : + matcapInfo._MatCapBlendMode == 3 ? 4 : 5); + originalMaterial.SetTexture(prefix + "Tex", matcapInfo._MatCapTex); + originalMaterial.SetColor(prefix + "TintColor", new Color(matcapInfo._MatCapColor.r, matcapInfo._MatCapColor.g, matcapInfo._MatCapColor.b, 1f)); + originalMaterial.SetFloat(prefix + "MasterStrength", matcapInfo._MatCapColor.a); + originalMaterial.SetFloat(prefix + "TexUVIndex", 4); + originalMaterial.SetTexture(prefix + "MaskTex", matcapInfo._MatCapBlendMask); + + Debug.Log($"{originalMaterial.name}ì— Matcapì„ Layer {targetLayerNumber}ì— ì ìš©í•¨"); + } + + DestroyImmediate(clonedMaterial); + } + + AssetDatabase.SaveAssets(); + EditorUtility.DisplayDialog("Matcap 복사 완료", "모든 ë¨¸í‹°ë¦¬ì–¼ì— Matcap ì„¤ì •ì„ ì ìš©í–ˆìŠµë‹ˆë‹¤.", "확ì¸"); + } + + private struct stMatcapInfo + { + public bool _UseMatCap; + public Texture _MatCapTex; + public Color _MatCapColor; + public Texture _MatCapBlendMask; + public int _MatCapBlendMode; + + public stMatcapInfo(bool use) + { + _UseMatCap = use; + _MatCapTex = null; + _MatCapColor = Color.white; + _MatCapBlendMask = null; + _MatCapBlendMode = 0; + } + + public stMatcapInfo(bool use, Texture tex, Color color, Texture mask, int mode) + { + _UseMatCap = use; + _MatCapTex = tex; + _MatCapColor = color; + _MatCapBlendMask = mask; + _MatCapBlendMode = mode; + } + } + + private stMatcapInfo GetMatcapInfoByName(Material mat, string propertyName, bool isFirst) + { + string suffix = isFirst ? "" : "2nd"; + if (mat.HasProperty(propertyName) && mat.GetInt(propertyName) == 1) + { + return new stMatcapInfo(true, + mat.GetTexture("_MatCap" + suffix + "Tex"), + mat.GetColor("_MatCap" + suffix + "Color"), + mat.GetTexture("_MatCap" + suffix + "BlendMask"), + mat.GetInt("_MatCap" + suffix + "BlendMode")); + } + return new stMatcapInfo(false); + } +} +#endif diff --git a/Assets/Scripts/NilotoonMaterialMatcapSetter.cs.meta b/Assets/Scripts/NilotoonMaterialMatcapSetter.cs.meta new file mode 100644 index 000000000..ecf86e7c8 --- /dev/null +++ b/Assets/Scripts/NilotoonMaterialMatcapSetter.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7a6ca025d3c26104d888d49ec66215df \ No newline at end of file diff --git a/Assets/Scripts/ObjectNameChanger.cs b/Assets/Scripts/ObjectNameChanger.cs new file mode 100644 index 000000000..c68c0f879 --- /dev/null +++ b/Assets/Scripts/ObjectNameChanger.cs @@ -0,0 +1,198 @@ +// ... existing code ... +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +public class ObjectNameModifier : EditorWindow +{ + private string prefixText = string.Empty; + private string suffixText = string.Empty; + + private GameObject rootObject; + private Dictionary> duplicateGroups = new(); + private Vector2 scroll; + + [MenuItem("Tools/Object Name Modifier")] + public static void ShowWindow() + { + GetWindow("Object Name Modifier"); + } + + private void OnGUI() + { + GUILayout.Label("Modify Object Names", EditorStyles.boldLabel); + + prefixText = EditorGUILayout.TextField("Prefix", prefixText); + suffixText = EditorGUILayout.TextField("Suffix", suffixText); + + if (GUILayout.Button("Apply Prefix and Suffix")) + ApplyPrefixAndSuffix(); + + GUILayout.Space(5); + + if (GUILayout.Button("Remove First Character")) + RemoveFirstCharacter(); + + if (GUILayout.Button("Remove Last Character")) + RemoveLastCharacter(); + + GUILayout.Space(5); + + if (GUILayout.Button("Replace Spaces with Underscores")) + ReplaceSpacesWithUnderscores(); + + GUILayout.Space(5); + + // ▼▼▼ ì¶”ê°€ëœ ë¶€ë¶„: 하위 오브ì íЏ ì´ë¦„순 ì •ë ¬ 버튼 ▼▼▼ + if (GUILayout.Button("Sort Children by Name (A-Z)") && Selection.activeGameObject != null) + { + SortChildrenByName(Selection.activeGameObject); + } + // ▲▲▲ ì¶”ê°€ëœ ë¶€ë¶„ ë ▲▲▲ + + GUILayout.Space(20); + EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); + + GUILayout.Label("Find and Fix Duplicate Names", EditorStyles.boldLabel); + + rootObject = (GameObject)EditorGUILayout.ObjectField("Target Root Object", rootObject, typeof(GameObject), true); + + if (GUILayout.Button("Find Duplicate Names") && rootObject != null) + { + FindDuplicateNames(rootObject); + } + + if (duplicateGroups.Count > 0) + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Duplicate Name List", EditorStyles.boldLabel); + scroll = EditorGUILayout.BeginScrollView(scroll, GUILayout.Height(200)); + + foreach (var kvp in duplicateGroups) + { + EditorGUILayout.LabelField($"{kvp.Key} ({kvp.Value.Count} items)"); + foreach (var t in kvp.Value) + { + EditorGUILayout.ObjectField(" ↳", t, typeof(Transform), true); + } + } + + EditorGUILayout.EndScrollView(); + + if (GUILayout.Button("Auto-Rename Duplicates")) + { + RenameDuplicates(); + } + } + else if (rootObject != null) + { + EditorGUILayout.HelpBox("No duplicate names found.", MessageType.Info); + } + } + + void ApplyPrefixAndSuffix() + { + foreach (GameObject obj in Selection.gameObjects) + { + Undo.RecordObject(obj, "Change Object Name"); + obj.name = prefixText + obj.name + suffixText; + } + } + + void RemoveFirstCharacter() + { + foreach (GameObject obj in Selection.gameObjects) + { + if (obj.name.Length > 0) + { + Undo.RecordObject(obj, "Remove First Character"); + obj.name = obj.name.Substring(1); + } + } + } + + void RemoveLastCharacter() + { + foreach (GameObject obj in Selection.gameObjects) + { + if (obj.name.Length > 0) + { + Undo.RecordObject(obj, "Remove Last Character"); + obj.name = obj.name.Substring(0, obj.name.Length - 1); + } + } + } + + void ReplaceSpacesWithUnderscores() + { + foreach (GameObject obj in Selection.gameObjects) + { + Undo.RecordObject(obj, "Replace Spaces"); + obj.name = obj.name.Replace(" ", "_"); + } + } + + void FindDuplicateNames(GameObject root) + { + duplicateGroups.Clear(); + Dictionary> nameMap = new(); + + foreach (Transform t in root.GetComponentsInChildren(true)) + { + if (!nameMap.ContainsKey(t.name)) + nameMap[t.name] = new List(); + + nameMap[t.name].Add(t); + } + + foreach (var kvp in nameMap) + { + if (kvp.Value.Count > 1) + { + duplicateGroups[kvp.Key] = kvp.Value; + } + } + } + + void RenameDuplicates() + { + foreach (var kvp in duplicateGroups) + { + for (int i = 0; i < kvp.Value.Count; i++) + { + string newName = (i == 0) ? kvp.Key : $"{kvp.Key}_{i}"; + Undo.RecordObject(kvp.Value[i], "Rename Duplicate"); + kvp.Value[i].name = newName; + } + } + + Debug.Log("Duplicate names have been renamed."); + FindDuplicateNames(rootObject); // 재검사 + } + + // ▼▼▼ ìˆ˜ì •ëœ ë¶€ë¶„: 하위 오브ì íЏ ì´ë¦„순 ì •ë ¬ 함수 ▼▼▼ + void SortChildrenByName(GameObject parent) + { + if (parent == null) return; + + // 하위 오브ì íЏ 리스트 가져오기 + List children = new List(); + for (int i = 0; i < parent.transform.childCount; i++) + { + children.Add(parent.transform.GetChild(i)); + } + + // 유니티 기본 ì •ë ¬ 순서로 ì •ë ¬ (ëŒ€ì†Œë¬¸ìž êµ¬ë¶„ ì—†ìŒ, ìžì—°ìŠ¤ëŸ¬ìš´ ìˆ«ìž ì •ë ¬) + children.Sort((a, b) => EditorUtility.NaturalCompare(a.name, b.name)); + + // ì •ë ¬ëœ ìˆœì„œëŒ€ë¡œ SiblingIndex 재설정 + for (int i = 0; i < children.Count; i++) + { + Undo.SetTransformParent(children[i], parent.transform, "Sort Children By Name"); + children[i].SetSiblingIndex(i); + } + + Debug.Log($"{parent.name}ì˜ í•˜ìœ„ 오브ì íŠ¸ë“¤ì´ ì´ë¦„순으로 ì •ë ¬ë˜ì—ˆìŠµë‹ˆë‹¤."); + } + // ▲▲▲ ìˆ˜ì •ëœ ë¶€ë¶„ ë ▲▲▲ +} \ No newline at end of file diff --git a/Assets/Scripts/ObjectNameChanger.cs.meta b/Assets/Scripts/ObjectNameChanger.cs.meta new file mode 100644 index 000000000..e8dfd1b52 --- /dev/null +++ b/Assets/Scripts/ObjectNameChanger.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4f2fd58d6ba387840b8dd2ec22178efc \ No newline at end of file diff --git a/Assets/Scripts/QA_Select.cs b/Assets/Scripts/QA_Select.cs new file mode 100644 index 000000000..0cbb2984f --- /dev/null +++ b/Assets/Scripts/QA_Select.cs @@ -0,0 +1,47 @@ +using UnityEngine; +using UnityEditor; + +public class ParentChildSelectionTool : EditorWindow +{ + [MenuItem("Tools/Select Parent %q")] // Q 키 (Ctrl/Command+Q)로 ìƒìœ„ 오브ì íЏ ì„ íƒ + private static void SelectParent() + { + if (Selection.activeGameObject != null) + { + Transform selectedTransform = Selection.activeGameObject.transform; + if (selectedTransform.parent != null) + { + Selection.activeGameObject = selectedTransform.parent.gameObject; + } + else + { + Debug.Log("No parent object found."); + } + } + else + { + Debug.Log("No object selected."); + } + } + + [MenuItem("Tools/Select Child %a")] // A 키 (Ctrl/Command+A)로 하위 오브ì íЏ ì„ íƒ + private static void SelectChild() + { + if (Selection.activeGameObject != null) + { + Transform selectedTransform = Selection.activeGameObject.transform; + if (selectedTransform.childCount > 0) + { + Selection.activeGameObject = selectedTransform.GetChild(0).gameObject; + } + else + { + Debug.Log("No child object found."); + } + } + else + { + Debug.Log("No object selected."); + } + } +} diff --git a/Assets/Scripts/QA_Select.cs.meta b/Assets/Scripts/QA_Select.cs.meta new file mode 100644 index 000000000..2b7895849 --- /dev/null +++ b/Assets/Scripts/QA_Select.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf82a01a2d2362a459389171c4b3cb1d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/RecompileScript.cs b/Assets/Scripts/RecompileScript.cs new file mode 100644 index 000000000..b4629467d --- /dev/null +++ b/Assets/Scripts/RecompileScript.cs @@ -0,0 +1,12 @@ +using UnityEditor; + +public class RecompileScript +{ + [MenuItem("Tools/Recompile")] + public static void Recompile() + { + // í˜„ìž¬ì˜ ì—디터 애플리케ì´ì…˜ì˜ ìƒíƒœë¥¼ 강제로 리컴파ì¼í•©ë‹ˆë‹¤. + AssetDatabase.Refresh(); + EditorUtility.RequestScriptReload(); + } +} diff --git a/Assets/Scripts/RecompileScript.cs.meta b/Assets/Scripts/RecompileScript.cs.meta new file mode 100644 index 000000000..1039f95db --- /dev/null +++ b/Assets/Scripts/RecompileScript.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c82283c20c563fa4aba64e0e6cb93aad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/RenameHumanoidBones.cs b/Assets/Scripts/RenameHumanoidBones.cs new file mode 100644 index 000000000..ef006f7f7 --- /dev/null +++ b/Assets/Scripts/RenameHumanoidBones.cs @@ -0,0 +1,127 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +public class RenameHumanoidBones : EditorWindow +{ + private Animator selectedAnimator; + private Dictionary humanoidBones = new Dictionary(); + private Dictionary newBoneNames = new Dictionary(); + + [MenuItem("Tools/Humanoid Bone Renamer")] + public static void ShowWindow() + { + GetWindow("Humanoid Bone Renamer"); + } + + private Vector2 scrollPosition; + + private void OnGUI() + { + GUILayout.Label("Humanoid Bone Renamer", EditorStyles.boldLabel); + + if (GUILayout.Button("Find Humanoid Bones")) + { + FindHumanoidBones(); + } + + if (selectedAnimator == null) + { + GUILayout.Label("No valid Humanoid Animator selected.", EditorStyles.helpBox); + return; + } + + GUILayout.Label("Selected GameObject: " + selectedAnimator.gameObject.name, EditorStyles.boldLabel); + + if (humanoidBones.Count > 0) + { + scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.Height(400)); + + EditorGUILayout.BeginVertical("box"); + GUILayout.Label("Humanoid Bones", EditorStyles.boldLabel); + + foreach (var bone in humanoidBones) + { + EditorGUILayout.BeginHorizontal(); + + // First column: Unity's Humanoid bone name + GUILayout.Label(bone.Key.ToString(), GUILayout.Width(150)); + + // Second column: Current bone name + GUILayout.Label(bone.Value != null ? bone.Value.name : "None", GUILayout.Width(150)); + + // Third column: Input field for new name (defaulting to the first column's name) + if (!newBoneNames.ContainsKey(bone.Key)) + { + newBoneNames[bone.Key] = bone.Key.ToString(); + } + newBoneNames[bone.Key] = EditorGUILayout.TextField(newBoneNames[bone.Key], GUILayout.Width(150)); + + EditorGUILayout.EndHorizontal(); + } + + EditorGUILayout.EndVertical(); + EditorGUILayout.EndScrollView(); + } + + if (GUILayout.Button("Change Humanoid Bones Name")) + { + ChangeHumanoidBoneNames(); + } + } + + private void FindHumanoidBones() + { + selectedAnimator = null; + humanoidBones.Clear(); + newBoneNames.Clear(); + + if (Selection.activeGameObject == null) + { + Debug.LogError("No GameObject selected. Please select a GameObject with an Animator component."); + return; + } + + selectedAnimator = Selection.activeGameObject.GetComponent(); + + if (selectedAnimator == null || selectedAnimator.avatar == null || !selectedAnimator.avatar.isValid || !selectedAnimator.avatar.isHuman) + { + Debug.LogError("Selected GameObject does not have a valid Humanoid Avatar."); + return; + } + + for (int i = 0; i < HumanTrait.BoneCount; i++) + { + HumanBodyBones bone = (HumanBodyBones)i; + Transform boneTransform = selectedAnimator.GetBoneTransform(bone); + + if (boneTransform != null) + { + humanoidBones[bone] = boneTransform; + } + } + + Debug.Log("Humanoid bones found and ready for renaming."); + } + + private void ChangeHumanoidBoneNames() + { + if (selectedAnimator == null) + { + Debug.LogError("No valid Humanoid Animator selected."); + return; + } + + foreach (var bone in humanoidBones) + { + if (bone.Value != null && !string.IsNullOrWhiteSpace(newBoneNames[bone.Key])) + { + string newName = newBoneNames[bone.Key]; + Debug.Log($"Renaming {bone.Value.name} to {newName}"); + bone.Value.name = newName; + } + } + + Debug.Log("Bone renaming completed."); + } +} diff --git a/Assets/Scripts/RenameHumanoidBones.cs.meta b/Assets/Scripts/RenameHumanoidBones.cs.meta new file mode 100644 index 000000000..9816919ca --- /dev/null +++ b/Assets/Scripts/RenameHumanoidBones.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 86b446ef6d092de4e870cee0521f2f16 \ No newline at end of file diff --git a/Assets/Scripts/SkyboxRotator.meta b/Assets/Scripts/SkyboxRotator.meta new file mode 100644 index 000000000..9051a0490 --- /dev/null +++ b/Assets/Scripts/SkyboxRotator.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 43a657b728255c94e9fec7cb53b3f1c0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/SkyboxRotator/SkyboxRotator.cs b/Assets/Scripts/SkyboxRotator/SkyboxRotator.cs new file mode 100644 index 000000000..7567fcba2 --- /dev/null +++ b/Assets/Scripts/SkyboxRotator/SkyboxRotator.cs @@ -0,0 +1,44 @@ +using UnityEngine; + +[ExecuteInEditMode] +public class SkyboxRotator : MonoBehaviour +{ + // Skyboxì˜ íšŒì „ ì†ë„를 설정할 수 있는 공개 변수 + [Range(0f, 360f)] public float rotationSpeed = 10f; + + // Skybox ìž¬ì§ˆì„ ì§ì ‘ 지정할 수 있는 옵션 + public Material customSkyboxMaterial; + + // 현재 씬ì—서 ì ìš©ëœ Skyboxì˜ íšŒì „ ê°ë„ + private float skyboxRotation; + + void Start() + { + // ì”¬ì— ì ìš©ëœ Skyboxê°€ 없고, ì‚¬ìš©ìž ì •ì˜ Skyboxê°€ 설정ë˜ì–´ 있으면 ì ìš© + if (RenderSettings.skybox == null && customSkyboxMaterial != null) + { + RenderSettings.skybox = customSkyboxMaterial; + } + } + + // Skybox íšŒì „ì„ ìœ„í•œ 함수 + void Update() + { + // Skybox를 회전시키는 ë¡œì§ + skyboxRotation += rotationSpeed * Time.deltaTime; + if (skyboxRotation > 360f) + { + skyboxRotation -= 360f; + } + + // Skybox 회전 ê°’ ì ìš© + RenderSettings.skybox.SetFloat("_Rotation", skyboxRotation); + } + + // 외부ì—서 Skybox 회전 ê°’ì„ ìˆ˜ë™ìœ¼ë¡œ 설정하는 함수 (예: Timelineì—서 사용) + public void SetSkyboxRotation(float rotation) + { + skyboxRotation = rotation; + RenderSettings.skybox.SetFloat("_Rotation", skyboxRotation); + } +} diff --git a/Assets/Scripts/SkyboxRotator/SkyboxRotator.cs.meta b/Assets/Scripts/SkyboxRotator/SkyboxRotator.cs.meta new file mode 100644 index 000000000..7354f19ce --- /dev/null +++ b/Assets/Scripts/SkyboxRotator/SkyboxRotator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1d37f069f3e29674d9516f924caf1c62 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/TimelineStopper.meta b/Assets/Scripts/TimelineStopper.meta new file mode 100644 index 000000000..e1e9d72c6 --- /dev/null +++ b/Assets/Scripts/TimelineStopper.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9b3f4eb8287fd1f4c927a85d12b166da +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/TimelineStopper/Notification Receiver.cs b/Assets/Scripts/TimelineStopper/Notification Receiver.cs new file mode 100644 index 000000000..9a2e6a9b6 --- /dev/null +++ b/Assets/Scripts/TimelineStopper/Notification Receiver.cs @@ -0,0 +1,32 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.Playables; +using UnityEngine.Timeline; + +public class PauseMarkerReceiver : MonoBehaviour, INotificationReceiver +{ + private PlayableDirector director; + private bool isPaused = false; + + private void Awake() + { + director = GetComponent(); + } + + public void OnNotify(Playable origin, INotification notification, object context) + { + if (notification is PauseMarker pauseMarker && !isPaused) + { + StartCoroutine(PauseAndResume(pauseMarker.pauseDuration)); + } + } + + private IEnumerator PauseAndResume(float duration) + { + isPaused = true; + director.Pause(); // ìž¬ìƒ ì¼ì‹œì •ì§€ + yield return new WaitForSecondsRealtime(duration); // 실제 시간 기준 대기 + director.Play(); // ìž¬ìƒ ìž¬ê°œ + isPaused = false; + } +} diff --git a/Assets/Scripts/TimelineStopper/Notification Receiver.cs.meta b/Assets/Scripts/TimelineStopper/Notification Receiver.cs.meta new file mode 100644 index 000000000..65869c0be --- /dev/null +++ b/Assets/Scripts/TimelineStopper/Notification Receiver.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9b954343938352d409bf3f8f32c6c46a \ No newline at end of file diff --git a/Assets/Scripts/TimelineStopper/PauseMarker.cs b/Assets/Scripts/TimelineStopper/PauseMarker.cs new file mode 100644 index 000000000..b8feabaed --- /dev/null +++ b/Assets/Scripts/TimelineStopper/PauseMarker.cs @@ -0,0 +1,10 @@ +using UnityEngine; +using UnityEngine.Playables; +using UnityEngine.Timeline; + +[System.Serializable] +public class PauseMarker : Marker, INotification +{ + public PropertyName id => new PropertyName(); + public float pauseDuration = 1f; // 멈출 시간 (ì´ˆ) +} diff --git a/Assets/Scripts/TimelineStopper/PauseMarker.cs.meta b/Assets/Scripts/TimelineStopper/PauseMarker.cs.meta new file mode 100644 index 000000000..49329bc66 --- /dev/null +++ b/Assets/Scripts/TimelineStopper/PauseMarker.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a96294be1db2931488c44999754415c2 \ No newline at end of file diff --git a/Assets/Settings/DefaultVolumeProfile.asset b/Assets/Settings/DefaultVolumeProfile.asset new file mode 100644 index 000000000..2ee4bde52 --- /dev/null +++ b/Assets/Settings/DefaultVolumeProfile.asset @@ -0,0 +1,1832 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-9167874883656233139 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 5485954d14dfb9a4c8ead8edb0ded5b1, type: 3} + m_Name: LiftGammaGain + m_EditorClassIdentifier: + active: 1 + lift: + m_OverrideState: 1 + m_Value: {x: 1, y: 1, z: 1, w: 0} + gamma: + m_OverrideState: 1 + m_Value: {x: 1, y: 1, z: 1, w: 0} + gain: + m_OverrideState: 1 + m_Value: {x: 1, y: 1, z: 1, w: 0} +--- !u!114 &-8270506406425502121 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 70afe9e12c7a7ed47911bb608a23a8ff, type: 3} + m_Name: SplitToning + m_EditorClassIdentifier: + active: 1 + shadows: + m_OverrideState: 1 + m_Value: {r: 0.5, g: 0.5, b: 0.5, a: 1} + highlights: + m_OverrideState: 1 + m_Value: {r: 0.5, g: 0.5, b: 0.5, a: 1} + balance: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-8104416584915340131 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 0} + m_Name: CopyPasteTestComponent2 + m_EditorClassIdentifier: Unity.RenderPipelines.Core.Editor.Tests:UnityEditor.Rendering.Tests:VolumeComponentCopyPasteTests/CopyPasteTestComponent2 + active: 1 + p1: + m_OverrideState: 1 + m_Value: 0 + p2: + m_OverrideState: 1 + m_Value: 0 + p21: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-7750755424749557576 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 60f3b30c03e6ba64d9a27dc9dba8f28d, type: 3} + m_Name: OutlineVolumeComponent + m_EditorClassIdentifier: + active: 1 + Enabled: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-7743500325797982168 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: ccf1aba9553839d41ae37dd52e9ebcce, type: 3} + m_Name: MotionBlur + m_EditorClassIdentifier: + active: 1 + mode: + m_OverrideState: 1 + m_Value: 0 + quality: + m_OverrideState: 1 + m_Value: 0 + intensity: + m_OverrideState: 1 + m_Value: 0 + clamp: + m_OverrideState: 1 + m_Value: 0.05 +--- !u!114 &-7274224791359825572 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 0fd9ee276a1023e439cf7a9c393195fa, type: 3} + m_Name: TestAnimationCurveVolumeComponent + m_EditorClassIdentifier: + active: 1 + testParameter: + m_OverrideState: 1 + m_Value: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0.5 + value: 10 + inSlope: 0 + outSlope: 10 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 15 + inSlope: 10 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!114 &-6848783720466317983 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 87db17722cc284a4a82f8563727fc49b, type: 3} + m_Name: NiloToonScreenSpaceOutlineV2ControlVolume + m_EditorClassIdentifier: + active: 1 + intensity: + m_OverrideState: 1 + m_Value: 0 + intensityForCharacter: + m_OverrideState: 1 + m_Value: 1 + intensityForEnvironment: + m_OverrideState: 1 + m_Value: 1 + widthMultiplier: + m_OverrideState: 1 + m_Value: 1 + widthMultiplierForCharacter: + m_OverrideState: 1 + m_Value: 1 + widthMultiplierForEnvironment: + m_OverrideState: 1 + m_Value: 1 + extraWidthMultiplierForXR: + m_OverrideState: 1 + m_Value: 0.2 + outlineTintColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + outlineTintColorForChar: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + outlineTintColorForEnvi: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + drawGeometryEdgeOutline: + m_OverrideState: 1 + m_Value: 1 + drawGeometryEdgeOutlineForChar: + m_OverrideState: 1 + m_Value: 1 + drawGeometryEdgeOutlineForEnvi: + m_OverrideState: 1 + m_Value: 1 + geometryEdgeThreshold: + m_OverrideState: 1 + m_Value: 1 + geometryEdgeThresholdForCharacter: + m_OverrideState: 1 + m_Value: 1 + geometryEdgeThresholdForEnvironment: + m_OverrideState: 1 + m_Value: 1 + drawNormalAngleOutline: + m_OverrideState: 1 + m_Value: 1 + drawNormalAngleOutlineForChar: + m_OverrideState: 1 + m_Value: 1 + drawNormalAngleOutlineForEnvi: + m_OverrideState: 1 + m_Value: 1 + normalAngleMin: + m_OverrideState: 1 + m_Value: 40 + normalAngleMinForCharacter: + m_OverrideState: 1 + m_Value: 40 + normalAngleMinForEnvironment: + m_OverrideState: 1 + m_Value: 40 + normalAngleMax: + m_OverrideState: 1 + m_Value: 180 + normalAngleMaxForCharacter: + m_OverrideState: 1 + m_Value: 180 + normalAngleMaxForEnvironment: + m_OverrideState: 1 + m_Value: 180 + drawMaterialBoundaryOutline: + m_OverrideState: 1 + m_Value: 1 + drawCustomIDBoundaryOutline: + m_OverrideState: 1 + m_Value: 1 + drawWireframeOutline: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-6453909008720401061 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 4a104dcd31bca784aaed640904c00a0b, type: 3} + m_Name: NiloToonCharRenderingControlVolume + m_EditorClassIdentifier: + active: 1 + charBaseColorMultiply: + m_OverrideState: 1 + m_Value: 1 + charBaseColorTintColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + charMulColorIntensity: + m_OverrideState: 1 + m_Value: 1 + charMulColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + charLerpColorUsage: + m_OverrideState: 1 + m_Value: 0 + charLerpColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 0} + charOcclusionUsage: + m_OverrideState: 1 + m_Value: 1 + charIndirectLightMultiplier: + m_OverrideState: 1 + m_Value: 1 + charIndirectLightMinColor: + m_OverrideState: 1 + m_Value: {r: 0.01, g: 0.01, b: 0.01, a: 0} + charIndirectLightMaxColor: + m_OverrideState: 1 + m_Value: {r: 0.5, g: 0.5, b: 0.5, a: 1} + mainDirectionalLightIntensityMultiplier: + m_OverrideState: 1 + m_Value: 1 + mainDirectionalLightIntensityMultiplierColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + addMainLightColor: + m_OverrideState: 1 + m_Value: {r: 0, g: 0, b: 0, a: 1} + mainDirectionalLightMaxContribution: + m_OverrideState: 1 + m_Value: 1 + mainDirectionalLightMaxContributionColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + overrideLightDirectionIntensity: + m_OverrideState: 1 + m_Value: 0 + overridedLightUpDownAngle: + m_OverrideState: 1 + m_Value: -45 + overridedLightLRAngle: + m_OverrideState: 1 + m_Value: 0 + lightColorOverrideStrength: + m_OverrideState: 1 + m_Value: 0 + overridedLightColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + desaturateLightColor: + m_OverrideState: 1 + m_Value: 0 + additionalLightIntensityMultiplier: + m_OverrideState: 1 + m_Value: 1 + additionalLightIntensityMultiplierColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + additionalLightIntensityMultiplierForFaceArea: + m_OverrideState: 1 + m_Value: 1 + additionalLightIntensityMultiplierColorForFaceArea: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + additionalLightIntensityMultiplierForOutlineArea: + m_OverrideState: 1 + m_Value: 1 + additionalLightIntensityMultiplierColorForOutlineArea: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + additionalLightApplyRimMask: + m_OverrideState: 1 + m_Value: 0 + additionalLightRimMaskPower: + m_OverrideState: 1 + m_Value: 1 + additionalLightRimMaskSoftness: + m_OverrideState: 1 + m_Value: 1 + additionalLightMaxContribution: + m_OverrideState: 1 + m_Value: 1 + additionalLightMaxContributionColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + specularIntensityMultiplier: + m_OverrideState: 1 + m_Value: 1 + specularTintColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 0} + specularInShadowMinIntensity: + m_OverrideState: 1 + m_Value: 0.25 + specularReactToLightDirectionChange: + m_OverrideState: 1 + m_Value: 1 + depthTextureRimLightAndShadowWidthMultiplier: + m_OverrideState: 1 + m_Value: 1 + charRimLightMultiplier: + m_OverrideState: 1 + m_Value: 1 + charRimLightTintColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 0} + charRimLightMultiplierForOutlineArea: + m_OverrideState: 1 + m_Value: 0 + charRimLightTintColorForOutlineArea: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 0} + depthTexRimLightDepthDiffThresholdOffset: + m_OverrideState: 1 + m_Value: 0 + charRimLightCameraDistanceFadeoutStartDistance: + m_OverrideState: 1 + m_Value: 1000 + charRimLightCameraDistanceFadeoutEndDistance: + m_OverrideState: 1 + m_Value: 2000 + characterOverallShadowStrength: + m_OverrideState: 1 + m_Value: 1 + characterOverallShadowTintColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 0} + charOutlineWidthMultiplier: + m_OverrideState: 1 + m_Value: 1 + charOutlineWidthExtraMultiplierForXR: + m_OverrideState: 1 + m_Value: 0.5 + charOutlineWidthAutoAdjustToCameraDistanceAndFOV: + m_OverrideState: 1 + m_Value: 1 + charOutlineMulColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} +--- !u!114 &-6335409530604852063 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 66f335fb1ffd8684294ad653bf1c7564, type: 3} + m_Name: ColorAdjustments + m_EditorClassIdentifier: + active: 1 + postExposure: + m_OverrideState: 1 + m_Value: 0 + contrast: + m_OverrideState: 1 + m_Value: 0 + colorFilter: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + hueShift: + m_OverrideState: 1 + m_Value: 0 + saturation: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-6288072647309666549 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 29fa0085f50d5e54f8144f766051a691, type: 3} + m_Name: FilmGrain + m_EditorClassIdentifier: + active: 1 + type: + m_OverrideState: 1 + m_Value: 0 + intensity: + m_OverrideState: 1 + m_Value: 0 + response: + m_OverrideState: 1 + m_Value: 0.8 + texture: + m_OverrideState: 1 + m_Value: {fileID: 0} +--- !u!114 &-6034333096595414194 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 5a00a63fdd6bd2a45ab1f2d869305ffd, type: 3} + m_Name: OasisFogVolumeComponent + m_EditorClassIdentifier: + active: 1 + Density: + m_OverrideState: 1 + m_Value: 0 + StartDistance: + m_OverrideState: 1 + m_Value: 0 + HeightRange: + m_OverrideState: 1 + m_Value: {x: 0, y: 50} + Tint: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + SunScatteringIntensity: + m_OverrideState: 1 + m_Value: 2 +--- !u!114 &-5520245016509672950 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 97c23e3b12dc18c42a140437e53d3951, type: 3} + m_Name: Tonemapping + m_EditorClassIdentifier: + active: 1 + mode: + m_OverrideState: 1 + m_Value: 0 + neutralHDRRangeReductionMode: + m_OverrideState: 1 + m_Value: 2 + acesPreset: + m_OverrideState: 1 + m_Value: 3 + hueShiftAmount: + m_OverrideState: 1 + m_Value: 0 + detectPaperWhite: + m_OverrideState: 1 + m_Value: 0 + paperWhite: + m_OverrideState: 1 + m_Value: 300 + detectBrightnessLimits: + m_OverrideState: 1 + m_Value: 1 + minNits: + m_OverrideState: 1 + m_Value: 0.005 + maxNits: + m_OverrideState: 1 + m_Value: 1000 +--- !u!114 &-5433043836740020232 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: d89c46e6b4f031541986f8d6bdbad145, type: 3} + m_Name: NiloToonCinematicRimLightVolume + m_EditorClassIdentifier: + active: 1 + strengthRimMask2D: + m_OverrideState: 1 + m_Value: 0 + strengthRimMask3D_ClassicStyle: + m_OverrideState: 1 + m_Value: 0 + strengthRimMask3D_DynmaicStyle: + m_OverrideState: 1 + m_Value: 0 + sharpnessRimMask3D_DynamicStyle: + m_OverrideState: 1 + m_Value: 0.375 + strengthRimMask3D_StableStyle: + m_OverrideState: 1 + m_Value: 0 + sharpnessRimMask3D_StableStyle: + m_OverrideState: 1 + m_Value: 0.5 + lightIntensityMultiplier: + m_OverrideState: 1 + m_Value: 1 + tintBaseMap: + m_OverrideState: 1 + m_Value: 0.5 + enableStyleSafeGuard: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &-5360449096862653589 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 0} + m_Name: VolumeComponentSupportedEverywhere + m_EditorClassIdentifier: Unity.RenderPipelines.Core.Editor.Tests:UnityEngine.Rendering.Tests:VolumeComponentEditorSupportedOnTests/VolumeComponentSupportedEverywhere + active: 1 +--- !u!114 &-5139089513906902183 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 5a00a63fdd6bd2a45ab1f2d869305ffd, type: 3} + m_Name: OasisFogVolumeComponent + m_EditorClassIdentifier: + active: 1 + Density: + m_OverrideState: 1 + m_Value: 0 + StartDistance: + m_OverrideState: 1 + m_Value: 0 + HeightRange: + m_OverrideState: 1 + m_Value: {x: 0, y: 50} + Tint: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + SunScatteringIntensity: + m_OverrideState: 1 + m_Value: 2 +--- !u!114 &-4463884970436517307 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: fb60a22f311433c4c962b888d1393f88, type: 3} + m_Name: PaniniProjection + m_EditorClassIdentifier: + active: 1 + distance: + m_OverrideState: 1 + m_Value: 0 + cropToFit: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &-4337935226145447908 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 853cfdf4b80146545b90713442d462cf, type: 3} + m_Name: NiloToonAdditionalLightStyleVolume + m_EditorClassIdentifier: + active: 1 + additionalLightInjectIntoMainLightColor_Strength: + m_OverrideState: 1 + m_Value: 1 + additionalLightInjectIntoMainLightDirection_Strength: + m_OverrideState: 1 + m_Value: 1 + additionalLightInjectIntoMainLightColor_Desaturate: + m_OverrideState: 1 + m_Value: 0 + additionalLightInjectIntoMainLightColor_AllowCloseLightOverBright: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &-3193994094532107207 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: eecc32444ea4503479fa0394f277db7d, type: 3} + m_Name: NiloToonScreenSpaceOutlineControlVolume + m_EditorClassIdentifier: + active: 1 + intensity: + m_OverrideState: 1 + m_Value: 0 + intensityForCharacter: + m_OverrideState: 1 + m_Value: 1 + intensityForEnvironment: + m_OverrideState: 1 + m_Value: 1 + widthMultiplier: + m_OverrideState: 1 + m_Value: 1 + widthMultiplierForCharacter: + m_OverrideState: 1 + m_Value: 1 + widthMultiplierForEnvironment: + m_OverrideState: 1 + m_Value: 1 + extraWidthMultiplierForXR: + m_OverrideState: 1 + m_Value: 0.2 + normalsSensitivityOffset: + m_OverrideState: 1 + m_Value: 0 + normalsSensitivityOffsetForCharacter: + m_OverrideState: 1 + m_Value: 0 + normalsSensitivityOffsetForEnvironment: + m_OverrideState: 1 + m_Value: 0 + depthSensitivityOffset: + m_OverrideState: 1 + m_Value: 0 + depthSensitivityOffsetForCharacter: + m_OverrideState: 1 + m_Value: 0 + depthSensitivityOffsetForEnvironment: + m_OverrideState: 1 + m_Value: 0 + depthSensitivityDistanceFadeoutStrength: + m_OverrideState: 1 + m_Value: 1 + depthSensitivityDistanceFadeoutStrengthForCharacter: + m_OverrideState: 1 + m_Value: 1 + depthSensitivityDistanceFadeoutStrengthForEnvironment: + m_OverrideState: 1 + m_Value: 1 + outlineTintColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + outlineTintColorForChar: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + outlineTintColorForEnvi: + m_OverrideState: 1 + m_Value: {r: 0.12, g: 0.12, b: 0.12, a: 1} +--- !u!114 &-1410297666881709256 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 6bd486065ce11414fa40e631affc4900, type: 3} + m_Name: ProbeVolumesOptions + m_EditorClassIdentifier: + active: 1 + normalBias: + m_OverrideState: 1 + m_Value: 0.33 + viewBias: + m_OverrideState: 1 + m_Value: 0 + scaleBiasWithMinProbeDistance: + m_OverrideState: 1 + m_Value: 0 + samplingNoise: + m_OverrideState: 1 + m_Value: 0.1 + animateSamplingNoise: + m_OverrideState: 1 + m_Value: 1 + leakReductionMode: + m_OverrideState: 1 + m_Value: 1 + minValidDotProductValue: + m_OverrideState: 1 + m_Value: 0.1 + occlusionOnlyReflectionNormalization: + m_OverrideState: 1 + m_Value: 1 + intensityMultiplier: + m_OverrideState: 1 + m_Value: 1 + skyOcclusionIntensityMultiplier: + m_OverrideState: 1 + m_Value: 1 + worldOffset: + m_OverrideState: 1 + m_Value: {x: 0, y: 0, z: 0} +--- !u!114 &-1216621516061285780 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 0b2db86121404754db890f4c8dfe81b2, type: 3} + m_Name: Bloom + m_EditorClassIdentifier: + active: 1 + skipIterations: + m_OverrideState: 1 + m_Value: 1 + threshold: + m_OverrideState: 1 + m_Value: 0.9 + intensity: + m_OverrideState: 1 + m_Value: 0 + scatter: + m_OverrideState: 1 + m_Value: 0.7 + clamp: + m_OverrideState: 1 + m_Value: 65472 + tint: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + highQualityFiltering: + m_OverrideState: 1 + m_Value: 0 + downscale: + m_OverrideState: 1 + m_Value: 0 + maxIterations: + m_OverrideState: 1 + m_Value: 6 + dirtTexture: + m_OverrideState: 1 + m_Value: {fileID: 0} + dimension: 1 + dirtIntensity: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-1170528603972255243 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 221518ef91623a7438a71fef23660601, type: 3} + m_Name: WhiteBalance + m_EditorClassIdentifier: + active: 1 + temperature: + m_OverrideState: 1 + m_Value: 0 + tint: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &-581120513425526550 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 0} + m_Name: CopyPasteTestComponent3 + m_EditorClassIdentifier: Unity.RenderPipelines.Core.Editor.Tests:UnityEditor.Rendering.Tests:VolumeComponentCopyPasteTests/CopyPasteTestComponent3 + active: 1 + p1: + m_OverrideState: 1 + m_Value: 0 + p2: + m_OverrideState: 1 + m_Value: 0 + p31: + m_OverrideState: 1 + m_Value: {r: 0, g: 0, b: 0, a: 1} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: d7fd9488000d3734a9e00ee676215985, type: 3} + m_Name: DefaultVolumeProfile + m_EditorClassIdentifier: + components: + - {fileID: -9167874883656233139} + - {fileID: 1918650496244738858} + - {fileID: 853819529557874667} + - {fileID: 1052315754049611418} + - {fileID: -1170528603972255243} + - {fileID: -8270506406425502121} + - {fileID: -5520245016509672950} + - {fileID: 7173750748008157695} + - {fileID: 1666464333004379222} + - {fileID: 9001657382290151224} + - {fileID: -6335409530604852063} + - {fileID: -1216621516061285780} + - {fileID: 3959858460715838825} + - {fileID: -7743500325797982168} + - {fileID: 4644742534064026673} + - {fileID: -4463884970436517307} + - {fileID: -6288072647309666549} + - {fileID: 7518938298396184218} + - {fileID: -1410297666881709256} + - {fileID: -4337935226145447908} + - {fileID: -6453909008720401061} + - {fileID: 375704047594593491} + - {fileID: 5498996420690327226} + - {fileID: -6848783720466317983} + - {fileID: 4307208578333861838} + - {fileID: -5433043836740020232} + - {fileID: -3193994094532107207} + - {fileID: 271431995186689846} + - {fileID: 5507029023061418331} + - {fileID: 7860059515940364625} + - {fileID: 1149897091762735767} + - {fileID: 9180474596897214431} + - {fileID: -6034333096595414194} + - {fileID: 740528849878659255} +--- !u!114 &271431995186689846 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: e0b07a42ea8749b41bdca5f151c44d94, type: 3} + m_Name: NiloToonRenderingPerformanceControlVolume + m_EditorClassIdentifier: + active: 1 + overrideEnableDepthTextureRimLigthAndShadow: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &375704047594593491 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 8a10bd7999fb5fe43ab7b08bda3fe53f, type: 3} + m_Name: NiloToonBloomVolume + m_EditorClassIdentifier: + active: 1 + threshold: + m_OverrideState: 1 + m_Value: 0.9 + intensity: + m_OverrideState: 1 + m_Value: 0 + scatter: + m_OverrideState: 1 + m_Value: 0.7 + tint: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + clamp: + m_OverrideState: 1 + m_Value: 65472 + highQualityFiltering: + m_OverrideState: 1 + m_Value: 0 + downscale: + m_OverrideState: 1 + m_Value: 0 + maxIterations: + m_OverrideState: 1 + m_Value: 8 + dirtTexture: + m_OverrideState: 1 + m_Value: {fileID: 0} + dimension: 1 + dirtIntensity: + m_OverrideState: 1 + m_Value: 0 + characterBaseColorBrightness: + m_OverrideState: 1 + m_Value: 1 + characterBrightness: + m_OverrideState: 1 + m_Value: 1 + characterPreTonemapBrightness: + m_OverrideState: 1 + m_Value: 1 + characterAreaBloomEmitMultiplier: + m_OverrideState: 1 + m_Value: 1 + characterAreaOverridedThreshold: + m_OverrideState: 1 + m_Value: 0.9 + characterAreaOverridedIntensity: + m_OverrideState: 1 + m_Value: 0 + HueOffset: + m_OverrideState: 1 + m_Value: 0 + SaturationBoost: + m_OverrideState: 1 + m_Value: 0 + ValueMultiply: + m_OverrideState: 1 + m_Value: 1 + ApplyHSVToCharAreaOnly: + m_OverrideState: 1 + m_Value: 0 + renderTextureOverridedToFixedHeight: + m_OverrideState: 1 + m_Value: 1080 +--- !u!114 &740528849878659255 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 60f3b30c03e6ba64d9a27dc9dba8f28d, type: 3} + m_Name: OutlineVolumeComponent + m_EditorClassIdentifier: + active: 1 + Enabled: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &853819529557874667 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 06437c1ff663d574d9447842ba0a72e4, type: 3} + m_Name: ScreenSpaceLensFlare + m_EditorClassIdentifier: + active: 1 + intensity: + m_OverrideState: 1 + m_Value: 0 + tintColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + bloomMip: + m_OverrideState: 1 + m_Value: 1 + firstFlareIntensity: + m_OverrideState: 1 + m_Value: 1 + secondaryFlareIntensity: + m_OverrideState: 1 + m_Value: 1 + warpedFlareIntensity: + m_OverrideState: 1 + m_Value: 1 + warpedFlareScale: + m_OverrideState: 1 + m_Value: {x: 1, y: 1} + samples: + m_OverrideState: 1 + m_Value: 1 + sampleDimmer: + m_OverrideState: 1 + m_Value: 0.5 + vignetteEffect: + m_OverrideState: 1 + m_Value: 1 + startingPosition: + m_OverrideState: 1 + m_Value: 1.25 + scale: + m_OverrideState: 1 + m_Value: 1.5 + streaksIntensity: + m_OverrideState: 1 + m_Value: 0 + streaksLength: + m_OverrideState: 1 + m_Value: 0.5 + streaksOrientation: + m_OverrideState: 1 + m_Value: 0 + streaksThreshold: + m_OverrideState: 1 + m_Value: 0.25 + resolution: + m_OverrideState: 1 + m_Value: 4 + chromaticAbberationIntensity: + m_OverrideState: 1 + m_Value: 0.5 +--- !u!114 &1052315754049611418 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 558a8e2b6826cf840aae193990ba9f2e, type: 3} + m_Name: ShadowsMidtonesHighlights + m_EditorClassIdentifier: + active: 1 + shadows: + m_OverrideState: 1 + m_Value: {x: 1, y: 1, z: 1, w: 0} + midtones: + m_OverrideState: 1 + m_Value: {x: 1, y: 1, z: 1, w: 0} + highlights: + m_OverrideState: 1 + m_Value: {x: 1, y: 1, z: 1, w: 0} + shadowsStart: + m_OverrideState: 1 + m_Value: 0 + shadowsEnd: + m_OverrideState: 1 + m_Value: 0.3 + highlightsStart: + m_OverrideState: 1 + m_Value: 0.55 + highlightsEnd: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &1149897091762735767 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 90fbf49926625114084d7e0c0cffe8d1, type: 3} + m_Name: HBAO + m_EditorClassIdentifier: + active: 1 + preset: + m_OverrideState: 1 + m_Value: 2 + mode: + m_OverrideState: 1 + m_Value: 1 + renderingPath: + m_OverrideState: 1 + m_Value: 0 + quality: + m_OverrideState: 1 + m_Value: 2 + deinterleaving: + m_OverrideState: 1 + m_Value: 0 + resolution: + m_OverrideState: 1 + m_Value: 0 + noiseType: + m_OverrideState: 1 + m_Value: 0 + debugMode: + m_OverrideState: 1 + m_Value: 0 + radius: + m_OverrideState: 1 + m_Value: 0.8 + maxRadiusPixels: + m_OverrideState: 1 + m_Value: 128 + bias: + m_OverrideState: 1 + m_Value: 0.05 + intensity: + m_OverrideState: 1 + m_Value: 0 + useMultiBounce: + m_OverrideState: 1 + m_Value: 0 + multiBounceInfluence: + m_OverrideState: 1 + m_Value: 1 + directLightingStrength: + m_OverrideState: 1 + m_Value: 0.25 + offscreenSamplesContribution: + m_OverrideState: 1 + m_Value: 0 + maxDistance: + m_OverrideState: 1 + m_Value: 150 + distanceFalloff: + m_OverrideState: 1 + m_Value: 50 + perPixelNormals: + m_OverrideState: 1 + m_Value: 2 + baseColor: + m_OverrideState: 1 + m_Value: {r: 0, g: 0, b: 0, a: 1} + temporalFilterEnabled: + m_OverrideState: 1 + m_Value: 0 + varianceClipping: + m_OverrideState: 1 + m_Value: 1 + blurType: + m_OverrideState: 1 + m_Value: 2 + sharpness: + m_OverrideState: 1 + m_Value: 8 + colorBleedingEnabled: + m_OverrideState: 1 + m_Value: 0 + saturation: + m_OverrideState: 1 + m_Value: 1 + brightnessMask: + m_OverrideState: 1 + m_Value: 1 + brightnessMaskRange: + m_OverrideState: 1 + m_Value: {x: 0, y: 0.5} + min: 0 + max: 2 +--- !u!114 &1666464333004379222 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 3eb4b772797da9440885e8bd939e9560, type: 3} + m_Name: ColorCurves + m_EditorClassIdentifier: + active: 1 + master: + m_OverrideState: 1 + m_Value: + k__BackingField: 2 + m_Loop: 0 + m_ZeroValue: 0 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + red: + m_OverrideState: 1 + m_Value: + k__BackingField: 2 + m_Loop: 0 + m_ZeroValue: 0 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + green: + m_OverrideState: 1 + m_Value: + k__BackingField: 2 + m_Loop: 0 + m_ZeroValue: 0 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + blue: + m_OverrideState: 1 + m_Value: + k__BackingField: 2 + m_Loop: 0 + m_ZeroValue: 0 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + hueVsHue: + m_OverrideState: 1 + m_Value: + k__BackingField: 0 + m_Loop: 1 + m_ZeroValue: 0.5 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + hueVsSat: + m_OverrideState: 1 + m_Value: + k__BackingField: 0 + m_Loop: 1 + m_ZeroValue: 0.5 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + satVsSat: + m_OverrideState: 1 + m_Value: + k__BackingField: 0 + m_Loop: 0 + m_ZeroValue: 0.5 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + lumVsSat: + m_OverrideState: 1 + m_Value: + k__BackingField: 0 + m_Loop: 0 + m_ZeroValue: 0.5 + m_Range: 1 + m_Curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!114 &1918650496244738858 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: e021b4c809a781e468c2988c016ebbea, type: 3} + m_Name: ColorLookup + m_EditorClassIdentifier: + active: 1 + texture: + m_OverrideState: 1 + m_Value: {fileID: 0} + dimension: 1 + contribution: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &3959858460715838825 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: c01700fd266d6914ababb731e09af2eb, type: 3} + m_Name: DepthOfField + m_EditorClassIdentifier: + active: 1 + mode: + m_OverrideState: 1 + m_Value: 0 + gaussianStart: + m_OverrideState: 1 + m_Value: 10 + gaussianEnd: + m_OverrideState: 1 + m_Value: 30 + gaussianMaxRadius: + m_OverrideState: 1 + m_Value: 1 + highQualitySampling: + m_OverrideState: 1 + m_Value: 0 + focusDistance: + m_OverrideState: 1 + m_Value: 10 + aperture: + m_OverrideState: 1 + m_Value: 5.6 + focalLength: + m_OverrideState: 1 + m_Value: 50 + bladeCount: + m_OverrideState: 1 + m_Value: 5 + bladeCurvature: + m_OverrideState: 1 + m_Value: 1 + bladeRotation: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &4251301726029935498 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 74955a4b0b4243bc87231e8b59ed9140, type: 3} + m_Name: TestVolume + m_EditorClassIdentifier: + active: 1 + param: + m_OverrideState: 1 + m_Value: 123 +--- !u!114 &4307208578333861838 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 905ab376be722a641bd27d7ae304cedd, type: 3} + m_Name: NiloToonTonemappingVolume + m_EditorClassIdentifier: + active: 1 + mode: + m_OverrideState: 1 + m_Value: 0 + intensity: + m_OverrideState: 1 + m_Value: 1 + ApplyToCharacter: + m_OverrideState: 1 + m_Value: 0 + ApplyToNonCharacter: + m_OverrideState: 1 + m_Value: 1 + BrightnessMulForCharacter: + m_OverrideState: 1 + m_Value: 1 + BrightnessMulForNonCharacter: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &4644742534064026673 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 81180773991d8724ab7f2d216912b564, type: 3} + m_Name: ChromaticAberration + m_EditorClassIdentifier: + active: 1 + intensity: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &5498996420690327226 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 5aa15fc7246432d4fb73e65893caaa4b, type: 3} + m_Name: NiloToonAnimePostProcessVolume + m_EditorClassIdentifier: + active: 1 + intensity: + m_OverrideState: 1 + m_Value: 0 + rotation: + m_OverrideState: 1 + m_Value: 0 + topLightEffectDrawHeight: + m_OverrideState: 1 + m_Value: 0.5 + topLightEffectIntensity: + m_OverrideState: 1 + m_Value: 1 + topLightMultiplyLightColor: + m_OverrideState: 1 + m_Value: 1 + topLightSunTintColor: + m_OverrideState: 1 + m_Value: {r: 0.3, g: 0.225, b: 0.1125, a: 1} + topLightDesaturate: + m_OverrideState: 1 + m_Value: 0 + topLightTintColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + topLightExtraRotation: + m_OverrideState: 1 + m_Value: 0 + bottomDarkenEffectDrawHeight: + m_OverrideState: 1 + m_Value: 0.5 + bottomDarkenEffectIntensity: + m_OverrideState: 1 + m_Value: 1 + bottomDarkenExtraRotation: + m_OverrideState: 1 + m_Value: 0 + drawBeforePostProcess: + m_OverrideState: 1 + m_Value: 0 + affectedByCameraPostprocessToggle: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &5507029023061418331 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 39dc1fe45bfcc1e4eaa9ae19ecefd49c, type: 3} + m_Name: NiloToonShadowControlVolume + m_EditorClassIdentifier: + active: 1 + characterOverallShadowTintColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + characterOverallShadowStrength: + m_OverrideState: 1 + m_Value: 1 + enableCharAverageShadow: + m_OverrideState: 1 + m_Value: 1 + charAverageShadowStrength: + m_OverrideState: 1 + m_Value: 1 + enableCharSelfShadow: + m_OverrideState: 1 + m_Value: 1 + charSelfShadowStrength: + m_OverrideState: 1 + m_Value: 1 + useMainLightAsCastShadowDirection: + m_OverrideState: 1 + m_Value: 1 + shadowAngle: + m_OverrideState: 1 + m_Value: 30 + shadowLRAngle: + m_OverrideState: 1 + m_Value: 0 + shadowRange: + m_OverrideState: 1 + m_Value: 10 + shadowMapSize: + m_OverrideState: 1 + m_Value: 4096 + depthBias: + m_OverrideState: 1 + m_Value: 1 + normalBias: + m_OverrideState: 1 + m_Value: 1 + receiveURPShadow: + m_OverrideState: 1 + m_Value: 0 + URPShadowIntensity: + m_OverrideState: 1 + m_Value: 1 + URPShadowAsDirectLightMultiplier: + m_OverrideState: 1 + m_Value: 1 + URPShadowAsDirectLightTintColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + URPShadowAsDirectLightTintIgnoreMaterialURPUsageSetting: + m_OverrideState: 1 + m_Value: 1 + URPShadowblurriness: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &6940869943325143175 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 0} + m_Name: VolumeComponentSupportedOnAnySRP + m_EditorClassIdentifier: Unity.RenderPipelines.Core.Editor.Tests:UnityEngine.Rendering.Tests:VolumeComponentEditorSupportedOnTests/VolumeComponentSupportedOnAnySRP + active: 1 +--- !u!114 &7173750748008157695 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 899c54efeace73346a0a16faa3afe726, type: 3} + m_Name: Vignette + m_EditorClassIdentifier: + active: 1 + color: + m_OverrideState: 1 + m_Value: {r: 0, g: 0, b: 0, a: 1} + center: + m_OverrideState: 1 + m_Value: {x: 0.5, y: 0.5} + intensity: + m_OverrideState: 1 + m_Value: 0 + smoothness: + m_OverrideState: 1 + m_Value: 0.2 + rounded: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &7518938298396184218 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: c5e1dc532bcb41949b58bc4f2abfbb7e, type: 3} + m_Name: LensDistortion + m_EditorClassIdentifier: + active: 1 + intensity: + m_OverrideState: 1 + m_Value: 0 + xMultiplier: + m_OverrideState: 1 + m_Value: 1 + yMultiplier: + m_OverrideState: 1 + m_Value: 1 + center: + m_OverrideState: 1 + m_Value: {x: 0.5, y: 0.5} + scale: + m_OverrideState: 1 + m_Value: 1 +--- !u!114 &7860059515940364625 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 190e72967b306f4498b2f326170fd5a2, type: 3} + m_Name: NiloToonEnvironmentControlVolume + m_EditorClassIdentifier: + active: 1 + GlobalIlluminationTintColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 1} + GlobalIlluminationAddColor: + m_OverrideState: 1 + m_Value: {r: 0, g: 0, b: 0, a: 1} + GlobalIlluminationOverrideColor: + m_OverrideState: 1 + m_Value: {r: 0, g: 0, b: 0, a: 0} + GlobalAlbedoOverrideColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 0} + GlobalSurfaceColorResultOverrideColor: + m_OverrideState: 1 + m_Value: {r: 1, g: 1, b: 1, a: 0} + GlobalShadowBoaderTintColorOverrideColor: + m_OverrideState: 1 + m_Value: {r: 0, g: 0, b: 0, a: 0} +--- !u!114 &9001657382290151224 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: cdfbdbb87d3286943a057f7791b43141, type: 3} + m_Name: ChannelMixer + m_EditorClassIdentifier: + active: 1 + redOutRedIn: + m_OverrideState: 1 + m_Value: 100 + redOutGreenIn: + m_OverrideState: 1 + m_Value: 0 + redOutBlueIn: + m_OverrideState: 1 + m_Value: 0 + greenOutRedIn: + m_OverrideState: 1 + m_Value: 0 + greenOutGreenIn: + m_OverrideState: 1 + m_Value: 100 + greenOutBlueIn: + m_OverrideState: 1 + m_Value: 0 + blueOutRedIn: + m_OverrideState: 1 + m_Value: 0 + blueOutGreenIn: + m_OverrideState: 1 + m_Value: 0 + blueOutBlueIn: + m_OverrideState: 1 + m_Value: 100 +--- !u!114 &9122958982931076880 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 0} + m_Name: CopyPasteTestComponent1 + m_EditorClassIdentifier: Unity.RenderPipelines.Core.Editor.Tests:UnityEditor.Rendering.Tests:VolumeComponentCopyPasteTests/CopyPasteTestComponent1 + active: 1 + p1: + m_OverrideState: 1 + m_Value: 0 + p2: + m_OverrideState: 1 + m_Value: 0 +--- !u!114 &9180474596897214431 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: ae2b217974b749d4b97b47bae772aee5, type: 3} + m_Name: NiloToonMotionBlurVolume + m_EditorClassIdentifier: + active: 1 + intensity: + m_OverrideState: 1 + m_Value: 0 diff --git a/Assets/Settings/DefaultVolumeProfile.asset.meta b/Assets/Settings/DefaultVolumeProfile.asset.meta new file mode 100644 index 000000000..53b314adf --- /dev/null +++ b/Assets/Settings/DefaultVolumeProfile.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ab09877e2e707104187f6f83e2f62510 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/Mobile_RPAsset.asset b/Assets/Settings/Mobile_RPAsset.asset new file mode 100644 index 000000000..0fdefd13e --- /dev/null +++ b/Assets/Settings/Mobile_RPAsset.asset @@ -0,0 +1,135 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: bf2edee5c58d82540a51f03df9d42094, type: 3} + m_Name: Mobile_RPAsset + m_EditorClassIdentifier: + k_AssetVersion: 12 + k_AssetPreviousVersion: 12 + m_RendererType: 1 + m_RendererData: {fileID: 0} + m_RendererDataList: + - {fileID: 11400000, guid: 65bc7dbf4170f435aa868c779acfb082, type: 2} + m_DefaultRendererIndex: 0 + m_RequireDepthTexture: 0 + m_RequireOpaqueTexture: 0 + m_OpaqueDownsampling: 0 + m_SupportsTerrainHoles: 1 + m_SupportsHDR: 1 + m_HDRColorBufferPrecision: 0 + m_MSAA: 1 + m_RenderScale: 0.8 + m_UpscalingFilter: 3 + m_FsrOverrideSharpness: 0 + m_FsrSharpness: 0.92 + m_EnableLODCrossFade: 1 + m_LODCrossFadeDitheringType: 1 + m_ShEvalMode: 0 + m_LightProbeSystem: 0 + m_ProbeVolumeMemoryBudget: 1024 + m_ProbeVolumeBlendingMemoryBudget: 256 + m_SupportProbeVolumeGPUStreaming: 0 + m_SupportProbeVolumeDiskStreaming: 0 + m_SupportProbeVolumeScenarios: 0 + m_SupportProbeVolumeScenarioBlending: 0 + m_ProbeVolumeSHBands: 1 + m_MainLightRenderingMode: 1 + m_MainLightShadowsSupported: 1 + m_MainLightShadowmapResolution: 1024 + m_AdditionalLightsRenderingMode: 1 + m_AdditionalLightsPerObjectLimit: 4 + m_AdditionalLightShadowsSupported: 0 + m_AdditionalLightsShadowmapResolution: 2048 + m_AdditionalLightsShadowResolutionTierLow: 256 + m_AdditionalLightsShadowResolutionTierMedium: 512 + m_AdditionalLightsShadowResolutionTierHigh: 1024 + m_ReflectionProbeBlending: 1 + m_ReflectionProbeBoxProjection: 1 + m_ShadowDistance: 50 + m_ShadowCascadeCount: 1 + m_Cascade2Split: 0.25 + m_Cascade3Split: {x: 0.1, y: 0.3} + m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467} + m_CascadeBorder: 0.2 + m_ShadowDepthBias: 1 + m_ShadowNormalBias: 1 + m_AnyShadowsSupported: 1 + m_SoftShadowsSupported: 0 + m_ConservativeEnclosingSphere: 1 + m_NumIterationsEnclosingSphere: 64 + m_SoftShadowQuality: 2 + m_AdditionalLightsCookieResolution: 1024 + m_AdditionalLightsCookieFormat: 1 + m_UseSRPBatcher: 1 + m_SupportsDynamicBatching: 0 + m_MixedLightingSupported: 1 + m_SupportsLightCookies: 1 + m_SupportsLightLayers: 1 + m_DebugLevel: 0 + m_StoreActionsOptimization: 0 + m_UseAdaptivePerformance: 1 + m_ColorGradingMode: 0 + m_ColorGradingLutSize: 32 + m_UseFastSRGBLinearConversion: 1 + m_SupportDataDrivenLensFlare: 1 + m_SupportScreenSpaceLensFlare: 1 + m_GPUResidentDrawerMode: 0 + m_UseLegacyLightmaps: 0 + m_SmallMeshScreenPercentage: 0 + m_GPUResidentDrawerEnableOcclusionCullingInCameras: 0 + m_ShadowType: 1 + m_LocalShadowsSupported: 0 + m_LocalShadowsAtlasResolution: 256 + m_MaxPixelLights: 0 + m_ShadowAtlasResolution: 256 + m_VolumeFrameworkUpdateMode: 0 + m_VolumeProfile: {fileID: 11400000, guid: 10fc4df2da32a41aaa32d77bc913491c, type: 2} + apvScenesData: + obsoleteSceneBounds: + m_Keys: [] + m_Values: [] + obsoleteHasProbeVolumes: + m_Keys: [] + m_Values: + m_PrefilteringModeMainLightShadows: 3 + m_PrefilteringModeAdditionalLight: 4 + m_PrefilteringModeAdditionalLightShadows: 0 + m_PrefilterXRKeywords: 1 + m_PrefilteringModeForwardPlus: 1 + m_PrefilteringModeDeferredRendering: 0 + m_PrefilteringModeScreenSpaceOcclusion: 0 + m_PrefilterDebugKeywords: 1 + m_PrefilterWriteRenderingLayers: 1 + m_PrefilterHDROutput: 1 + m_PrefilterSSAODepthNormals: 1 + m_PrefilterSSAOSourceDepthLow: 1 + m_PrefilterSSAOSourceDepthMedium: 0 + m_PrefilterSSAOSourceDepthHigh: 1 + m_PrefilterSSAOInterleaved: 0 + m_PrefilterSSAOBlueNoise: 1 + m_PrefilterSSAOSampleCountLow: 1 + m_PrefilterSSAOSampleCountMedium: 0 + m_PrefilterSSAOSampleCountHigh: 1 + m_PrefilterDBufferMRT1: 1 + m_PrefilterDBufferMRT2: 1 + m_PrefilterDBufferMRT3: 1 + m_PrefilterSoftShadowsQualityLow: 1 + m_PrefilterSoftShadowsQualityMedium: 1 + m_PrefilterSoftShadowsQualityHigh: 1 + m_PrefilterSoftShadows: 0 + m_PrefilterScreenCoord: 1 + m_PrefilterNativeRenderPass: 1 + m_PrefilterUseLegacyLightmaps: 0 + m_ShaderVariantLogLevel: 0 + m_ShadowCascades: 0 + m_Textures: + blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} + bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} diff --git a/Assets/Settings/Mobile_RPAsset.asset.meta b/Assets/Settings/Mobile_RPAsset.asset.meta new file mode 100644 index 000000000..3660d1516 --- /dev/null +++ b/Assets/Settings/Mobile_RPAsset.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5e6cbd92db86f4b18aec3ed561671858 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/Mobile_Renderer.asset b/Assets/Settings/Mobile_Renderer.asset new file mode 100644 index 000000000..7c5e2b683 --- /dev/null +++ b/Assets/Settings/Mobile_Renderer.asset @@ -0,0 +1,130 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-2389020161682282714 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 9ad20adf61393c4428c8b31cf405bb26, type: 3} + m_Name: NiloToonAllInOneRendererFeature + m_EditorClassIdentifier: + m_Active: 1 + settings: + outlineSettings: + ShouldRenderOutline: 1 + outlineWidthMultiplier: 1 + outlineWidthExtraMultiplierForXR: 0.5 + outlineTintColor: {r: 1, g: 1, b: 1, a: 1} + outlineWidthAutoAdjustToCameraDistanceAndFOV: 1 + allowClassicOutlineInPlanarReflection: 0 + AllowRenderScreenSpaceOutline: 0 + AllowRenderScreenSpaceOutlineInSceneView: 0 + extraThickOutlineRenderTiming: 500 + MiscSettings: + ShouldReceiveURPShadows: 0 + URPShadowIntensity: 1 + URPShadowDepthBias: 0 + URPShadowNormalBiasMultiplier: 1 + EnableDepthTextureRimLigthAndShadow: 1 + DepthTextureRimLightAndShadowWidthMultiplier: 1 + DepthTexRimLightDepthDiffThresholdOffset: 0 + EnableSkyboxDrawBeforeOpaque: 1 + ForceMinimumShader: 0 + ForceMinimumEnviShader: 0 + ForceNoOutline: 0 + sphereShadowTestSettings: + enableAverageShadow: 0 + animePostProcessSettings: + allowRender: 1 + uberPostProcessSettings: + renderPassEventTimingOffset: 0 + allowRenderNiloToonBloom: 1 + charSelfShadowSettings: + enableCharSelfShadow: 1 + useMainLightAsCastShadowDirection: 1 + shadowAngle: 30 + shadowLRAngle: 0 + shadowMapSize: 4096 + useSoftShadow: 1 + softShadowQuality: 2 + useSoftShadowResharpen: 0 + resharpenStregth: 0.5 + shadowRange: 10 + depthBias: 1 + normalBias: 0.5 + receiverDepthBias: 1 + receiverNormalBias: 1 + useNdotLFix: 1 + perfectCullingForShadowCasters: 1 + terrainCrashSafeGuard: 1 + shaderStrippingSettingSO: {fileID: 0} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: de640fe3d0db1804a85f9fc8f5cadab6, type: 3} + m_Name: Mobile_Renderer + m_EditorClassIdentifier: + debugShaders: + debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, type: 3} + hdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3} + probeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959, type: 3} + probeVolumeResources: + probeVolumeDebugShader: {fileID: 0} + probeVolumeFragmentationDebugShader: {fileID: 0} + probeVolumeOffsetDebugShader: {fileID: 0} + probeVolumeSamplingDebugShader: {fileID: 0} + probeSamplingDebugMesh: {fileID: 0} + probeSamplingDebugTexture: {fileID: 0} + probeVolumeBlendStatesCS: {fileID: 0} + m_RendererFeatures: + - {fileID: -2389020161682282714} + m_RendererFeatureMap: 2667ae0dd27ed8de + m_UseNativeRenderPass: 1 + xrSystemData: {fileID: 0} + postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} + m_AssetVersion: 2 + m_OpaqueLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_TransparentLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_DefaultStencilState: + overrideStencilState: 0 + stencilReference: 0 + stencilCompareFunction: 8 + passOperation: 2 + failOperation: 0 + zFailOperation: 0 + m_ShadowTransparentReceive: 0 + m_RenderingMode: 2 + m_DepthPrimingMode: 0 + m_CopyDepthMode: 0 + m_DepthAttachmentFormat: 0 + m_DepthTextureFormat: 0 + m_AccurateGbufferNormals: 0 + m_IntermediateTextureMode: 0 +--- !u!114 &1002035807535710140 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: a0ec52cecc795714f93f274c2e71e87b, type: 3} + m_Name: GlobalVolumeFeature + m_EditorClassIdentifier: + m_Active: 1 + _baseProfile: {fileID: 11400000, guid: f2d4d916a6612574cad220d125febbf2, type: 2} diff --git a/Assets/Settings/Mobile_Renderer.asset.meta b/Assets/Settings/Mobile_Renderer.asset.meta new file mode 100644 index 000000000..a3588b1a9 --- /dev/null +++ b/Assets/Settings/Mobile_Renderer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 65bc7dbf4170f435aa868c779acfb082 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/PC_RPAsset.asset b/Assets/Settings/PC_RPAsset.asset new file mode 100644 index 000000000..704c1c091 --- /dev/null +++ b/Assets/Settings/PC_RPAsset.asset @@ -0,0 +1,137 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: bf2edee5c58d82540a51f03df9d42094, type: 3} + m_Name: PC_RPAsset + m_EditorClassIdentifier: + k_AssetVersion: 12 + k_AssetPreviousVersion: 12 + m_RendererType: 1 + m_RendererData: {fileID: 0} + m_RendererDataList: + - {fileID: 11400000, guid: f288ae1f4751b564a96ac7587541f7a2, type: 2} + - {fileID: 11400000, guid: c4f1194f4250143a89838154a1af9634, type: 2} + m_DefaultRendererIndex: 0 + m_RequireDepthTexture: 1 + m_RequireOpaqueTexture: 0 + m_OpaqueDownsampling: 0 + m_SupportsTerrainHoles: 1 + m_SupportsHDR: 1 + m_HDRColorBufferPrecision: 1 + m_MSAA: 4 + m_RenderScale: 1 + m_UpscalingFilter: 0 + m_FsrOverrideSharpness: 0 + m_FsrSharpness: 0.92 + m_EnableLODCrossFade: 0 + m_LODCrossFadeDitheringType: 1 + m_ShEvalMode: 0 + m_LightProbeSystem: 0 + m_ProbeVolumeMemoryBudget: 1024 + m_ProbeVolumeBlendingMemoryBudget: 256 + m_SupportProbeVolumeGPUStreaming: 1 + m_SupportProbeVolumeDiskStreaming: 0 + m_SupportProbeVolumeScenarios: 0 + m_SupportProbeVolumeScenarioBlending: 0 + m_ProbeVolumeSHBands: 1 + m_MainLightRenderingMode: 1 + m_MainLightShadowsSupported: 1 + m_MainLightShadowmapResolution: 2048 + m_AdditionalLightsRenderingMode: 1 + m_AdditionalLightsPerObjectLimit: 8 + m_AdditionalLightShadowsSupported: 1 + m_AdditionalLightsShadowmapResolution: 2048 + m_AdditionalLightsShadowResolutionTierLow: 128 + m_AdditionalLightsShadowResolutionTierMedium: 256 + m_AdditionalLightsShadowResolutionTierHigh: 512 + m_ReflectionProbeBlending: 1 + m_ReflectionProbeBoxProjection: 1 + m_ShadowDistance: 50 + m_ShadowCascadeCount: 4 + m_Cascade2Split: 0.25 + m_Cascade3Split: {x: 0.1, y: 0.3} + m_Cascade4Split: {x: 0.12299999, y: 0.28, z: 0.53599995} + m_CascadeBorder: 0.107758604 + m_ShadowDepthBias: 1 + m_ShadowNormalBias: 1 + m_AnyShadowsSupported: 1 + m_SoftShadowsSupported: 1 + m_ConservativeEnclosingSphere: 1 + m_NumIterationsEnclosingSphere: 64 + m_SoftShadowQuality: 3 + m_AdditionalLightsCookieResolution: 2048 + m_AdditionalLightsCookieFormat: 3 + m_UseSRPBatcher: 0 + m_SupportsDynamicBatching: 0 + m_MixedLightingSupported: 1 + m_SupportsLightCookies: 1 + m_SupportsLightLayers: 1 + m_DebugLevel: 0 + m_StoreActionsOptimization: 0 + m_UseAdaptivePerformance: 1 + m_ColorGradingMode: 1 + m_ColorGradingLutSize: 32 + m_AllowPostProcessAlphaOutput: 1 + m_UseFastSRGBLinearConversion: 0 + m_SupportDataDrivenLensFlare: 1 + m_SupportScreenSpaceLensFlare: 1 + m_GPUResidentDrawerMode: 0 + m_SmallMeshScreenPercentage: 0 + m_GPUResidentDrawerEnableOcclusionCullingInCameras: 0 + m_ShadowType: 1 + m_LocalShadowsSupported: 0 + m_LocalShadowsAtlasResolution: 256 + m_MaxPixelLights: 0 + m_ShadowAtlasResolution: 256 + m_VolumeFrameworkUpdateMode: 0 + m_VolumeProfile: {fileID: 11400000, guid: f1294d65e811a974fa2000c587d56028, type: 2} + apvScenesData: + obsoleteSceneBounds: + m_Keys: [] + m_Values: [] + obsoleteHasProbeVolumes: + m_Keys: [] + m_Values: + m_PrefilteringModeMainLightShadows: 3 + m_PrefilteringModeAdditionalLight: 4 + m_PrefilteringModeAdditionalLightShadows: 0 + m_PrefilterXRKeywords: 1 + m_PrefilteringModeForwardPlus: 1 + m_PrefilteringModeDeferredRendering: 0 + m_PrefilteringModeScreenSpaceOcclusion: 1 + m_PrefilterDebugKeywords: 1 + m_PrefilterWriteRenderingLayers: 0 + m_PrefilterHDROutput: 1 + m_PrefilterAlphaOutput: 0 + m_PrefilterSSAODepthNormals: 0 + m_PrefilterSSAOSourceDepthLow: 1 + m_PrefilterSSAOSourceDepthMedium: 1 + m_PrefilterSSAOSourceDepthHigh: 1 + m_PrefilterSSAOInterleaved: 1 + m_PrefilterSSAOBlueNoise: 0 + m_PrefilterSSAOSampleCountLow: 1 + m_PrefilterSSAOSampleCountMedium: 0 + m_PrefilterSSAOSampleCountHigh: 1 + m_PrefilterDBufferMRT1: 1 + m_PrefilterDBufferMRT2: 1 + m_PrefilterDBufferMRT3: 0 + m_PrefilterSoftShadowsQualityLow: 0 + m_PrefilterSoftShadowsQualityMedium: 0 + m_PrefilterSoftShadowsQualityHigh: 0 + m_PrefilterSoftShadows: 0 + m_PrefilterScreenCoord: 1 + m_PrefilterNativeRenderPass: 1 + m_PrefilterUseLegacyLightmaps: 0 + m_ShaderVariantLogLevel: 0 + m_ShadowCascades: 0 + m_Textures: + blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} + bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} diff --git a/Assets/Settings/PC_RPAsset.asset.meta b/Assets/Settings/PC_RPAsset.asset.meta new file mode 100644 index 000000000..e286b2fdd --- /dev/null +++ b/Assets/Settings/PC_RPAsset.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4b83569d67af61e458304325a23e5dfd +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/PC_Renderer.asset b/Assets/Settings/PC_Renderer.asset new file mode 100644 index 000000000..18e824d1b --- /dev/null +++ b/Assets/Settings/PC_Renderer.asset @@ -0,0 +1,294 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-8625239526963705251 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 3a9a4847a92104072b352fe44da35cbb, type: 3} + m_Name: Volumetric Lights + m_EditorClassIdentifier: + m_Active: 1 + shader: {fileID: 4800000, guid: 6b7e6acc194204408b3294f5c220fc1e, type: 3} + blendMode: 0 + renderPassEvent: 450 + downscaling: 1 + blurPasses: 1 + blurDownscaling: 1 + blurSpread: 1 + blurHDR: 1 + blurEdgePreserve: 0 + blurEdgeDepthThreshold: 0.001 + brightness: 1 + ditherStrength: 0 + ignoreOverlayCamera: 1 +--- !u!114 &-3621555295984643616 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 9ad20adf61393c4428c8b31cf405bb26, type: 3} + m_Name: NiloToonAllInOneRendererFeature + m_EditorClassIdentifier: + m_Active: 1 + settings: + outlineSettings: + ShouldRenderOutline: 1 + outlineWidthMultiplier: 1 + outlineWidthExtraMultiplierForXR: 0.5 + outlineTintColor: {r: 1, g: 1, b: 1, a: 1} + outlineWidthAutoAdjustToCameraDistanceAndFOV: 1 + allowClassicOutlineInPlanarReflection: 0 + AllowRenderScreenSpaceOutline: 0 + AllowRenderScreenSpaceOutlineInSceneView: 0 + extraThickOutlineRenderTiming: 500 + MiscSettings: + ShouldReceiveURPShadows: 0 + URPShadowIntensity: 1 + URPShadowDepthBias: 0 + URPShadowNormalBiasMultiplier: 1 + EnableDepthTextureRimLigthAndShadow: 1 + DepthTextureRimLightAndShadowWidthMultiplier: 1 + DepthTexRimLightDepthDiffThresholdOffset: 0 + EnableSkyboxDrawBeforeOpaque: 1 + ForceMinimumShader: 0 + ForceMinimumEnviShader: 0 + ForceNoOutline: 0 + sphereShadowTestSettings: + enableAverageShadow: 0 + animePostProcessSettings: + allowRender: 1 + uberPostProcessSettings: + renderPassEventTimingOffset: 0 + allowRenderNiloToonBloom: 1 + charSelfShadowSettings: + enableCharSelfShadow: 1 + useMainLightAsCastShadowDirection: 1 + shadowAngle: 30 + shadowLRAngle: 0 + shadowMapSize: 4096 + useSoftShadow: 1 + softShadowQuality: 2 + useSoftShadowResharpen: 0 + resharpenStregth: 0.5 + shadowRange: 10 + depthBias: 1 + normalBias: 0.5 + receiverDepthBias: 1 + receiverNormalBias: 1 + useNdotLFix: 1 + perfectCullingForShadowCasters: 1 + terrainCrashSafeGuard: 1 + motionBlurSettings: + allowRender: 1 + shaderStrippingSettingSO: {fileID: 0} +--- !u!114 &-2852932001737893531 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 2e6a73f16fc15400aa1bbb77dd779b76, type: 3} + m_Name: VolumetricLightsDepthPrePassFeature + m_EditorClassIdentifier: + m_Active: 1 + transparentLayerMask: + serializedVersion: 2 + m_Bits: 0 + alphaCutoutLayerMask: + serializedVersion: 2 + m_Bits: 0 + alphaCutOff: 0 + ignoreReflectionProbes: 1 + ignoreOverlayCamera: 1 +--- !u!114 &-2625927759758650194 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 927576baecea04a5aa8be06dc57e6d9e, type: 3} + m_Name: Volumetric Fog 2 + m_EditorClassIdentifier: + m_Active: 1 + blurShader: {fileID: 4800000, guid: c9391e295126842e589edc35e6cfa61a, type: 3} + renderPassEvent: 450 + fogLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + cameraLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + ignoreReflectionProbes: 1 +--- !u!114 &-1421748198966979335 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: e32e72b6a3f58a24c9033e2b9275eea0, type: 3} + m_Name: ScreenSpaceShadows + m_EditorClassIdentifier: + m_Active: 1 + m_Shader: {fileID: 4800000, guid: 0f854b35a0cf61a429bd5dcfea30eddd, type: 3} +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: de640fe3d0db1804a85f9fc8f5cadab6, type: 3} + m_Name: PC_Renderer + m_EditorClassIdentifier: + debugShaders: + debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, type: 3} + hdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3} + probeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959, type: 3} + probeVolumeResources: + probeVolumeDebugShader: {fileID: 4800000, guid: e5c6678ed2aaa91408dd3df699057aae, type: 3} + probeVolumeFragmentationDebugShader: {fileID: 4800000, guid: 03cfc4915c15d504a9ed85ecc404e607, type: 3} + probeVolumeOffsetDebugShader: {fileID: 4800000, guid: 53a11f4ebaebf4049b3638ef78dc9664, type: 3} + probeVolumeSamplingDebugShader: {fileID: 4800000, guid: 8f96cd657dc40064aa21efcc7e50a2e7, type: 3} + probeSamplingDebugMesh: {fileID: -3555484719484374845, guid: 57d7c4c16e2765b47a4d2069b311bffe, type: 3} + probeSamplingDebugTexture: {fileID: 2800000, guid: 24ec0e140fb444a44ab96ee80844e18e, type: 3} + probeVolumeBlendStatesCS: {fileID: 7200000, guid: b9a23f869c4fd45f19c5ada54dd82176, type: 3} + m_RendererFeatures: + - {fileID: 7833122117494664109} + - {fileID: -3621555295984643616} + - {fileID: -1421748198966979335} + - {fileID: 7147247900318657015} + - {fileID: 2563399616140562874} + - {fileID: -2625927759758650194} + - {fileID: 1117754167293925116} + - {fileID: -8625239526963705251} + - {fileID: -2852932001737893531} + m_RendererFeatureMap: ad6b866f10d7b46ce0916668a5a6bdcdf99485b88bef44ecf76926fc18203063ba516e915e069323ae94bf819dd48edbfc56c4377e0f830f5d8aab4459fe4c88659911bc755968d8 + m_UseNativeRenderPass: 0 + xrSystemData: {fileID: 0} + postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} + m_AssetVersion: 2 + m_OpaqueLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_TransparentLayerMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_DefaultStencilState: + overrideStencilState: 0 + stencilReference: 1 + stencilCompareFunction: 3 + passOperation: 2 + failOperation: 0 + zFailOperation: 0 + m_ShadowTransparentReceive: 1 + m_RenderingMode: 2 + m_DepthPrimingMode: 0 + m_CopyDepthMode: 0 + m_DepthAttachmentFormat: 0 + m_DepthTextureFormat: 0 + m_AccurateGbufferNormals: 0 + m_IntermediateTextureMode: 0 +--- !u!114 &1117754167293925116 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: b3e6b9910358046a1a7a6e84c3169447, type: 3} + m_Name: VolumetricLightsTranslucentShadowMapFeature + m_EditorClassIdentifier: + m_Active: 1 + ignoreOverlayCamera: 1 +--- !u!114 &2563399616140562874 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: f7c2c2c3c19808149a4d3454e1019255, type: 3} + m_Name: HBAO + m_EditorClassIdentifier: + m_Active: 1 + shader: {fileID: 4800000, guid: bf610497676b34e4dbe0f14fe3fe311c, type: 3} +--- !u!114 &7147247900318657015 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: a1614fc811f8f184697d9bee70ab9fe5, type: 3} + m_Name: DecalRendererFeature + m_EditorClassIdentifier: + m_Active: 1 + m_Settings: + technique: 0 + maxDrawDistance: 1000 + decalLayers: 1 + dBufferSettings: + surfaceData: 2 + screenSpaceSettings: + normalBlend: 0 +--- !u!114 &7833122117494664109 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: f62c9c65cf3354c93be831c8bc075510, type: 3} + m_Name: ScreenSpaceAmbientOcclusion + m_EditorClassIdentifier: + m_Active: 1 + m_Settings: + AOMethod: 0 + Downsample: 0 + AfterOpaque: 0 + Source: 1 + NormalSamples: 1 + Intensity: 0.4 + DirectLightingStrength: 0.25 + Radius: 0.3 + Samples: 1 + BlurQuality: 0 + Falloff: 100 + SampleCount: -1 + m_BlueNoise256Textures: + - {fileID: 2800000, guid: 36f118343fc974119bee3d09e2111500, type: 3} + - {fileID: 2800000, guid: 4b7b083e6b6734e8bb2838b0b50a0bc8, type: 3} + - {fileID: 2800000, guid: c06cc21c692f94f5fb5206247191eeee, type: 3} + - {fileID: 2800000, guid: cb76dd40fa7654f9587f6a344f125c9a, type: 3} + - {fileID: 2800000, guid: e32226222ff144b24bf3a5a451de54bc, type: 3} + - {fileID: 2800000, guid: 3302065f671a8450b82c9ddf07426f3a, type: 3} + - {fileID: 2800000, guid: 56a77a3e8d64f47b6afe9e3c95cb57d5, type: 3} + m_Shader: {fileID: 4800000, guid: 0849e84e3d62649e8882e9d6f056a017, type: 3} diff --git a/Assets/Settings/PC_Renderer.asset.meta b/Assets/Settings/PC_Renderer.asset.meta new file mode 100644 index 000000000..ddae6a5f0 --- /dev/null +++ b/Assets/Settings/PC_Renderer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f288ae1f4751b564a96ac7587541f7a2 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/SampleSceneProfile.asset b/Assets/Settings/SampleSceneProfile.asset new file mode 100644 index 000000000..c1b0f6319 --- /dev/null +++ b/Assets/Settings/SampleSceneProfile.asset @@ -0,0 +1,159 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &-7893295128165547882 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 0b2db86121404754db890f4c8dfe81b2, type: 3} + m_Name: Bloom + m_EditorClassIdentifier: + active: 1 + skipIterations: + m_OverrideState: 1 + m_Value: 0 + threshold: + m_OverrideState: 1 + m_Value: 1 + intensity: + m_OverrideState: 1 + m_Value: 0.25 + scatter: + m_OverrideState: 1 + m_Value: 0.5 + clamp: + m_OverrideState: 0 + m_Value: 65472 + tint: + m_OverrideState: 0 + m_Value: {r: 1, g: 1, b: 1, a: 1} + highQualityFiltering: + m_OverrideState: 1 + m_Value: 1 + downscale: + m_OverrideState: 0 + m_Value: 0 + maxIterations: + m_OverrideState: 0 + m_Value: 6 + dirtTexture: + m_OverrideState: 0 + m_Value: {fileID: 0} + dimension: 1 + dirtIntensity: + m_OverrideState: 0 + m_Value: 0 +--- !u!114 &-3357603926938260329 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 899c54efeace73346a0a16faa3afe726, type: 3} + m_Name: Vignette + m_EditorClassIdentifier: + active: 1 + color: + m_OverrideState: 0 + m_Value: {r: 0, g: 0, b: 0, a: 1} + center: + m_OverrideState: 0 + m_Value: {x: 0.5, y: 0.5} + intensity: + m_OverrideState: 1 + m_Value: 0.2 + smoothness: + m_OverrideState: 0 + m_Value: 0.2 + rounded: + m_OverrideState: 0 + m_Value: 0 +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: d7fd9488000d3734a9e00ee676215985, type: 3} + m_Name: SampleSceneProfile + m_EditorClassIdentifier: + components: + - {fileID: 849379129802519247} + - {fileID: -7893295128165547882} + - {fileID: 7391319092446245454} + - {fileID: -3357603926938260329} +--- !u!114 &849379129802519247 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: 97c23e3b12dc18c42a140437e53d3951, type: 3} + m_Name: Tonemapping + m_EditorClassIdentifier: + active: 1 + mode: + m_OverrideState: 1 + m_Value: 1 + neutralHDRRangeReductionMode: + m_OverrideState: 0 + m_Value: 2 + acesPreset: + m_OverrideState: 0 + m_Value: 3 + hueShiftAmount: + m_OverrideState: 0 + m_Value: 0 + detectPaperWhite: + m_OverrideState: 1 + m_Value: 0 + paperWhite: + m_OverrideState: 1 + m_Value: 234 + detectBrightnessLimits: + m_OverrideState: 1 + m_Value: 1 + minNits: + m_OverrideState: 1 + m_Value: 0.005 + maxNits: + m_OverrideState: 1 + m_Value: 647 +--- !u!114 &7391319092446245454 +MonoBehaviour: + m_ObjectHideFlags: 3 + 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: ccf1aba9553839d41ae37dd52e9ebcce, type: 3} + m_Name: MotionBlur + m_EditorClassIdentifier: + active: 0 + mode: + m_OverrideState: 0 + m_Value: 0 + quality: + m_OverrideState: 1 + m_Value: 2 + intensity: + m_OverrideState: 1 + m_Value: 0.6 + clamp: + m_OverrideState: 0 + m_Value: 0.05 diff --git a/Assets/Settings/SampleSceneProfile.asset.meta b/Assets/Settings/SampleSceneProfile.asset.meta new file mode 100644 index 000000000..b82270c5b --- /dev/null +++ b/Assets/Settings/SampleSceneProfile.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 10fc4df2da32a41aaa32d77bc913491c +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset b/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset new file mode 100644 index 000000000..6aadcc3d4 --- /dev/null +++ b/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset @@ -0,0 +1,261 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + 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: 2ec995e51a6e251468d2a3fd8a686257, type: 3} + m_Name: UniversalRenderPipelineGlobalSettings + m_EditorClassIdentifier: + m_ShaderStrippingSetting: + m_Version: 0 + m_ExportShaderVariants: 1 + m_ShaderVariantLogLevel: 0 + m_StripRuntimeDebugShaders: 1 + m_URPShaderStrippingSetting: + m_Version: 0 + m_StripUnusedPostProcessingVariants: 1 + m_StripUnusedVariants: 1 + m_StripScreenCoordOverrideVariants: 1 + m_ShaderVariantLogLevel: 0 + m_ExportShaderVariants: 1 + m_StripDebugVariants: 1 + m_StripUnusedPostProcessingVariants: 1 + m_StripUnusedVariants: 1 + m_StripScreenCoordOverrideVariants: 1 + supportRuntimeDebugDisplay: 0 + m_EnableRenderGraph: 0 + m_Settings: + m_SettingsList: + m_List: + - rid: 6852985685364965376 + - rid: 6852985685364965377 + - rid: 6852985685364965378 + - rid: 6852985685364965379 + - rid: 6852985685364965380 + - rid: 6852985685364965381 + - rid: 6852985685364965382 + - rid: 6852985685364965383 + - rid: 6852985685364965384 + - rid: 6852985685364965385 + - rid: 6852985685364965386 + - rid: 6852985685364965387 + - rid: 6852985685364965388 + - rid: 6852985685364965389 + - rid: 6852985685364965390 + - rid: 6852985685364965391 + - rid: 6852985685364965392 + - rid: 6852985685364965393 + - rid: 6852985685364965394 + - rid: 8712630790384254976 + - rid: 377638681272647680 + - rid: 3846517534605967360 + m_RuntimeSettings: + m_List: [] + m_AssetVersion: 8 + m_ObsoleteDefaultVolumeProfile: {fileID: 0} + m_RenderingLayerNames: + - Light Layer default + - Light Layer 1 + - Light Layer 2 + - Light Layer 3 + - Light Layer 4 + - Light Layer 5 + - Light Layer 6 + - Light Layer 7 + m_ValidRenderingLayers: 0 + lightLayerName0: Light Layer default + lightLayerName1: Light Layer 1 + lightLayerName2: Light Layer 2 + lightLayerName3: Light Layer 3 + lightLayerName4: Light Layer 4 + lightLayerName5: Light Layer 5 + lightLayerName6: Light Layer 6 + lightLayerName7: Light Layer 7 + apvScenesData: + obsoleteSceneBounds: + m_Keys: [] + m_Values: [] + obsoleteHasProbeVolumes: + m_Keys: [] + m_Values: + references: + version: 2 + RefIds: + - rid: 377638681272647680 + type: {class: UniversalRenderPipelineRuntimeXRResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_xrOcclusionMeshPS: {fileID: 4800000, guid: 4431b1f1f743fbf4eb310a967890cbea, type: 3} + m_xrMirrorViewPS: {fileID: 4800000, guid: d5a307c014552314b9f560906d708772, type: 3} + m_xrMotionVector: {fileID: 4800000, guid: f89aac1e4f84468418fe30e611dff395, type: 3} + - rid: 3846517534605967360 + type: {class: UniversalRenderPipelineEditorAssets, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_DefaultSettingsVolumeProfile: {fileID: 11400000, guid: eda47df5b85f4f249abf7abd73db2cb2, type: 2} + - rid: 6852985685364965376 + type: {class: URPShaderStrippingSetting, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_StripUnusedPostProcessingVariants: 1 + m_StripUnusedVariants: 1 + m_StripScreenCoordOverrideVariants: 1 + - rid: 6852985685364965377 + type: {class: UniversalRenderPipelineEditorShaders, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_AutodeskInteractive: {fileID: 4800000, guid: 0e9d5a909a1f7e84882a534d0d11e49f, type: 3} + m_AutodeskInteractiveTransparent: {fileID: 4800000, guid: 5c81372d981403744adbdda4433c9c11, type: 3} + m_AutodeskInteractiveMasked: {fileID: 4800000, guid: 80aa867ac363ac043847b06ad71604cd, type: 3} + m_TerrainDetailLit: {fileID: 4800000, guid: f6783ab646d374f94b199774402a5144, type: 3} + m_TerrainDetailGrassBillboard: {fileID: 4800000, guid: 29868e73b638e48ca99a19ea58c48d90, type: 3} + m_TerrainDetailGrass: {fileID: 4800000, guid: e507fdfead5ca47e8b9a768b51c291a1, type: 3} + m_DefaultSpeedTree7Shader: {fileID: 4800000, guid: 0f4122b9a743b744abe2fb6a0a88868b, type: 3} + m_DefaultSpeedTree8Shader: {fileID: -6465566751694194690, guid: 9920c1f1781549a46ba081a2a15a16ec, type: 3} + m_DefaultSpeedTree9Shader: {fileID: -6465566751694194690, guid: cbd3e1cc4ae141c42a30e33b4d666a61, type: 3} + - rid: 6852985685364965378 + type: {class: UniversalRendererResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_CopyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} + m_CameraMotionVector: {fileID: 4800000, guid: c56b7e0d4c7cb484e959caeeedae9bbf, type: 3} + m_StencilDeferredPS: {fileID: 4800000, guid: e9155b26e1bc55942a41e518703fe304, type: 3} + m_DBufferClear: {fileID: 4800000, guid: f056d8bd2a1c7e44e9729144b4c70395, type: 3} + - rid: 6852985685364965379 + type: {class: UniversalRenderPipelineDebugShaders, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_DebugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, type: 3} + m_HdrDebugViewPS: {fileID: 4800000, guid: 573620ae32aec764abd4d728906d2587, type: 3} + m_ProbeVolumeSamplingDebugComputeShader: {fileID: 7200000, guid: 53626a513ea68ce47b59dc1299fe3959, type: 3} + - rid: 6852985685364965380 + type: {class: UniversalRenderPipelineRuntimeShaders, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_FallbackErrorShader: {fileID: 4800000, guid: e6e9a19c3678ded42a3bc431ebef7dbd, type: 3} + m_BlitHDROverlay: {fileID: 4800000, guid: a89bee29cffa951418fc1e2da94d1959, type: 3} + m_CoreBlitPS: {fileID: 4800000, guid: 93446b5c5339d4f00b85c159e1159b7c, type: 3} + m_CoreBlitColorAndDepthPS: {fileID: 4800000, guid: d104b2fc1ca6445babb8e90b0758136b, type: 3} + m_SamplingPS: {fileID: 4800000, guid: 04c410c9937594faa893a11dceb85f7e, type: 3} + - rid: 6852985685364965381 + type: {class: UniversalRenderPipelineRuntimeTextures, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 1 + m_BlueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} + m_BayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} + m_DebugFontTex: {fileID: 2800000, guid: 26a413214480ef144b2915d6ff4d0beb, type: 3} + - rid: 6852985685364965382 + type: {class: Renderer2DResources, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_LightShader: {fileID: 4800000, guid: 3f6c848ca3d7bca4bbe846546ac701a1, type: 3} + m_ProjectedShadowShader: {fileID: 4800000, guid: ce09d4a80b88c5a4eb9768fab4f1ee00, type: 3} + m_SpriteShadowShader: {fileID: 4800000, guid: 44fc62292b65ab04eabcf310e799ccf6, type: 3} + m_SpriteUnshadowShader: {fileID: 4800000, guid: de02b375720b5c445afe83cd483bedf3, type: 3} + m_GeometryShadowShader: {fileID: 4800000, guid: 19349a0f9a7ed4c48a27445bcf92e5e1, type: 3} + m_GeometryUnshadowShader: {fileID: 4800000, guid: 77774d9009bb81447b048c907d4c6273, type: 3} + m_FallOffLookup: {fileID: 2800000, guid: 5688ab254e4c0634f8d6c8e0792331ca, type: 3} + m_CopyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} + m_DefaultLitMaterial: {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2} + m_DefaultUnlitMaterial: {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, type: 2} + m_DefaultMaskMaterial: {fileID: 2100000, guid: 15d0c3709176029428a0da2f8cecf0b5, type: 2} + - rid: 6852985685364965383 + type: {class: UniversalRenderPipelineEditorMaterials, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_DefaultMaterial: {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_DefaultParticleMaterial: {fileID: 2100000, guid: e823cd5b5d27c0f4b8256e7c12ee3e6d, type: 2} + m_DefaultLineMaterial: {fileID: 2100000, guid: e823cd5b5d27c0f4b8256e7c12ee3e6d, type: 2} + m_DefaultTerrainMaterial: {fileID: 2100000, guid: 594ea882c5a793440b60ff72d896021e, type: 2} + m_DefaultDecalMaterial: {fileID: 2100000, guid: 31d0dcc6f2dd4e4408d18036a2c93862, type: 2} + m_DefaultSpriteMaterial: {fileID: 2100000, guid: 9dfc825aed78fcd4ba02077103263b40, type: 2} + - rid: 6852985685364965384 + type: {class: URPDefaultVolumeProfileSettings, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_VolumeProfile: {fileID: 11400000, guid: ab09877e2e707104187f6f83e2f62510, type: 2} + - rid: 6852985685364965385 + type: {class: RenderGraphSettings, ns: UnityEngine.Rendering.Universal, asm: Unity.RenderPipelines.Universal.Runtime} + data: + m_Version: 0 + m_EnableRenderCompatibilityMode: 1 + - rid: 6852985685364965386 + type: {class: GPUResidentDrawerResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.GPUDriven.Runtime} + data: + m_Version: 0 + m_InstanceDataBufferCopyKernels: {fileID: 7200000, guid: f984aeb540ded8b4fbb8a2047ab5b2e2, type: 3} + m_InstanceDataBufferUploadKernels: {fileID: 7200000, guid: 53864816eb00f2343b60e1a2c5a262ef, type: 3} + m_TransformUpdaterKernels: {fileID: 7200000, guid: 2a567b9b2733f8d47a700c3c85bed75b, type: 3} + m_WindDataUpdaterKernels: {fileID: 7200000, guid: fde76746e4fd0ed418c224f6b4084114, type: 3} + m_OccluderDepthPyramidKernels: {fileID: 7200000, guid: 08b2b5fb307b0d249860612774a987da, type: 3} + m_InstanceOcclusionCullingKernels: {fileID: 7200000, guid: f6d223acabc2f974795a5a7864b50e6c, type: 3} + m_OcclusionCullingDebugKernels: {fileID: 7200000, guid: b23e766bcf50ca4438ef186b174557df, type: 3} + m_DebugOcclusionTestPS: {fileID: 4800000, guid: d3f0849180c2d0944bc71060693df100, type: 3} + m_DebugOccluderPS: {fileID: 4800000, guid: b3c92426a88625841ab15ca6a7917248, type: 3} + - rid: 6852985685364965387 + type: {class: STP/RuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_setupCS: {fileID: 7200000, guid: 33be2e9a5506b2843bdb2bdff9cad5e1, type: 3} + m_preTaaCS: {fileID: 7200000, guid: a679dba8ec4d9ce45884a270b0e22dda, type: 3} + m_taaCS: {fileID: 7200000, guid: 3923900e2b41b5e47bc25bfdcbcdc9e6, type: 3} + - rid: 6852985685364965388 + type: {class: ProbeVolumeBakingResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + dilationShader: {fileID: 7200000, guid: 6bb382f7de370af41b775f54182e491d, type: 3} + subdivideSceneCS: {fileID: 7200000, guid: bb86f1f0af829fd45b2ebddda1245c22, type: 3} + voxelizeSceneShader: {fileID: 4800000, guid: c8b6a681c7b4e2e4785ffab093907f9e, type: 3} + traceVirtualOffsetCS: {fileID: -6772857160820960102, guid: ff2cbab5da58bf04d82c5f34037ed123, type: 3} + traceVirtualOffsetRT: {fileID: -5126288278712620388, guid: ff2cbab5da58bf04d82c5f34037ed123, type: 3} + skyOcclusionCS: {fileID: -6772857160820960102, guid: 5a2a534753fbdb44e96c3c78b5a6999d, type: 3} + skyOcclusionRT: {fileID: -5126288278712620388, guid: 5a2a534753fbdb44e96c3c78b5a6999d, type: 3} + renderingLayerCS: {fileID: -6772857160820960102, guid: 94a070d33e408384bafc1dea4a565df9, type: 3} + renderingLayerRT: {fileID: -5126288278712620388, guid: 94a070d33e408384bafc1dea4a565df9, type: 3} + - rid: 6852985685364965389 + type: {class: ProbeVolumeGlobalSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + m_ProbeVolumeDisableStreamingAssets: 0 + - rid: 6852985685364965390 + type: {class: ProbeVolumeDebugResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + probeVolumeDebugShader: {fileID: 4800000, guid: 3b21275fd12d65f49babb5286f040f2d, type: 3} + probeVolumeFragmentationDebugShader: {fileID: 4800000, guid: 3a80877c579b9144ebdcc6d923bca303, type: 3} + probeVolumeSamplingDebugShader: {fileID: 4800000, guid: bf54e6528c79a224e96346799064c393, type: 3} + probeVolumeOffsetDebugShader: {fileID: 4800000, guid: db8bd7436dc2c5f4c92655307d198381, type: 3} + probeSamplingDebugMesh: {fileID: -3555484719484374845, guid: 20be25aac4e22ee49a7db76fb3df6de2, type: 3} + numbersDisplayTex: {fileID: 2800000, guid: 73fe53b428c5b3440b7e87ee830b608a, type: 3} + - rid: 6852985685364965391 + type: {class: IncludeAdditionalRPAssets, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_version: 0 + m_IncludeReferencedInScenes: 0 + m_IncludeAssetsByLabel: 0 + m_LabelToInclude: + - rid: 6852985685364965392 + type: {class: ShaderStrippingSetting, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 0 + m_ExportShaderVariants: 1 + m_ShaderVariantLogLevel: 0 + m_StripRuntimeDebugShaders: 1 + - rid: 6852985685364965393 + type: {class: ProbeVolumeRuntimeResources, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 1 + probeVolumeBlendStatesCS: {fileID: 7200000, guid: a3f7b8c99de28a94684cb1daebeccf5d, type: 3} + probeVolumeUploadDataCS: {fileID: 7200000, guid: 0951de5992461754fa73650732c4954c, type: 3} + probeVolumeUploadDataL2CS: {fileID: 7200000, guid: 6196f34ed825db14b81fb3eb0ea8d931, type: 3} + - rid: 6852985685364965394 + type: {class: RenderGraphGlobalSettings, ns: UnityEngine.Rendering, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_version: 0 + m_EnableCompilationCaching: 1 + m_EnableValidityChecks: 1 + - rid: 8712630790384254976 + type: {class: RenderGraphUtilsResources, ns: UnityEngine.Rendering.RenderGraphModule.Util, asm: Unity.RenderPipelines.Core.Runtime} + data: + m_Version: 0 + m_CoreCopyPS: {fileID: 4800000, guid: 12dc59547ea167a4ab435097dd0f9add, type: 3} diff --git a/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset.meta b/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset.meta new file mode 100644 index 000000000..81b84f2ae --- /dev/null +++ b/Assets/Settings/UniversalRenderPipelineGlobalSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 18dc0cd2c080841dea60987a38ce93fa +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: