From 2b34694ab395396635ffba7a0c394d6877d3d7e9 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 27 Mar 2018 16:40:11 +0900 Subject: [PATCH] add VRM scripts --- Scenes.meta | 10 + Scenes/VRMRuntimeLoaderSample.unity | 1710 +++++++++++++++++ Scenes/VRMRuntimeLoaderSample.unity.meta | 8 + Scripts.meta | 10 + Scripts/BlendShape.meta | 10 + Scripts/BlendShape/AIUEO.cs | 79 + Scripts/BlendShape/AIUEO.cs.meta | 13 + Scripts/BlendShape/BlendShapeAvatar.cs | 78 + Scripts/BlendShape/BlendShapeAvatar.cs.meta | 13 + Scripts/BlendShape/BlendShapeClip.cs | 77 + Scripts/BlendShape/BlendShapeClip.cs.meta | 13 + Scripts/BlendShape/BlendShapeClipHandler.cs | 52 + .../BlendShape/BlendShapeClipHandler.cs.meta | 12 + Scripts/BlendShape/BlendShapeKey.cs | 96 + Scripts/BlendShape/BlendShapeKey.cs.meta | 12 + Scripts/BlendShape/Blinker.cs | 116 ++ Scripts/BlendShape/Blinker.cs.meta | 13 + Scripts/BlendShape/Editor.meta | 10 + Scripts/BlendShape/Editor/BlendShapeSlider.cs | 71 + .../Editor/BlendShapeSlider.cs.meta | 12 + .../Editor/VRMBlendShapeManipulatorEditor.cs | 157 ++ .../VRMBlendShapeManipulatorEditor.cs.meta | 13 + .../Editor/VRMBlnedShapeProxyEditor.cs | 360 ++++ .../Editor/VRMBlnedShapeProxyEditor.cs.meta | 13 + .../BlendShape/VRMBlendShapeManipulator.cs | 9 + .../VRMBlendShapeManipulator.cs.meta | 13 + Scripts/BlendShape/VRMBlendShapeProxy.cs | 93 + Scripts/BlendShape/VRMBlendShapeProxy.cs.meta | 13 + Scripts/Editor.meta | 9 + Scripts/Editor/Tests.meta | 9 + Scripts/Editor/Tests/VRMBlendShapeKeyTest.cs | 24 + .../Editor/Tests/VRMBlendShapeKeyTest.cs.meta | 12 + Scripts/Editor/VRMExportUnityPackage.cs | 55 + Scripts/Editor/VRMExportUnityPackage.cs.meta | 12 + Scripts/Editor/VRMMonoBehaviourComparator.cs | 30 + .../Editor/VRMMonoBehaviourComparator.cs.meta | 12 + Scripts/Editor/VRMTest.cs | 76 + Scripts/Editor/VRMTest.cs.meta | 12 + Scripts/FirstPerson.meta | 10 + Scripts/FirstPerson/Editor.meta | 9 + .../Editor/RendererFirstPersonFlagsDrawer.cs | 40 + .../RendererFirstPersonFlagsDrawer.cs.meta | 12 + Scripts/FirstPerson/VRMFirstPerson.cs | 210 ++ Scripts/FirstPerson/VRMFirstPerson.cs.meta | 13 + .../VRMFirstPersonCameraManager.cs | 91 + .../VRMFirstPersonCameraManager.cs.meta | 13 + Scripts/Format.meta | 10 + Scripts/Format/Editor.meta | 10 + Scripts/Format/Editor/VRMAssetWriter.cs | 212 ++ Scripts/Format/Editor/VRMAssetWriter.cs.meta | 12 + Scripts/Format/Editor/VRMExporter.cs | 219 +++ Scripts/Format/Editor/VRMExporter.cs.meta | 13 + Scripts/Format/Editor/VRMExporterMenu.cs | 124 ++ Scripts/Format/Editor/VRMExporterMenu.cs.meta | 12 + .../Editor/VRMHumanoidNormalizerMenu.cs | 162 ++ .../Editor/VRMHumanoidNormalizerMenu.cs.meta | 12 + Scripts/Format/Editor/VRMImporterMenu.cs | 54 + Scripts/Format/Editor/VRMImporterMenu.cs.meta | 13 + Scripts/Format/Editor/VRMVersionMenu.cs | 46 + Scripts/Format/Editor/VRMVersionMenu.cs.meta | 13 + .../Format/Editor/vrmAssetPostprocessor.cs | 49 + .../Editor/vrmAssetPostprocessor.cs.meta | 12 + Scripts/Format/VRMException.cs | 15 + Scripts/Format/VRMException.cs.meta | 12 + Scripts/Format/VRMFormat.cs | 57 + Scripts/Format/VRMFormat.cs.meta | 13 + Scripts/Format/VRMImporter.cs | 661 +++++++ Scripts/Format/VRMImporter.cs.meta | 13 + Scripts/Format/VRMImporterContext.cs | 43 + Scripts/Format/VRMImporterContext.cs.meta | 12 + Scripts/Format/VRMVersion.cs | 14 + Scripts/Format/VRMVersion.cs.meta | 13 + Scripts/Format/glTF_VRM_BlendShape.cs | 146 ++ Scripts/Format/glTF_VRM_BlendShape.cs.meta | 13 + Scripts/Format/glTF_VRM_FirstPerson.cs | 85 + Scripts/Format/glTF_VRM_FirstPerson.cs.meta | 13 + Scripts/Format/glTF_VRM_Humanoid.cs | 221 +++ Scripts/Format/glTF_VRM_Humanoid.cs.meta | 13 + Scripts/Format/glTF_VRM_Material.cs | 183 ++ Scripts/Format/glTF_VRM_Material.cs.meta | 12 + Scripts/Format/glTF_VRM_Meta.cs | 71 + Scripts/Format/glTF_VRM_Meta.cs.meta | 12 + Scripts/Format/glTF_VRM_SecondaryAnimation.cs | 75 + .../glTF_VRM_SecondaryAnimation.cs.meta | 12 + Scripts/Humanoid.meta | 9 + Scripts/Humanoid/VRMHumanoidDescription.cs | 56 + .../Humanoid/VRMHumanoidDescription.cs.meta | 12 + Scripts/LookAt.meta | 10 + Scripts/LookAt/CurveMapper.cs | 63 + Scripts/LookAt/CurveMapper.cs.meta | 12 + Scripts/LookAt/Editor.meta | 10 + Scripts/LookAt/Editor/VRMLookAtHeadEditor.cs | 60 + .../LookAt/Editor/VRMLookAtHeadEditor.cs.meta | 13 + Scripts/LookAt/LookTarget.cs | 36 + Scripts/LookAt/LookTarget.cs.meta | 12 + Scripts/LookAt/Matrix4x4Extensions.cs | 38 + Scripts/LookAt/Matrix4x4Extensions.cs.meta | 13 + Scripts/LookAt/OffsetOnTransform.cs | 52 + Scripts/LookAt/OffsetOnTransform.cs.meta | 13 + Scripts/LookAt/VRMLookAt.cs | 252 +++ Scripts/LookAt/VRMLookAt.cs.meta | 13 + Scripts/LookAt/VRMLookAtBlendShapeApplyer.cs | 74 + .../LookAt/VRMLookAtBlendShapeApplyer.cs.meta | 13 + Scripts/LookAt/VRMLookAtBoneApplyer.cs | 133 ++ Scripts/LookAt/VRMLookAtBoneApplyer.cs.meta | 13 + Scripts/LookAt/VRMLookAtHead.cs | 161 ++ Scripts/LookAt/VRMLookAtHead.cs.meta | 13 + Scripts/Meta.meta | 9 + Scripts/Meta/VRMMetaInformation.cs | 106 + Scripts/Meta/VRMMetaInformation.cs.meta | 12 + Scripts/RuntimeLoader.meta | 9 + Scripts/RuntimeLoader/CanvasManager.cs | 22 + Scripts/RuntimeLoader/CanvasManager.cs.meta | 12 + Scripts/RuntimeLoader/VRMRuntimeLoader.cs | 231 +++ .../RuntimeLoader/VRMRuntimeLoader.cs.meta | 12 + Scripts/SkinnedMeshUtility.meta | 9 + Scripts/SkinnedMeshUtility/BoneMeshEraser.cs | 115 ++ .../SkinnedMeshUtility/BoneMeshEraser.cs.meta | 13 + Scripts/SkinnedMeshUtility/Editor.meta | 10 + .../Editor/BoneMeshEraserWizard.cs | 200 ++ .../Editor/BoneMeshEraserWizard.cs.meta | 13 + .../Editor/BoneNormalizer.cs | 238 +++ .../Editor/BoneNormalizer.cs.meta | 13 + .../Editor/MeshIntegrator.cs | 359 ++++ .../Editor/MeshIntegrator.cs.meta | 13 + .../Editor/MeshIntegratorWizard.cs | 174 ++ .../Editor/MeshIntegratorWizard.cs.meta | 13 + .../SkinnedMeshUtility/VRMBindposeGizmo.cs | 158 ++ .../VRMBindposeGizmo.cs.meta | 13 + Scripts/SpringBone.meta | 10 + Scripts/SpringBone/Editor.meta | 9 + .../VRMSpringBoneColliderGroupEditor.cs | 42 + .../VRMSpringBoneColliderGroupEditor.cs.meta | 12 + Scripts/SpringBone/VRMSpringBone.cs | 305 +++ Scripts/SpringBone/VRMSpringBone.cs.meta | 13 + .../SpringBone/VRMSpringBoneColliderGroup.cs | 39 + .../VRMSpringBoneColliderGroup.cs.meta | 13 + Scripts/UniTask.meta | 9 + Scripts/UniTask/Functor.cs | 177 ++ Scripts/UniTask/Functor.cs.meta | 12 + Scripts/UniTask/LockQueue.cs | 56 + Scripts/UniTask/LockQueue.cs.meta | 12 + Scripts/UniTask/MainThreadDispatcher.cs | 181 ++ Scripts/UniTask/MainThreadDispatcher.cs.meta | 12 + Scripts/UniTask/MonitorQueue.cs | 48 + Scripts/UniTask/MonitorQueue.cs.meta | 12 + Scripts/UniTask/Schedulable.cs | 227 +++ Scripts/UniTask/Schedulable.cs.meta | 12 + Scripts/UniTask/Scheduler.cs | 7 + Scripts/UniTask/Scheduler.cs.meta | 12 + Scripts/UniTask/StepScheduler.cs | 30 + Scripts/UniTask/StepScheduler.cs.meta | 12 + Scripts/UniTask/TaskChain.cs | 91 + Scripts/UniTask/TaskChain.cs.meta | 12 + Scripts/UniTask/ThreadScheduler.cs | 89 + Scripts/UniTask/ThreadScheduler.cs.meta | 12 + Scripts/UniTask/Unit.cs | 41 + Scripts/UniTask/Unit.cs.meta | 12 + 158 files changed, 10771 insertions(+) create mode 100644 Scenes.meta create mode 100644 Scenes/VRMRuntimeLoaderSample.unity create mode 100644 Scenes/VRMRuntimeLoaderSample.unity.meta create mode 100644 Scripts.meta create mode 100644 Scripts/BlendShape.meta create mode 100644 Scripts/BlendShape/AIUEO.cs create mode 100644 Scripts/BlendShape/AIUEO.cs.meta create mode 100644 Scripts/BlendShape/BlendShapeAvatar.cs create mode 100644 Scripts/BlendShape/BlendShapeAvatar.cs.meta create mode 100644 Scripts/BlendShape/BlendShapeClip.cs create mode 100644 Scripts/BlendShape/BlendShapeClip.cs.meta create mode 100644 Scripts/BlendShape/BlendShapeClipHandler.cs create mode 100644 Scripts/BlendShape/BlendShapeClipHandler.cs.meta create mode 100644 Scripts/BlendShape/BlendShapeKey.cs create mode 100644 Scripts/BlendShape/BlendShapeKey.cs.meta create mode 100644 Scripts/BlendShape/Blinker.cs create mode 100644 Scripts/BlendShape/Blinker.cs.meta create mode 100644 Scripts/BlendShape/Editor.meta create mode 100644 Scripts/BlendShape/Editor/BlendShapeSlider.cs create mode 100644 Scripts/BlendShape/Editor/BlendShapeSlider.cs.meta create mode 100644 Scripts/BlendShape/Editor/VRMBlendShapeManipulatorEditor.cs create mode 100644 Scripts/BlendShape/Editor/VRMBlendShapeManipulatorEditor.cs.meta create mode 100644 Scripts/BlendShape/Editor/VRMBlnedShapeProxyEditor.cs create mode 100644 Scripts/BlendShape/Editor/VRMBlnedShapeProxyEditor.cs.meta create mode 100644 Scripts/BlendShape/VRMBlendShapeManipulator.cs create mode 100644 Scripts/BlendShape/VRMBlendShapeManipulator.cs.meta create mode 100644 Scripts/BlendShape/VRMBlendShapeProxy.cs create mode 100644 Scripts/BlendShape/VRMBlendShapeProxy.cs.meta create mode 100644 Scripts/Editor.meta create mode 100644 Scripts/Editor/Tests.meta create mode 100644 Scripts/Editor/Tests/VRMBlendShapeKeyTest.cs create mode 100644 Scripts/Editor/Tests/VRMBlendShapeKeyTest.cs.meta create mode 100644 Scripts/Editor/VRMExportUnityPackage.cs create mode 100644 Scripts/Editor/VRMExportUnityPackage.cs.meta create mode 100644 Scripts/Editor/VRMMonoBehaviourComparator.cs create mode 100644 Scripts/Editor/VRMMonoBehaviourComparator.cs.meta create mode 100644 Scripts/Editor/VRMTest.cs create mode 100644 Scripts/Editor/VRMTest.cs.meta create mode 100644 Scripts/FirstPerson.meta create mode 100644 Scripts/FirstPerson/Editor.meta create mode 100644 Scripts/FirstPerson/Editor/RendererFirstPersonFlagsDrawer.cs create mode 100644 Scripts/FirstPerson/Editor/RendererFirstPersonFlagsDrawer.cs.meta create mode 100644 Scripts/FirstPerson/VRMFirstPerson.cs create mode 100644 Scripts/FirstPerson/VRMFirstPerson.cs.meta create mode 100644 Scripts/FirstPerson/VRMFirstPersonCameraManager.cs create mode 100644 Scripts/FirstPerson/VRMFirstPersonCameraManager.cs.meta create mode 100644 Scripts/Format.meta create mode 100644 Scripts/Format/Editor.meta create mode 100644 Scripts/Format/Editor/VRMAssetWriter.cs create mode 100644 Scripts/Format/Editor/VRMAssetWriter.cs.meta create mode 100644 Scripts/Format/Editor/VRMExporter.cs create mode 100644 Scripts/Format/Editor/VRMExporter.cs.meta create mode 100644 Scripts/Format/Editor/VRMExporterMenu.cs create mode 100644 Scripts/Format/Editor/VRMExporterMenu.cs.meta create mode 100644 Scripts/Format/Editor/VRMHumanoidNormalizerMenu.cs create mode 100644 Scripts/Format/Editor/VRMHumanoidNormalizerMenu.cs.meta create mode 100644 Scripts/Format/Editor/VRMImporterMenu.cs create mode 100644 Scripts/Format/Editor/VRMImporterMenu.cs.meta create mode 100644 Scripts/Format/Editor/VRMVersionMenu.cs create mode 100644 Scripts/Format/Editor/VRMVersionMenu.cs.meta create mode 100644 Scripts/Format/Editor/vrmAssetPostprocessor.cs create mode 100644 Scripts/Format/Editor/vrmAssetPostprocessor.cs.meta create mode 100644 Scripts/Format/VRMException.cs create mode 100644 Scripts/Format/VRMException.cs.meta create mode 100644 Scripts/Format/VRMFormat.cs create mode 100644 Scripts/Format/VRMFormat.cs.meta create mode 100644 Scripts/Format/VRMImporter.cs create mode 100644 Scripts/Format/VRMImporter.cs.meta create mode 100644 Scripts/Format/VRMImporterContext.cs create mode 100644 Scripts/Format/VRMImporterContext.cs.meta create mode 100644 Scripts/Format/VRMVersion.cs create mode 100644 Scripts/Format/VRMVersion.cs.meta create mode 100644 Scripts/Format/glTF_VRM_BlendShape.cs create mode 100644 Scripts/Format/glTF_VRM_BlendShape.cs.meta create mode 100644 Scripts/Format/glTF_VRM_FirstPerson.cs create mode 100644 Scripts/Format/glTF_VRM_FirstPerson.cs.meta create mode 100644 Scripts/Format/glTF_VRM_Humanoid.cs create mode 100644 Scripts/Format/glTF_VRM_Humanoid.cs.meta create mode 100644 Scripts/Format/glTF_VRM_Material.cs create mode 100644 Scripts/Format/glTF_VRM_Material.cs.meta create mode 100644 Scripts/Format/glTF_VRM_Meta.cs create mode 100644 Scripts/Format/glTF_VRM_Meta.cs.meta create mode 100644 Scripts/Format/glTF_VRM_SecondaryAnimation.cs create mode 100644 Scripts/Format/glTF_VRM_SecondaryAnimation.cs.meta create mode 100644 Scripts/Humanoid.meta create mode 100644 Scripts/Humanoid/VRMHumanoidDescription.cs create mode 100644 Scripts/Humanoid/VRMHumanoidDescription.cs.meta create mode 100644 Scripts/LookAt.meta create mode 100644 Scripts/LookAt/CurveMapper.cs create mode 100644 Scripts/LookAt/CurveMapper.cs.meta create mode 100644 Scripts/LookAt/Editor.meta create mode 100644 Scripts/LookAt/Editor/VRMLookAtHeadEditor.cs create mode 100644 Scripts/LookAt/Editor/VRMLookAtHeadEditor.cs.meta create mode 100644 Scripts/LookAt/LookTarget.cs create mode 100644 Scripts/LookAt/LookTarget.cs.meta create mode 100644 Scripts/LookAt/Matrix4x4Extensions.cs create mode 100644 Scripts/LookAt/Matrix4x4Extensions.cs.meta create mode 100644 Scripts/LookAt/OffsetOnTransform.cs create mode 100644 Scripts/LookAt/OffsetOnTransform.cs.meta create mode 100644 Scripts/LookAt/VRMLookAt.cs create mode 100644 Scripts/LookAt/VRMLookAt.cs.meta create mode 100644 Scripts/LookAt/VRMLookAtBlendShapeApplyer.cs create mode 100644 Scripts/LookAt/VRMLookAtBlendShapeApplyer.cs.meta create mode 100644 Scripts/LookAt/VRMLookAtBoneApplyer.cs create mode 100644 Scripts/LookAt/VRMLookAtBoneApplyer.cs.meta create mode 100644 Scripts/LookAt/VRMLookAtHead.cs create mode 100644 Scripts/LookAt/VRMLookAtHead.cs.meta create mode 100644 Scripts/Meta.meta create mode 100644 Scripts/Meta/VRMMetaInformation.cs create mode 100644 Scripts/Meta/VRMMetaInformation.cs.meta create mode 100644 Scripts/RuntimeLoader.meta create mode 100644 Scripts/RuntimeLoader/CanvasManager.cs create mode 100644 Scripts/RuntimeLoader/CanvasManager.cs.meta create mode 100644 Scripts/RuntimeLoader/VRMRuntimeLoader.cs create mode 100644 Scripts/RuntimeLoader/VRMRuntimeLoader.cs.meta create mode 100644 Scripts/SkinnedMeshUtility.meta create mode 100644 Scripts/SkinnedMeshUtility/BoneMeshEraser.cs create mode 100644 Scripts/SkinnedMeshUtility/BoneMeshEraser.cs.meta create mode 100644 Scripts/SkinnedMeshUtility/Editor.meta create mode 100644 Scripts/SkinnedMeshUtility/Editor/BoneMeshEraserWizard.cs create mode 100644 Scripts/SkinnedMeshUtility/Editor/BoneMeshEraserWizard.cs.meta create mode 100644 Scripts/SkinnedMeshUtility/Editor/BoneNormalizer.cs create mode 100644 Scripts/SkinnedMeshUtility/Editor/BoneNormalizer.cs.meta create mode 100644 Scripts/SkinnedMeshUtility/Editor/MeshIntegrator.cs create mode 100644 Scripts/SkinnedMeshUtility/Editor/MeshIntegrator.cs.meta create mode 100644 Scripts/SkinnedMeshUtility/Editor/MeshIntegratorWizard.cs create mode 100644 Scripts/SkinnedMeshUtility/Editor/MeshIntegratorWizard.cs.meta create mode 100644 Scripts/SkinnedMeshUtility/VRMBindposeGizmo.cs create mode 100644 Scripts/SkinnedMeshUtility/VRMBindposeGizmo.cs.meta create mode 100644 Scripts/SpringBone.meta create mode 100644 Scripts/SpringBone/Editor.meta create mode 100644 Scripts/SpringBone/Editor/VRMSpringBoneColliderGroupEditor.cs create mode 100644 Scripts/SpringBone/Editor/VRMSpringBoneColliderGroupEditor.cs.meta create mode 100644 Scripts/SpringBone/VRMSpringBone.cs create mode 100644 Scripts/SpringBone/VRMSpringBone.cs.meta create mode 100644 Scripts/SpringBone/VRMSpringBoneColliderGroup.cs create mode 100644 Scripts/SpringBone/VRMSpringBoneColliderGroup.cs.meta create mode 100644 Scripts/UniTask.meta create mode 100644 Scripts/UniTask/Functor.cs create mode 100644 Scripts/UniTask/Functor.cs.meta create mode 100644 Scripts/UniTask/LockQueue.cs create mode 100644 Scripts/UniTask/LockQueue.cs.meta create mode 100644 Scripts/UniTask/MainThreadDispatcher.cs create mode 100644 Scripts/UniTask/MainThreadDispatcher.cs.meta create mode 100644 Scripts/UniTask/MonitorQueue.cs create mode 100644 Scripts/UniTask/MonitorQueue.cs.meta create mode 100644 Scripts/UniTask/Schedulable.cs create mode 100644 Scripts/UniTask/Schedulable.cs.meta create mode 100644 Scripts/UniTask/Scheduler.cs create mode 100644 Scripts/UniTask/Scheduler.cs.meta create mode 100644 Scripts/UniTask/StepScheduler.cs create mode 100644 Scripts/UniTask/StepScheduler.cs.meta create mode 100644 Scripts/UniTask/TaskChain.cs create mode 100644 Scripts/UniTask/TaskChain.cs.meta create mode 100644 Scripts/UniTask/ThreadScheduler.cs create mode 100644 Scripts/UniTask/ThreadScheduler.cs.meta create mode 100644 Scripts/UniTask/Unit.cs create mode 100644 Scripts/UniTask/Unit.cs.meta diff --git a/Scenes.meta b/Scenes.meta new file mode 100644 index 000000000..8a58b5a55 --- /dev/null +++ b/Scenes.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: c58829edf15349648929208fdb1c42ca +folderAsset: yes +timeCreated: 1519303162 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scenes/VRMRuntimeLoaderSample.unity b/Scenes/VRMRuntimeLoaderSample.unity new file mode 100644 index 000000000..e8e723af3 --- /dev/null +++ b/Scenes/VRMRuntimeLoaderSample.unity @@ -0,0 +1,1710 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 8 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_GIWorkflowMode: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_TemporalCoherenceThreshold: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 1 + m_LightmapEditorSettings: + serializedVersion: 8 + m_Resolution: 2 + m_BakeResolution: 40 + m_TextureWidth: 1024 + m_TextureHeight: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFiltering: 0 + m_PVRFilteringMode: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousColorSigma: 1 + m_PVRFilteringAtrousNormalSigma: 1 + m_PVRFilteringAtrousPositionSigma: 1 + m_LightingDataAsset: {fileID: 0} + m_ShadowMaskMode: 2 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &147376043 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 147376044} + - component: {fileID: 147376046} + - component: {fileID: 147376045} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &147376044 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 147376043} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2108006564} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: -88.7, y: -23.7} + m_SizeDelta: {x: 177.4, y: 47.4} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &147376045 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 147376043} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 32 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 3 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: FirstPerson +--- !u!222 &147376046 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 147376043} +--- !u!1 &267321008 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 267321009} + - component: {fileID: 267321012} + - component: {fileID: 267321011} + - component: {fileID: 267321010} + m_Layer: 5 + m_Name: BottomLeft + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &267321009 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 267321008} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2036452538} + - {fileID: 555566559} + m_Father: {fileID: 2082684587} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &267321010 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 267321008} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1297475563, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 0 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 +--- !u!114 &267321011 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 267321008} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 0.392} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 +--- !u!222 &267321012 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 267321008} +--- !u!1 &283664911 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 283664914} + - component: {fileID: 283664913} + - component: {fileID: 283664912} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &283664912 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 283664911} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &283664913 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 283664911} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &283664914 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 283664911} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &555566558 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 555566559} + - component: {fileID: 555566562} + - component: {fileID: 555566561} + - component: {fileID: 555566560} + m_Layer: 5 + m_Name: LoadBVH + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &555566559 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 555566558} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 605703266} + m_Father: {fileID: 267321009} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &555566560 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 555566558} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 555566561} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &555566561 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 555566558} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 +--- !u!222 &555566562 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 555566558} +--- !u!1 &568975773 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 568975775} + - component: {fileID: 568975774} + m_Layer: 0 + m_Name: CameraManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &568975774 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 568975773} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6b34fb2c039c3ce4881f04e476a2128f, type: 3} + m_Name: + m_EditorClassIdentifier: + m_topLeft: + Camera: {fileID: 1468129204} + Texture: {fileID: 0} + Image: {fileID: 2108006565} + m_topRight: + Camera: {fileID: 772693251} + Texture: {fileID: 0} + Image: {fileID: 635962097} + m_bottomRight: + Camera: {fileID: 1919635067} + Texture: {fileID: 0} + Image: {fileID: 991744090} + m_firstPersonCamera: {fileID: 1468129204} + m_thirdPersonCameras: + - {fileID: 1919635067} + - {fileID: 772693251} +--- !u!4 &568975775 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 568975773} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1468129205} + - {fileID: 772693254} + - {fileID: 1919635063} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &605703265 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 605703266} + - component: {fileID: 605703268} + - component: {fileID: 605703267} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &605703266 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 605703265} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 555566559} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &605703267 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 605703265} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Load BVH +--- !u!222 &605703268 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 605703265} +--- !u!1 &635962095 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 635962096} + - component: {fileID: 635962098} + - component: {fileID: 635962097} + m_Layer: 5 + m_Name: TopRight + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &635962096 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 635962095} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 646222219} + m_Father: {fileID: 2082684587} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &635962097 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 635962095} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -98529514, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Texture: {fileID: 0} + m_UVRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 +--- !u!222 &635962098 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 635962095} +--- !u!1 &646222218 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 646222219} + - component: {fileID: 646222221} + - component: {fileID: 646222220} + m_Layer: 5 + m_Name: Text (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &646222219 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 646222218} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 635962096} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 88.7, y: -23.700012} + m_SizeDelta: {x: 177.4, y: 47.4} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &646222220 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 646222218} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 32 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 3 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: ThirdPerson +--- !u!222 &646222221 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 646222218} +--- !u!1 &772693250 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 772693254} + - component: {fileID: 772693251} + - component: {fileID: 772693253} + - component: {fileID: 772693252} + m_Layer: 0 + m_Name: OutPov + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!20 &772693251 +Camera: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 772693250} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294966783 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 + m_StereoMirrorMode: 0 +--- !u!81 &772693252 +AudioListener: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 772693250} + m_Enabled: 0 +--- !u!124 &772693253 +Behaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 772693250} + m_Enabled: 0 +--- !u!4 &772693254 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 772693250} + m_LocalRotation: {x: 0, y: 1, z: 0, w: 0} + m_LocalPosition: {x: 0, y: 1.2, z: 1} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 568975775} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!1 &936781945 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 936781946} + - component: {fileID: 936781948} + - component: {fileID: 936781947} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &936781946 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 936781945} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2036452538} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &936781947 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 936781945} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Load VRM +--- !u!222 &936781948 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 936781945} +--- !u!1 &991744088 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 991744089} + - component: {fileID: 991744091} + - component: {fileID: 991744090} + m_Layer: 5 + m_Name: BottomRight + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &991744089 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 991744088} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1382317302} + m_Father: {fileID: 2082684587} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &991744090 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 991744088} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -98529514, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Texture: {fileID: 0} + m_UVRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 +--- !u!222 &991744091 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 991744088} +--- !u!1 &1148284494 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1148284495} + - component: {fileID: 1148284496} + m_Layer: 0 + m_Name: VRMRuntimeLoader + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1148284495 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1148284494} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1148284496 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1148284494} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 03b059a6d90275246ba8622ac40a63dc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_canvas: {fileID: 2082684588} + m_faceCamera: {fileID: 1919635064} + m_source: {fileID: 0} + m_target: {fileID: 0} + m_firstPerson: {fileID: 0} +--- !u!1 &1175289393 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1175289395} + - component: {fileID: 1175289394} + m_Layer: 0 + m_Name: Directional light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1175289394 +Light: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1175289393} + m_Enabled: 1 + serializedVersion: 8 + m_Type: 1 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 0.33 + m_Range: 10 + m_SpotAngle: 30 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_Lightmapping: 4 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1175289395 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1175289393} + m_LocalRotation: {x: 0.2571214, y: -0.8612099, z: 0.4380491, w: 0.017861776} + m_LocalPosition: {x: 2.84, y: 1.7, z: 2.02} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 130.209, y: -17.533997, z: 138.566} +--- !u!1 &1382317301 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1382317302} + - component: {fileID: 1382317304} + - component: {fileID: 1382317303} + m_Layer: 5 + m_Name: Text (2) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1382317302 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1382317301} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 991744089} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 242.4, y: -23.699997} + m_SizeDelta: {x: 484.7, y: 47.4} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1382317303 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1382317301} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 32 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 3 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: ThirdPerson(BlendShapeCheck) +--- !u!222 &1382317304 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1382317301} +--- !u!1 &1396766179 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1396766183} + - component: {fileID: 1396766182} + - component: {fileID: 1396766181} + - component: {fileID: 1396766180} + m_Layer: 0 + m_Name: Plane + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &1396766180 +MeshRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1396766179} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!64 &1396766181 +MeshCollider: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1396766179} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Convex: 0 + m_InflateMesh: 0 + m_SkinWidth: 0.01 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &1396766182 +MeshFilter: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1396766179} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1396766183 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1396766179} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 1.41} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1468129200 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1468129205} + - component: {fileID: 1468129204} + - component: {fileID: 1468129203} + - component: {fileID: 1468129202} + - component: {fileID: 1468129201} + m_Layer: 0 + m_Name: FirstPerson + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1468129201 +AudioListener: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1468129200} + m_Enabled: 0 +--- !u!92 &1468129202 +Behaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1468129200} + m_Enabled: 0 +--- !u!124 &1468129203 +Behaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1468129200} + m_Enabled: 0 +--- !u!20 &1468129204 +Camera: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1468129200} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294966271 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 + m_StereoMirrorMode: 0 +--- !u!4 &1468129205 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1468129200} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1.13, z: -1.29} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 568975775} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1919635062 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1919635063} + - component: {fileID: 1919635067} + - component: {fileID: 1919635066} + - component: {fileID: 1919635065} + - component: {fileID: 1919635064} + m_Layer: 0 + m_Name: OutFace + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1919635063 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1919635062} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: -0.261, y: 1.497, z: 0.048} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 568975775} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!114 &1919635064 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1919635062} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d1cc319f70f55264eb38d1959c4222c6, type: 3} + m_Name: + m_EditorClassIdentifier: + Target: {fileID: 0} + m_offset: {x: 0, y: 0.05, z: 0} + m_distance: 0.7 + m_offsetTransform: + Transform: {fileID: 0} + OffsetRotation: + e00: 0 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 0 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 0 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 0 +--- !u!81 &1919635065 +AudioListener: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1919635062} + m_Enabled: 0 +--- !u!124 &1919635066 +Behaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1919635062} + m_Enabled: 0 +--- !u!20 &1919635067 +Camera: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1919635062} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.01 + far clip plane: 2 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294966783 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 + m_StereoMirrorMode: 0 +--- !u!1 &2036452537 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 2036452538} + - component: {fileID: 2036452541} + - component: {fileID: 2036452540} + - component: {fileID: 2036452539} + m_Layer: 5 + m_Name: LoadVRM + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2036452538 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2036452537} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 936781946} + m_Father: {fileID: 267321009} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2036452539 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2036452537} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 2036452540} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &2036452540 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2036452537} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 +--- !u!222 &2036452541 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2036452537} +--- !u!1 &2082684583 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 2082684587} + - component: {fileID: 2082684586} + - component: {fileID: 2082684585} + - component: {fileID: 2082684584} + - component: {fileID: 2082684588} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2082684584 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2082684583} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &2082684585 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2082684583} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!223 &2082684586 +Canvas: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2082684583} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &2082684587 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2082684583} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 2108006564} + - {fileID: 635962096} + - {fileID: 991744089} + - {fileID: 267321009} + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &2082684588 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2082684583} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1ae08a6ba07c0864c9132bc8a004030d, type: 3} + m_Name: + m_EditorClassIdentifier: + LoadVRMButton: {fileID: 2036452539} + LoadBVHButton: {fileID: 555566560} +--- !u!1 &2108006563 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 2108006564} + - component: {fileID: 2108006566} + - component: {fileID: 2108006565} + m_Layer: 5 + m_Name: TopLeft + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2108006564 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2108006563} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 147376044} + m_Father: {fileID: 2082684587} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0.5, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &2108006565 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2108006563} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -98529514, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Texture: {fileID: 0} + m_UVRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 +--- !u!222 &2108006566 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2108006563} diff --git a/Scenes/VRMRuntimeLoaderSample.unity.meta b/Scenes/VRMRuntimeLoaderSample.unity.meta new file mode 100644 index 000000000..d23b8211a --- /dev/null +++ b/Scenes/VRMRuntimeLoaderSample.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cb6ff948a1027244a86abf24f3445a87 +timeCreated: 1520832729 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts.meta b/Scripts.meta new file mode 100644 index 000000000..96afb8fa6 --- /dev/null +++ b/Scripts.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 2f85d3d3cb76658408fd936e3b798481 +folderAsset: yes +timeCreated: 1517228412 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape.meta b/Scripts/BlendShape.meta new file mode 100644 index 000000000..88f909901 --- /dev/null +++ b/Scripts/BlendShape.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 0604208c180cfea44878a6962ab134b3 +folderAsset: yes +timeCreated: 1517402736 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/AIUEO.cs b/Scripts/BlendShape/AIUEO.cs new file mode 100644 index 000000000..db0261327 --- /dev/null +++ b/Scripts/BlendShape/AIUEO.cs @@ -0,0 +1,79 @@ +using System.Collections; +using UnityEngine; + + +namespace VRM +{ + public class AIUEO : MonoBehaviour + { + [SerializeField] + public VRMBlendShapeProxy BlendShapes; + private void Reset() + { + BlendShapes = GetComponent(); + } + + BlendShapeClipHandler m_appyerA; + BlendShapeClipHandler m_appyerI; + BlendShapeClipHandler m_appyerU; + BlendShapeClipHandler m_appyerE; + BlendShapeClipHandler m_appyerO; + + Coroutine m_coroutine; + + [SerializeField] + float m_wait = 0.5f; + + private void Awake() + { + if (BlendShapes == null) BlendShapes = GetComponent(); + if (BlendShapes == null) return; + if (BlendShapes.BlendShapeAvatar == null) return; + var avatar = BlendShapes.BlendShapeAvatar; + + m_appyerA = new BlendShapeClipHandler(avatar.GetClip("A"), transform); + m_appyerI = new BlendShapeClipHandler(avatar.GetClip("I"), transform); + m_appyerU = new BlendShapeClipHandler(avatar.GetClip("U"), transform); + m_appyerE = new BlendShapeClipHandler(avatar.GetClip("E"), transform); + m_appyerO = new BlendShapeClipHandler(avatar.GetClip("O"), transform); + } + + IEnumerator Routine() + { + while (true) + { + yield return new WaitForSeconds(1.0f); + + if (m_appyerA != null) m_appyerA.Apply(1.0f); + yield return new WaitForSeconds(m_wait); + if (m_appyerA != null) m_appyerA.Apply(0); + + if (m_appyerI != null) m_appyerI.Apply(1.0f); + yield return new WaitForSeconds(m_wait); + if (m_appyerI != null) m_appyerI.Apply(0); + + if (m_appyerU != null) m_appyerU.Apply(1.0f); + yield return new WaitForSeconds(m_wait); + if (m_appyerU != null) m_appyerU.Apply(0); + + if (m_appyerE != null) m_appyerE.Apply(1.0f); + yield return new WaitForSeconds(m_wait); + if (m_appyerE != null) m_appyerE.Apply(0); + + if (m_appyerO != null) m_appyerO.Apply(1.0f); + yield return new WaitForSeconds(m_wait); + if (m_appyerO != null) m_appyerO.Apply(0); + } + } + + private void OnEnable() + { + m_coroutine = StartCoroutine(Routine()); + } + + private void OnDisable() + { + StopCoroutine(m_coroutine); + } + } +} diff --git a/Scripts/BlendShape/AIUEO.cs.meta b/Scripts/BlendShape/AIUEO.cs.meta new file mode 100644 index 000000000..d245454c5 --- /dev/null +++ b/Scripts/BlendShape/AIUEO.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: b62ca4f3096cada41938f18e4a02d8dc +timeCreated: 1517463794 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/BlendShapeAvatar.cs b/Scripts/BlendShape/BlendShapeAvatar.cs new file mode 100644 index 000000000..aa904cead --- /dev/null +++ b/Scripts/BlendShape/BlendShapeAvatar.cs @@ -0,0 +1,78 @@ +using UnityEngine; +using System.Linq; +using System; +using System.Collections.Generic; + + +namespace VRM +{ + [CreateAssetMenu(menuName = "VRM/BlendShapeAvatar")] + public class BlendShapeAvatar : ScriptableObject + { + [SerializeField] + public List Clips = new List(); + + public void CreateDefault() + { + foreach (BlendShapePreset preset in Enum.GetValues(typeof(BlendShapePreset))) + { + if (preset != BlendShapePreset.Unknown) + { + var clip = GetClip(preset); + if (clip == null) + { + clip = ScriptableObject.CreateInstance(); + clip.name = preset.ToString(); + clip.BlendShapeName = preset.ToString(); + Clips.Add(clip); + } + } + } + } + + public void SetClip(BlendShapeKey key, BlendShapeClip clip) + { + int index = -1; + try + { + index = Clips.FindIndex(x => key.Match(x)); + } + catch (Exception) + { + + } + if (index == -1) + { + Clips.Add(clip); + } + else + { + Clips[index] = clip; + } + } + + public BlendShapeClip GetClip(BlendShapeKey key) + { + if (Clips == null) return null; + return Clips.FirstOrDefault(x => key.Match(x)); + } + + public BlendShapeClip GetClip(BlendShapePreset preset) + { + return GetClip(new BlendShapeKey(preset)); + } + + public BlendShapeClip GetClip(String name) + { + return GetClip(new BlendShapeKey(name)); + } + + public bool Apply(string name, Transform transform, float value) + { + var clip = GetClip(name); + if (clip == null) return false; + clip.Apply(transform, value); + return true; + } + } +} diff --git a/Scripts/BlendShape/BlendShapeAvatar.cs.meta b/Scripts/BlendShape/BlendShapeAvatar.cs.meta new file mode 100644 index 000000000..e67352a91 --- /dev/null +++ b/Scripts/BlendShape/BlendShapeAvatar.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 329dca3bf78fcdd42b2df941673db76f +timeCreated: 1519195979 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/BlendShapeClip.cs b/Scripts/BlendShape/BlendShapeClip.cs new file mode 100644 index 000000000..ffc9e4428 --- /dev/null +++ b/Scripts/BlendShape/BlendShapeClip.cs @@ -0,0 +1,77 @@ +using System; +using System.Linq; +using UnityEngine; + + +namespace VRM +{ + [Serializable] + public struct BlendShapeBinding + { + public String RelativePath; + public int Index; + public float Weight; + } + + /* + public struct BlendShapeKey + { + public BlendShapePreset Preset; + public String Name; + + public BlendShapeKey(BlendShapePreset preset, String name) + { + Preset = preset; + Name = name.ToUpper(); + } + public BlendShapeKey(BlendShapePreset preset) + { + Preset = preset; + Name = preset.ToString().ToUpper(); + } + public BlendShapeKey(String name) + { + Preset = (BlendShapePreset)Enum.Parse(typeof(BlendShapePreset), name, true); + Name = name.ToUpper(); + } + } + */ + + [CreateAssetMenu(menuName = "VRM/BlendShapeClip")] + public class BlendShapeClip : ScriptableObject + { + [SerializeField] + public string BlendShapeName; + + [SerializeField] + public BlendShapePreset Preset; + + [SerializeField] + public BlendShapeBinding[] Values = new BlendShapeBinding[] { }; + + public void Apply(Transform root, float value) + { + if (Values != null) + { + foreach (var x in Values) + { + var target = root.Find(x.RelativePath); + if (target != null) + { + var sr = target.GetComponent(); + sr.SetBlendShapeWeight(x.Index, x.Weight * value); + } + } + } + } + + public static BlendShapeClip Create(BlendShapePreset preset) + { + var clip = ScriptableObject.CreateInstance(); + clip.Preset = preset; + clip.BlendShapeName = preset.ToString(); + clip.name = preset.ToString(); + return clip; + } + } +} diff --git a/Scripts/BlendShape/BlendShapeClip.cs.meta b/Scripts/BlendShape/BlendShapeClip.cs.meta new file mode 100644 index 000000000..cddffb589 --- /dev/null +++ b/Scripts/BlendShape/BlendShapeClip.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 37562b39ff933b245ac2f35d87edbcd6 +timeCreated: 1517402750 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/BlendShapeClipHandler.cs b/Scripts/BlendShape/BlendShapeClipHandler.cs new file mode 100644 index 000000000..7cfd8212b --- /dev/null +++ b/Scripts/BlendShape/BlendShapeClipHandler.cs @@ -0,0 +1,52 @@ +using UnityEngine; +using System.Linq; + + +namespace VRM +{ + public class BlendShapeClipHandler + { + BlendShapeClip m_clip; + public BlendShapeClip Cilp + { + get { return m_clip; } + } + SkinnedMeshRenderer[] m_renderers; + + public BlendShapeClipHandler(BlendShapeClip clip, Transform transform) + { + m_clip = clip; + + if (m_clip != null && m_clip.Values!=null && transform != null) + { + m_renderers = m_clip.Values.Select(x => + { + var target = UniGLTF.UnityExtensions.GetFromPath(transform, x.RelativePath); + return target.GetComponent(); + }) + .ToArray(); + } + } + + public float LastValue + { + get; + private set; + } + + public void Apply(float value) + { + LastValue = value; + + if (m_clip == null) return; + if (m_renderers == null) return; + + for (int i = 0; i < m_clip.Values.Length; ++i) + { + var binding = m_clip.Values[i]; + var target = m_renderers[i]; + target.SetBlendShapeWeight(binding.Index, binding.Weight * value); + } + } + } +} diff --git a/Scripts/BlendShape/BlendShapeClipHandler.cs.meta b/Scripts/BlendShape/BlendShapeClipHandler.cs.meta new file mode 100644 index 000000000..1b0a17fcf --- /dev/null +++ b/Scripts/BlendShape/BlendShapeClipHandler.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b93cb40fe6ff9ec4a8dcac1686f90ce8 +timeCreated: 1519729616 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/BlendShapeKey.cs b/Scripts/BlendShape/BlendShapeKey.cs new file mode 100644 index 000000000..c86669447 --- /dev/null +++ b/Scripts/BlendShape/BlendShapeKey.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; + +namespace VRM +{ + [Serializable] + public struct BlendShapeKey : IEquatable + { + public string Name; + public BlendShapePreset Preset; + + string m_id; + string ID + { + get + { + if (string.IsNullOrEmpty(m_id)) + { + if (Preset != BlendShapePreset.Unknown) + { + m_id = Preset.ToString().ToUpper(); + } + else + { + m_id = Name; + } + } + return m_id; + } + } + + public BlendShapeKey(string name) : this(name, BlendShapePreset.Unknown) + { + } + + public BlendShapeKey(BlendShapePreset preset) : this(preset.ToString(), BlendShapePreset.Unknown) + { + } + + public BlendShapeKey(string name, BlendShapePreset preset) + { + Name = name.ToUpper(); + Preset = preset; + if (Preset != BlendShapePreset.Unknown) + { + m_id = Preset.ToString().ToUpper(); + } + else + { + m_id = Name; + } + } + + public override string ToString() + { + return ID; + } + + public bool Equals(BlendShapeKey other) + { + /* + if (Preset != BlendShapePreset.Unknown && Preset == other.Preset) + { + // Unknown以外のPresetが一致したら一致とみなす + return true; + } + // .ToUpper()済み + return Name == other.Name; + */ + return ID == other.ID; + } + + public class CustomerEqualityComparer : IEqualityComparer + { + public bool Equals(BlendShapeKey x, BlendShapeKey y) + { + return x.Equals(y); + } + + public int GetHashCode(BlendShapeKey obj) + { + return obj.ToString().GetHashCode(); + } + } + + public static BlendShapeKey CreateFrom(BlendShapeClip clip) + { + return new BlendShapeKey(clip.BlendShapeName, clip.Preset); + } + + public bool Match(BlendShapeClip clip) + { + return this.Equals(CreateFrom(clip)); + } + } +} diff --git a/Scripts/BlendShape/BlendShapeKey.cs.meta b/Scripts/BlendShape/BlendShapeKey.cs.meta new file mode 100644 index 000000000..83719f7f0 --- /dev/null +++ b/Scripts/BlendShape/BlendShapeKey.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 273b1f57f417db8408c13673d45890ff +timeCreated: 1521727258 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/Blinker.cs b/Scripts/BlendShape/Blinker.cs new file mode 100644 index 000000000..1942c509f --- /dev/null +++ b/Scripts/BlendShape/Blinker.cs @@ -0,0 +1,116 @@ +using System.Collections; +using UnityEngine; + + +namespace VRM +{ + public class Blinker : MonoBehaviour + { + [SerializeField] + public VRMBlendShapeProxy BlendShapes; + private void Reset() + { + BlendShapes = GetComponent(); + } + + [SerializeField] + float m_interVal = 5.0f; + + [SerializeField] + float m_closingTime = 0.06f; + + [SerializeField] + float m_openingSeconds = 0.03f; + + [SerializeField] + float m_closeSeconds = 0.1f; + + Coroutine m_coroutine; + + static readonly string BLINK_NAME = BlendShapePreset.Blink.ToString(); + + IEnumerator BlinkRoutine() + { + while (true) + { + yield return new WaitForSeconds(Random.value * m_interVal); + + // close + var value = 0.0f; + var closeSpeed = 1.0f / m_closeSeconds; + while (true) + { + value += Time.deltaTime * closeSpeed; + if (value >= 1.0f) + { + break; + } + + BlendShapes.SetValue(BLINK_NAME, value); + yield return null; + } + BlendShapes.SetValue(BLINK_NAME, 1.0f); + + // wait... + yield return new WaitForSeconds(m_closingTime); + + // open + value = 1.0f; + var openSpeed = 1.0f / m_openingSeconds; + while (true) + { + value -= Time.deltaTime * openSpeed; + if (value < 0) + { + break; + } + + BlendShapes.SetValue(BLINK_NAME, value); + yield return null; + } + BlendShapes.SetValue(BLINK_NAME, 0); + } + } + + private void Start() + { + m_coroutine = StartCoroutine(BlinkRoutine()); + } + + private void Update() + { + /* + var weight = BlendShapes.GetWeightByFlags(BlendShapeFlags.Eye, m_key); + if (m_coroutine != null) + { + if (weight > 0) + { + Debug.LogFormat("[Blinker] cancel: {0}", BlendShapes.Status); + // まばたきキャンセル + StopCoroutine(m_coroutine); + m_coroutine = null; + BlendShapes.Set(m_key, 0); + } + } + else + { + if (weight == 0) + { + Debug.Log("[Blinker] start"); + // 開始 + m_coroutine = StartCoroutine(BlinkRoutine()); + } + } + */ + } + + private void OnDisable() + { + if (m_coroutine != null) + { + StopCoroutine(m_coroutine); + m_coroutine = null; + } + } + } +} diff --git a/Scripts/BlendShape/Blinker.cs.meta b/Scripts/BlendShape/Blinker.cs.meta new file mode 100644 index 000000000..73f197d4c --- /dev/null +++ b/Scripts/BlendShape/Blinker.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 69ea1f88e8d74e04e9341465573a4ef8 +timeCreated: 1517463794 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/Editor.meta b/Scripts/BlendShape/Editor.meta new file mode 100644 index 000000000..8ace96e8c --- /dev/null +++ b/Scripts/BlendShape/Editor.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 269b9c7394d16084a9e55528470e2ac7 +folderAsset: yes +timeCreated: 1517404636 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/Editor/BlendShapeSlider.cs b/Scripts/BlendShape/Editor/BlendShapeSlider.cs new file mode 100644 index 000000000..e883a4573 --- /dev/null +++ b/Scripts/BlendShape/Editor/BlendShapeSlider.cs @@ -0,0 +1,71 @@ +using UnityEditor; +using UnityEngine; + +namespace VRM +{ + class BlendShapeSlider + { + VRMBlendShapeProxy m_target; + BlendShapeKey m_key; + float? m_editorValue; + + public BlendShapeSlider(VRMBlendShapeProxy target, BlendShapeKey key) + { + m_target = target; + m_key = key; + } + + public void Slider() + { + if (m_target.BlendShapeAvatar == null) + { + return; + } + + var oldClip = m_target.BlendShapeAvatar.GetClip(m_key); + /*var newClip = (BlendShapeClip)*/EditorGUILayout.ObjectField(m_key.ToString(), oldClip, typeof(BlendShapeClip), true); + /* + if (oldClip != newClip) + { + m_target.BlendShapeAvatar.SetClip(m_key, newClip); + } + */ + + if (Application.isPlaying) + { + var oldValue = m_target.GetValue(m_key); + var newValue = EditorGUILayout.Slider(oldValue, 0, 1.0f); + if (oldValue != newValue) + { + m_target.SetValue(m_key, newValue); + } + } + else + { + var oldValue = m_editorValue.HasValue ? m_editorValue.Value : 0.0f; + var newValue = EditorGUILayout.Slider(oldValue, 0, 1.0f); + if (oldValue != newValue) + { + var clip = m_target.BlendShapeAvatar.GetClip(m_key); + if (clip != null) + { + clip.Apply(m_target.transform, newValue); + m_editorValue = newValue; + } + } + } + } + + public void RestoreEditorValue() + { + if (m_editorValue.HasValue) + { + var clip = m_target.BlendShapeAvatar.GetClip(m_key); + if (clip != null) + { + clip.Apply(m_target.transform, m_editorValue.Value); + } + } + } + } +} diff --git a/Scripts/BlendShape/Editor/BlendShapeSlider.cs.meta b/Scripts/BlendShape/Editor/BlendShapeSlider.cs.meta new file mode 100644 index 000000000..ef59fb868 --- /dev/null +++ b/Scripts/BlendShape/Editor/BlendShapeSlider.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 84dd38a83c8fb594484159a563312a26 +timeCreated: 1520579905 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/Editor/VRMBlendShapeManipulatorEditor.cs b/Scripts/BlendShape/Editor/VRMBlendShapeManipulatorEditor.cs new file mode 100644 index 000000000..ae5e41aaa --- /dev/null +++ b/Scripts/BlendShape/Editor/VRMBlendShapeManipulatorEditor.cs @@ -0,0 +1,157 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UniGLTF; +using System.IO; + +namespace VRM +{ + [CustomEditor(typeof(VRMBlendShapeManipulator))] + public class VRMBlendShapeManipulatorEditor : Editor + { + VRMBlendShapeManipulator m_target = null; + SkinnedMeshRenderer[] m_renderers; + + void OnEnable() + { + m_target = (VRMBlendShapeManipulator)target; + + m_renderers = m_target.transform + .Traverse() + .Select(x => x.GetComponent()) + .Where(x => x != null) + .ToArray() + ; + } + + static string EscapeFilePath(string src) + { + return src + .Replace(">", ">") + .Replace("<", "<") + ; + } + + public override void OnInspectorGUI() + { + if (GUILayout.Button("Clear")) + { + ClearBlendShape(); + } + + if (GUILayout.Button("Create BlendShapeClip")) + { + CreateBlendShapeClip(); + } + + var clip = (BlendShapeClip)EditorGUILayout.ObjectField("Load clip", null, typeof(BlendShapeClip), false); + if (clip != null) + { + ClearBlendShape(); + clip.Apply(m_target.transform, 1.0f); + } + + EditorGUILayout.Space(); + + // sliders + foreach (var renderer in m_renderers) + { + var mesh = renderer.sharedMesh; + if (mesh != null) + { + var relativePath = UniGLTF.UnityExtensions.RelativePathFrom(renderer.transform, m_target.transform); + EditorGUILayout.LabelField(m_target.name+"/"+relativePath); + + for (int i = 0; i < mesh.blendShapeCount; ++i) + { + var src = renderer.GetBlendShapeWeight(i); + var dst = EditorGUILayout.Slider(mesh.GetBlendShapeName(i), src, 0, 100.0f); + if (dst != src) + { + renderer.SetBlendShapeWeight(i, dst); + } + } + } + } + } + + private void CreateBlendShapeClip() + { + var maxWeight = 0.0f; + var maxWeightName = ""; + + // weightのついたblendShapeを集める + var blendShapes = m_renderers.SelectMany(x => + { + var mesh = x.sharedMesh; + + var relativePath = UniGLTF.UnityExtensions.RelativePathFrom(x.transform, m_target.transform); + + var list = new List(); + if (mesh != null) + { + for (int i = 0; i < mesh.blendShapeCount; ++i) + { + var weight = x.GetBlendShapeWeight(i); + if (weight == 0) + { + continue; + } + var name = mesh.GetBlendShapeName(i); + if (weight > maxWeight) + { + maxWeightName = name; + maxWeight = weight; + } + list.Add(new BlendShapeBinding + { + Index = i, + RelativePath = relativePath, + Weight = weight + }); + } + } + return list; + }) + .ToArray() + ; + + var assetPath = string.Format("Assets/{0}.{1}.asset", + m_target.name, + maxWeightName); + var prefab = PrefabUtility.GetPrefabParent(m_target.gameObject); + if (prefab != null) + { + var prefabPath = AssetDatabase.GetAssetPath(prefab); + assetPath = string.Format("{0}/{1}.{2}.asset", + Path.GetDirectoryName(prefabPath), + Path.GetFileNameWithoutExtension(prefabPath), + maxWeightName); + } + assetPath = EscapeFilePath(assetPath); + + var asset = ScriptableObject.CreateInstance(); + asset.Values = blendShapes.ToArray(); + Debug.LogFormat("create asset: {0}", assetPath); + AssetDatabase.CreateAsset(asset, assetPath); + + Selection.objects = new UnityEngine.Object[] { AssetDatabase.LoadAssetAtPath(assetPath, typeof(BlendShapeClip)) }; + } + + private void ClearBlendShape() + { + foreach (var renderer in m_renderers) + { + var mesh = renderer.sharedMesh; + if (mesh != null) + { + for (int i = 0; i < mesh.blendShapeCount; ++i) + { + renderer.SetBlendShapeWeight(i, 0); + } + } + } + } + } +} diff --git a/Scripts/BlendShape/Editor/VRMBlendShapeManipulatorEditor.cs.meta b/Scripts/BlendShape/Editor/VRMBlendShapeManipulatorEditor.cs.meta new file mode 100644 index 000000000..11288de69 --- /dev/null +++ b/Scripts/BlendShape/Editor/VRMBlendShapeManipulatorEditor.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: e213c696e46ae2642b99797f2124a682 +timeCreated: 1517404644 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/Editor/VRMBlnedShapeProxyEditor.cs b/Scripts/BlendShape/Editor/VRMBlnedShapeProxyEditor.cs new file mode 100644 index 000000000..4f347dd37 --- /dev/null +++ b/Scripts/BlendShape/Editor/VRMBlnedShapeProxyEditor.cs @@ -0,0 +1,360 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UniGLTF; +using UnityEditor; +using UnityEngine; + + +namespace VRM +{ + [CustomEditor(typeof(VRMBlendShapeProxy))] + public class VRMBlnedShapeProxyEditor : Editor + { + VRMBlendShapeProxy m_target; + SkinnedMeshRenderer[] m_renderers; + VRMLookAt m_lookAt; + + #region Preview + class PreviewRenderer + { + PreviewRenderUtility m_previewRenderUtility; + + public PreviewRenderer() + { + //true にすることでシーン内のゲームオブジェクトを描画できるようになる + m_previewRenderUtility = new PreviewRenderUtility(true); + +#if UNITY_2017_3_OR_NEWER + //FieldOfView を 30 にするとちょうどいい見た目になる + m_previewRenderUtility.cameraFieldOfView = 30f; + + //必要に応じて nearClipPlane と farClipPlane を設定 + m_previewRenderUtility.camera.nearClipPlane = 0.3f; + m_previewRenderUtility.camera.farClipPlane = 1000; +#else + //FieldOfView を 30 にするとちょうどいい見た目になる + m_previewRenderUtility.m_CameraFieldOfView = 30f; + + //必要に応じて nearClipPlane と farClipPlane を設定 + m_previewRenderUtility.m_Camera.nearClipPlane = 0.3f; + m_previewRenderUtility.m_Camera.farClipPlane = 1000; +#endif + } + + public Camera Camera + { + get + { +#if UNITY_2017_3_OR_NEWER + var previewCamera = m_previewRenderUtility.camera; +#else + var previewCamera = m_previewRenderUtility.m_Camera; +#endif + return previewCamera; + } + } + + public void Render(Rect r, GUIStyle background) + { + var previewCamera = Camera; + if (previewCamera == null) + { + // 無い時がある + return; + } + m_previewRenderUtility.BeginPreview(r, background); + previewCamera.Render(); + m_previewRenderUtility.EndAndDrawPreview(r); + } + } + PreviewRenderer m_preview; + public override bool HasPreviewGUI() + { + return true; + } + + public override GUIContent GetPreviewTitle() + { + return new GUIContent("BlendShapeProxy"); + } + + public override void OnPreviewSettings() + { + /* + GUIStyle preLabel = new GUIStyle("preLabel"); + GUIStyle preButton = new GUIStyle("preButton"); + GUILayout.Label("ラベル", preLabel); + GUILayout.Button("ボタン", preButton); + */ + } + + public override void OnPreviewGUI(Rect r, GUIStyle background) + { + if (m_lookAt == null) return; + if (m_lookAt.Head.Transform == null) return; + m_lookAt.LookFace(m_preview.Camera.transform); + m_preview.Render(r, background); + //描画タイミングが少ないことによって + //カクつきがきになる時は Repaint を呼び出す(高負荷) + //Repaint (); + } + #endregion + + void OnEnable() + { + m_target = (VRMBlendShapeProxy)target; + + if (m_target.BlendShapeAvatar == null) return; + m_loadClip = m_target.BlendShapeAvatar.GetClip(BlendShapePreset.Neutral.ToString()); + + m_renderers = m_target.transform + .Traverse() + .Select(x => x.GetComponent()) + .Where(x => x != null) + .ToArray() + ; + + m_sliders = m_target.BlendShapeAvatar.Clips + .Where(x => x!=null) + .Select(x => new BlendShapeSlider(m_target, BlendShapeKey.CreateFrom(x))) + .ToList() + ; + + m_lookAt = m_target.GetComponent(); + m_preview = new PreviewRenderer(); + } + + private void OnDisable() + { + if(m_mode==EditorMode.Editor) + { + ClearBlendShape(); + } + } + + enum EditorMode + { + Runtime, + Editor, + } + EditorMode m_mode; + static string[] MODES = ((EditorMode[])Enum.GetValues(typeof(EditorMode))) + .Select(x => x.ToString()) + .ToArray(); + + public override void OnInspectorGUI() + { + /// xxxx + var mode = + (EditorMode)GUILayout.Toolbar((int)m_mode, MODES); + if (mode != m_mode) + { + m_mode = mode; + ClearBlendShape(); + switch ((EditorMode)m_mode) + { + case EditorMode.Runtime: + if (Application.isPlaying) + { + m_target.Reload(); + } + else + { + if (m_sliders != null) + { + foreach (var x in m_sliders) + { + x.RestoreEditorValue(); + } + } + } + RuntimeInspector(); + break; + + case EditorMode.Editor: + Apply(); + EditorInspector(); + break; + } + } + else + { + switch ((EditorMode)m_mode) + { + case EditorMode.Runtime: + RuntimeInspector(); + break; + + case EditorMode.Editor: + EditorInspector(); + break; + } + } + } + + #region RuntimeInspector + List m_sliders; + + void RuntimeInspector() + { + base.OnInspectorGUI(); + + if (m_sliders != null) + { + foreach (var slider in m_sliders) + { + slider.Slider(); + } + } + } + #endregion + + #region EditorInspector + BlendShapeClip m_loadClip; + BlendShapeClip LoadClip + { + get { return m_loadClip; } + set + { + if (m_loadClip == value) return; + + m_loadClip = value; + ClearBlendShape(); + Apply(); + } + } + void Apply() + { + if (m_loadClip != null) + { + m_loadClip.Apply(m_target.transform, 1.0f); + } + } + + int m_preset; + void EditorInspector() + { + if (m_target.BlendShapeAvatar == null) return; + + if (GUILayout.Button("Clear")) + { + ClearBlendShape(); + } + + /* + if (GUILayout.Button("Create BlendShapeClip")) + { + CreateBlendShapeClip(); + } + */ + + GUILayout.BeginHorizontal(); + if (m_loadClip != null && GUILayout.Button("Apply")) + { + /*var loadClip = (BlendShapeClip)*/ + EditorGUILayout.ObjectField("Load clip", + LoadClip, typeof(BlendShapeClip), false); + string maxWeightString; + m_loadClip.Values = GetBindings(out maxWeightString); + } + GUILayout.EndHorizontal(); + + // buttons + var preset = GUILayout.SelectionGrid(m_preset, m_target.BlendShapeAvatar.Clips + .Where(x => x!=null) + .Select(x => BlendShapeKey.CreateFrom(x).ToString()).ToArray(), 4); + if (preset != m_preset) + { + LoadClip = m_target.BlendShapeAvatar.Clips[preset]; + m_preset = preset; + } + + EditorGUILayout.Space(); + + // sliders + if (m_loadClip != null) + { + foreach (var renderer in m_renderers) + { + var mesh = renderer.sharedMesh; + if (mesh != null) + { + var relativePath = UniGLTF.UnityExtensions.RelativePathFrom(renderer.transform, m_target.transform); + EditorGUILayout.LabelField(m_target.name + "/" + relativePath); + + for (int i = 0; i < mesh.blendShapeCount; ++i) + { + var src = renderer.GetBlendShapeWeight(i); + var dst = EditorGUILayout.Slider(mesh.GetBlendShapeName(i), src, 0, 100.0f); + if (dst != src) + { + renderer.SetBlendShapeWeight(i, dst); + + } + } + } + } + } + } + + BlendShapeBinding[] GetBindings(out string _maxWeightName) + { + var maxWeight = 0.0f; + var maxWeightName = ""; + // weightのついたblendShapeを集める + var values= m_renderers.SelectMany(x => + { + var mesh = x.sharedMesh; + + var relativePath = UniGLTF.UnityExtensions.RelativePathFrom(x.transform, m_target.transform); + + var list = new List(); + if (mesh != null) + { + for (int i = 0; i < mesh.blendShapeCount; ++i) + { + var weight = x.GetBlendShapeWeight(i); + if (weight == 0) + { + continue; + } + var name = mesh.GetBlendShapeName(i); + if (weight > maxWeight) + { + maxWeightName = name; + maxWeight = weight; + } + list.Add(new BlendShapeBinding + { + Index = i, + RelativePath = relativePath, + Weight = weight + }); + } + } + return list; + }).ToArray() + ; + _maxWeightName = maxWeightName; + return values; + } + + private void ClearBlendShape() + { + if (m_renderers == null) return; + foreach (var renderer in m_renderers) + { + var mesh = renderer.sharedMesh; + if (mesh != null) + { + for (int i = 0; i < mesh.blendShapeCount; ++i) + { + renderer.SetBlendShapeWeight(i, 0); + } + } + } + } + #endregion + } +} diff --git a/Scripts/BlendShape/Editor/VRMBlnedShapeProxyEditor.cs.meta b/Scripts/BlendShape/Editor/VRMBlnedShapeProxyEditor.cs.meta new file mode 100644 index 000000000..7d4c20959 --- /dev/null +++ b/Scripts/BlendShape/Editor/VRMBlnedShapeProxyEditor.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 0f9ca53e9d292ce48a7e6449a03734a9 +timeCreated: 1517819499 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/VRMBlendShapeManipulator.cs b/Scripts/BlendShape/VRMBlendShapeManipulator.cs new file mode 100644 index 000000000..56a8cbe0d --- /dev/null +++ b/Scripts/BlendShape/VRMBlendShapeManipulator.cs @@ -0,0 +1,9 @@ +using UnityEngine; + + +namespace VRM +{ + public class VRMBlendShapeManipulator : MonoBehaviour + { + } +} diff --git a/Scripts/BlendShape/VRMBlendShapeManipulator.cs.meta b/Scripts/BlendShape/VRMBlendShapeManipulator.cs.meta new file mode 100644 index 000000000..e3fafa4cc --- /dev/null +++ b/Scripts/BlendShape/VRMBlendShapeManipulator.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 4829a7f37bfef244289c32551215632d +timeCreated: 1517403264 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/VRMBlendShapeProxy.cs b/Scripts/BlendShape/VRMBlendShapeProxy.cs new file mode 100644 index 000000000..8e597826d --- /dev/null +++ b/Scripts/BlendShape/VRMBlendShapeProxy.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + + +namespace VRM +{ + public class VRMBlendShapeProxy : MonoBehaviour + { + [SerializeField] + public BlendShapeAvatar BlendShapeAvatar; + + Dictionary m_handlerMap; + public Dictionary CreateHandlerMap() + { + var handlerMap = new Dictionary( + new BlendShapeKey.CustomerEqualityComparer()); + foreach (var x in BlendShapeAvatar.Clips) + { + handlerMap.Add(BlendShapeKey.CreateFrom(x), new BlendShapeClipHandler(x, transform)); + ; + } + return handlerMap; + } + + private void Update() + { + if (BlendShapeAvatar != null) + { + if (m_handlerMap == null) + { + m_handlerMap = CreateHandlerMap(); + } + } + } + + public void Reload() + { + if (BlendShapeAvatar == null) return; + + foreach (var kv in m_handlerMap) + { + SetValue(kv.Key, GetValue(kv.Key)); + } + } + + public void SetValue(BlendShapePreset key, float value) + { + SetValue(new BlendShapeKey(key), value); + } + public float GetValue(BlendShapePreset key) + { + return GetValue(new BlendShapeKey(key)); + } + public void SetValue(String key, float value) + { + SetValue(new BlendShapeKey(key), value); + } + public float GetValue(String key) + { + return GetValue(new BlendShapeKey(key)); + } + public void SetValue(BlendShapeKey key, float value) + { + if (m_handlerMap == null) return; + BlendShapeClipHandler handler; + if (m_handlerMap.TryGetValue(key, out handler)) + { + handler.Apply(value); + } + } + public float GetValue(BlendShapeKey key) + { + if (m_handlerMap == null) return 0; + BlendShapeClipHandler handler; + if (!m_handlerMap.TryGetValue(key, out handler)) + { + return 0; + } + return handler.LastValue; + } + + public void ClearKeys() + { + if (m_handlerMap == null) return; + foreach(var kv in m_handlerMap) + { + kv.Value.Apply(0); + } + } + } +} diff --git a/Scripts/BlendShape/VRMBlendShapeProxy.cs.meta b/Scripts/BlendShape/VRMBlendShapeProxy.cs.meta new file mode 100644 index 000000000..9eaaa544e --- /dev/null +++ b/Scripts/BlendShape/VRMBlendShapeProxy.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 5b678c1df50cfb547990db24a32856da +timeCreated: 1517467747 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Editor.meta b/Scripts/Editor.meta new file mode 100644 index 000000000..3b4c9994b --- /dev/null +++ b/Scripts/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 41cb69128d62a4e4a9ffde396b606553 +folderAsset: yes +timeCreated: 1521102890 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Editor/Tests.meta b/Scripts/Editor/Tests.meta new file mode 100644 index 000000000..9acbf73c3 --- /dev/null +++ b/Scripts/Editor/Tests.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0903c33afe5ef6346ad9526e78055293 +folderAsset: yes +timeCreated: 1521799604 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Editor/Tests/VRMBlendShapeKeyTest.cs b/Scripts/Editor/Tests/VRMBlendShapeKeyTest.cs new file mode 100644 index 000000000..807ee7634 --- /dev/null +++ b/Scripts/Editor/Tests/VRMBlendShapeKeyTest.cs @@ -0,0 +1,24 @@ +using NUnit.Framework; +using System.Collections.Generic; +using VRM; + + +public class VRMBlendShapeKeyTest +{ + [Test] + public void KeyTest() + { + var key = new BlendShapeKey("Blink", BlendShapePreset.Blink); + + Assert.AreEqual(key, new BlendShapeKey("blink")); + Assert.AreEqual(key, new BlendShapeKey(BlendShapePreset.Blink)); + Assert.AreEqual(key, new BlendShapeKey("xxx", BlendShapePreset.Blink)); + + var dict = new Dictionary(new BlendShapeKey.CustomerEqualityComparer()); + dict[new BlendShapeKey("xxx", BlendShapePreset.Blink)] = 1.0f; + + Assert.IsTrue(dict.ContainsKey(new BlendShapeKey("blink"))); + Assert.IsTrue(dict.ContainsKey(new BlendShapeKey(BlendShapePreset.Blink))); + Assert.IsTrue(dict.ContainsKey(new BlendShapeKey("xxx", BlendShapePreset.Blink))); + } +} diff --git a/Scripts/Editor/Tests/VRMBlendShapeKeyTest.cs.meta b/Scripts/Editor/Tests/VRMBlendShapeKeyTest.cs.meta new file mode 100644 index 000000000..cb7c673a2 --- /dev/null +++ b/Scripts/Editor/Tests/VRMBlendShapeKeyTest.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ca2bf37b88b7c3a45adbeebb8a17559d +timeCreated: 1521799592 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Editor/VRMExportUnityPackage.cs b/Scripts/Editor/VRMExportUnityPackage.cs new file mode 100644 index 000000000..576a81be0 --- /dev/null +++ b/Scripts/Editor/VRMExportUnityPackage.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using UnityEditor; +using UnityEngine; + + +namespace VRM +{ + public static class VRMExportUnityPackage + { + static string GetDesktop() + { + return Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/VRM"; + } + + const string DATE_FORMAT = "yyyyMMdd"; + const string PREFIX = "UniVRM"; + + static string GetPath() + { + var folder = GetDesktop(); + if (!Directory.Exists(folder)) + { + Directory.CreateDirectory(folder); + } + + //var date = DateTime.Today.ToString(DATE_FORMAT); + + var path = string.Format("{0}/{1}-{2}.unitypackage", + folder, + PREFIX, + VRMVersion.VERSION + ).Replace("\\", "/"); + + return path; + } + +#if VRM_DEVELOP + [MenuItem("VRM/Export unitypackage")] +#endif + public static void CreateUnityPackage() + { + var path = GetPath(); + + if (File.Exists(path)) + { + Debug.LogErrorFormat("{0} is already exists", path); + return; + } + + AssetDatabase.ExportPackage("Assets/VRM", path, ExportPackageOptions.Recurse); + Debug.LogFormat("exported: {0}", path); + } + } +} diff --git a/Scripts/Editor/VRMExportUnityPackage.cs.meta b/Scripts/Editor/VRMExportUnityPackage.cs.meta new file mode 100644 index 000000000..ab6531f74 --- /dev/null +++ b/Scripts/Editor/VRMExportUnityPackage.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6895a43269f0daf4eab06931c9a7724c +timeCreated: 1521714822 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Editor/VRMMonoBehaviourComparator.cs b/Scripts/Editor/VRMMonoBehaviourComparator.cs new file mode 100644 index 000000000..931b1deb7 --- /dev/null +++ b/Scripts/Editor/VRMMonoBehaviourComparator.cs @@ -0,0 +1,30 @@ +using System; +using UnityEngine; +using VRM; + + +public static class VRMMonoBehaviourComparator +{ + public static bool AssertAreEquals(GameObject l, GameObject r) + { + return + AssertAreEquals(l, r, + (x, y) => x[0].Equals(y[0])) + ; + } + + public static bool AssertAreEquals(GameObject l, GameObject r, Func pred) where T : Component + { + var ll = l.GetComponents(); + var rr = r.GetComponents(); + if (ll.Length != rr.Length) + { + return false; + } + if (ll.Length == 0) + { + return true; + } + return pred(ll, rr); + } +} diff --git a/Scripts/Editor/VRMMonoBehaviourComparator.cs.meta b/Scripts/Editor/VRMMonoBehaviourComparator.cs.meta new file mode 100644 index 000000000..c0a76a6dc --- /dev/null +++ b/Scripts/Editor/VRMMonoBehaviourComparator.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 557330772b8af474c9342f543cd61550 +timeCreated: 1521106869 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Editor/VRMTest.cs b/Scripts/Editor/VRMTest.cs new file mode 100644 index 000000000..fe607c0b8 --- /dev/null +++ b/Scripts/Editor/VRMTest.cs @@ -0,0 +1,76 @@ +using NUnit.Framework; +using System; +using UniGLTF; +using UnityEngine; +using VRM; + + +public class VRMTest +{ + static GameObject CreateSimpelScene() + { + var root = new GameObject("gltfRoot").transform; + + var scene = new GameObject("scene0").transform; + scene.SetParent(root, false); + scene.localPosition = new Vector3(1, 2, 3); + + return root.gameObject; + } + + void AssertAreEqual(Transform go, Transform other) + { + var lt = go.Traverse().GetEnumerator(); + var rt = go.Traverse().GetEnumerator(); + + while (lt.MoveNext()) + { + if (!rt.MoveNext()) + { + throw new Exception("rt shorter"); + } + + MonoBehaviourComparator. + AssertAreEquals(lt.Current.gameObject, rt.Current.gameObject); + VRMMonoBehaviourComparator. + AssertAreEquals(lt.Current.gameObject, rt.Current.gameObject); + } + + if (rt.MoveNext()) + { + throw new Exception("rt longer"); + } + } + + [Test] + public void VRMSimpleSceneTest() + { + var go = CreateSimpelScene(); + var context = new VRMImporterContext(); + + try + { + // export + var gltf = VRMExporter.Export(go); + + using (var exporter = new gltfExporter(gltf)) + { + exporter.Prepare(go); + exporter.Export(); + + // import + context.Json = gltf.ToJson(); + Debug.LogFormat("{0}", context.Json); + gltfImporter.Import(context, new ArraySegment()); + + AssertAreEqual(go.transform, context.Root.transform); + } + } + finally + { + //Debug.LogFormat("Destory, {0}", go.name); + GameObject.DestroyImmediate(go); + context.Destroy(true); + } + } +} diff --git a/Scripts/Editor/VRMTest.cs.meta b/Scripts/Editor/VRMTest.cs.meta new file mode 100644 index 000000000..bb2f84446 --- /dev/null +++ b/Scripts/Editor/VRMTest.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2b3bb055ba3c9384ca27fbeb2c696604 +timeCreated: 1521102909 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/FirstPerson.meta b/Scripts/FirstPerson.meta new file mode 100644 index 000000000..28a1a0131 --- /dev/null +++ b/Scripts/FirstPerson.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 5a5c5355606c9da4cb354f3ae2ae4bae +folderAsset: yes +timeCreated: 1519278754 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/FirstPerson/Editor.meta b/Scripts/FirstPerson/Editor.meta new file mode 100644 index 000000000..a4ff4e17f --- /dev/null +++ b/Scripts/FirstPerson/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0ee18512b5f8dd94a923348721614318 +folderAsset: yes +timeCreated: 1520848598 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/FirstPerson/Editor/RendererFirstPersonFlagsDrawer.cs b/Scripts/FirstPerson/Editor/RendererFirstPersonFlagsDrawer.cs new file mode 100644 index 000000000..148b5bfe3 --- /dev/null +++ b/Scripts/FirstPerson/Editor/RendererFirstPersonFlagsDrawer.cs @@ -0,0 +1,40 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + + +namespace VRM +{ + [CustomPropertyDrawer(typeof(VRMFirstPerson.RendererFirstPersonFlags))] + public class RendererFirstPersonFlagsDrawer : PropertyDrawer + { + static Rect LeftSide(Rect position, float width) + { + return new Rect(position.x, position.y, position.width-width, position.height); + } + static Rect RightSide(Rect position, float width) + { + return new Rect(position.x + (position.width-width), position.y, width, position.height); + } + + public override void OnGUI(Rect position, + SerializedProperty property, GUIContent label) + { + var rendererProp = property.FindPropertyRelative("Renderer"); + var flagProp = property.FindPropertyRelative("FirstPersonFlag"); + + const float WIDTH = 140.0f; + EditorGUI.PropertyField(LeftSide(position, WIDTH), rendererProp, new GUIContent(""), true); + EditorGUI.PropertyField(RightSide(position, WIDTH), flagProp, new GUIContent(""), true); + } + + /* + public override float GetPropertyHeight(SerializedProperty property, + GUIContent label) + { + return 60.0f; + } + */ + } +} diff --git a/Scripts/FirstPerson/Editor/RendererFirstPersonFlagsDrawer.cs.meta b/Scripts/FirstPerson/Editor/RendererFirstPersonFlagsDrawer.cs.meta new file mode 100644 index 000000000..b75e211c6 --- /dev/null +++ b/Scripts/FirstPerson/Editor/RendererFirstPersonFlagsDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ddbc54a3a83438841a744bf50b34ebb9 +timeCreated: 1520848617 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/FirstPerson/VRMFirstPerson.cs b/Scripts/FirstPerson/VRMFirstPerson.cs new file mode 100644 index 000000000..ff39dadb4 --- /dev/null +++ b/Scripts/FirstPerson/VRMFirstPerson.cs @@ -0,0 +1,210 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UniGLTF; +using UnityEngine; + + +namespace VRM +{ + public class VRMFirstPerson : MonoBehaviour + { + public const int FIRSTPERSON_ONLY_LAYER = 9; + public const int THIRDPERSON_ONLY_LAYER = 10; + + [SerializeField] + public Transform FirstPersonBone; + + [SerializeField] + public Vector3 FirstPersonOffset; + + [Serializable] + public struct RendererFirstPersonFlags + { + public Renderer Renderer; + public FirstPersonFlag FirstPersonFlag; + public Mesh SharedMesh + { + get + { + var renderer = Renderer as SkinnedMeshRenderer; + if (renderer != null) + { + return renderer.sharedMesh; + } + + var filter = Renderer.GetComponent(); + if (filter != null) + { + return filter.sharedMesh; + } + + return null; + } + } + } + + [SerializeField] + public List Renderers = new List(); + + static IEnumerable Traverse(Transform parent) + { + yield return parent; + + foreach (Transform child in parent) + { + foreach (var x in Traverse(child)) + { + yield return x; + } + } + } + + public void CopyTo(GameObject _dst, Dictionary map) + { + var dst = _dst.AddComponent(); + dst.FirstPersonBone = FirstPersonBone; + dst.FirstPersonOffset = FirstPersonOffset; + dst.Renderers = Renderers.Select(x => + { + var renderer = map[x.Renderer.transform].GetComponent(); + return new VRMFirstPerson.RendererFirstPersonFlags + { + Renderer = renderer, + FirstPersonFlag = x.FirstPersonFlag, + }; + }).ToList(); + } + + public void SetDefault() + { + FirstPersonOffset = new Vector3(0, 0.06f, 0); + var animator = GetComponent(); + if (animator != null) + { + FirstPersonBone = animator.GetBoneTransform(HumanBodyBones.Head); + } + } + + private void Reset() + { + TraverseRenderers(); + } + + public void TraverseRenderers(VRMImporterContext context = null) + { + Renderers = Traverse(transform) + .Select(x => x.GetComponent()) + .Where(x => x != null) + .Select(x => new RendererFirstPersonFlags + { + Renderer = x, + FirstPersonFlag = context == null + ? FirstPersonFlag.Auto + : GetFirstPersonFlag(context, x) + }) + .ToList() + ; + } + + static FirstPersonFlag GetFirstPersonFlag(VRMImporterContext context, Renderer r) + { + var mesh = r.transform.GetSharedMesh(); + if (mesh == null) + { + return FirstPersonFlag.Auto; + } + + var index = context.Meshes.FindIndex(x => x.Mesh == mesh); + if (index == -1) + { + return FirstPersonFlag.Auto; + } + + foreach(var x in context.VRM.extensions.VRM.firstPerson.meshAnnotations) + { + if (x.mesh == index) + { + return (FirstPersonFlag)Enum.Parse(typeof(FirstPersonFlag), x.firstPersonFlag, true); + } + } + + return FirstPersonFlag.Auto; + } + + void CreateHeadlessModel(Renderer _renderer, Transform EraseRoot) + { + var renderer = _renderer as SkinnedMeshRenderer; + if (renderer != null) + { + var go = new GameObject("_headless_" + renderer.name); + go.layer = FIRSTPERSON_ONLY_LAYER; + go.transform.SetParent(transform, false); + + var m_eraseBones = renderer.bones.Select(x => + { + var eb = new BoneMeshEraser.EraseBone + { + Bone = x, + }; + + if (EraseRoot != null) + { + // 首の子孫を消去 + if (eb.Bone.Ancestor().Any(y => y == EraseRoot)) + { + //Debug.LogFormat("erase {0}", x); + eb.Erase = true; + } + } + + return eb; + }) + .ToArray(); + + var bones = renderer.bones; + var eraseBones = m_eraseBones + .Where(x => x.Erase) + .Select(x => bones.IndexOf(x.Bone)) + .ToArray(); + + var mesh = BoneMeshEraser.CreateErasedMesh(renderer.sharedMesh, eraseBones); + + var erased = go.AddComponent(); + erased.sharedMesh = mesh; + erased.sharedMaterials = renderer.sharedMaterials; + erased.bones = renderer.bones; + erased.rootBone = renderer.rootBone; + } + } + + /// + /// 配下のモデルのレイヤー設定など + /// + public void Setup() + { + foreach (var x in Renderers) + { + switch (x.FirstPersonFlag) + { + case FirstPersonFlag.Auto: + x.Renderer.gameObject.layer = THIRDPERSON_ONLY_LAYER; + CreateHeadlessModel(x.Renderer, FirstPersonBone); + break; + + case FirstPersonFlag.FirstPersonOnly: + x.Renderer.gameObject.layer = FIRSTPERSON_ONLY_LAYER; + break; + + case FirstPersonFlag.ThirdPersonOnly: + x.Renderer.gameObject.layer = THIRDPERSON_ONLY_LAYER; + break; + + case FirstPersonFlag.Both: + //x.Renderer.gameObject.layer = 0; + break; + } + } + } + } +} diff --git a/Scripts/FirstPerson/VRMFirstPerson.cs.meta b/Scripts/FirstPerson/VRMFirstPerson.cs.meta new file mode 100644 index 000000000..0711249b2 --- /dev/null +++ b/Scripts/FirstPerson/VRMFirstPerson.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: dedba1309bdf12b42af2362f52eea134 +timeCreated: 1519218333 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/FirstPerson/VRMFirstPersonCameraManager.cs b/Scripts/FirstPerson/VRMFirstPersonCameraManager.cs new file mode 100644 index 000000000..b29714743 --- /dev/null +++ b/Scripts/FirstPerson/VRMFirstPersonCameraManager.cs @@ -0,0 +1,91 @@ +#pragma warning disable 0414, 0649 +using UnityEngine; +using System.Linq; +using UnityEngine.UI; +using System; + +namespace VRM +{ + /// + /// ファーストパーソン向けLayer検討 + /// + /// * Deault LayerをFirstPersonレイヤーとして使う + /// * 9番にThirdPerson Layerを追加する + /// + /// * FirstPersonCameraはCullingMaskでThirdPerson Layerを除外 + /// * ThirdPersonCameraはCullingMaskでDefault Layerを除外 + /// + /// * それ以外のシーンオブジェクトはDefaultLayerとThirdPersonレイヤーの両方に所属するべし + /// * 首無しモデルはDefault Layerのみに所属するべし + /// * 首有りモデルはThirdPerson Layerのみに所属するべし + /// * コントローラーはDefault Layerがいいかも + /// * 鏡もDefault Layerがいいかも(カメラごとにRenderTargetを用意するのは煩雑) + /// + public class VRMFirstPersonCameraManager : MonoBehaviour + { + [Serializable] + class CameraWithRawImage + { + public Camera Camera; + public RenderTexture Texture; + public RawImage Image; + } + + /// + /// FirstPerson + /// + [SerializeField] + CameraWithRawImage m_topLeft; + + /// + /// ThirdPerson body + /// + [SerializeField] + CameraWithRawImage m_topRight; + + /// + /// ThirdPerson head + /// + [SerializeField] + CameraWithRawImage m_bottomRight; + + [SerializeField, Header("Cameras")] + Camera m_firstPersonCamera; + + [SerializeField] + Camera[] m_thirdPersonCameras; + + void Reset() + { + var cameras = GameObject.FindObjectsOfType(); + m_firstPersonCamera = Camera.main; + m_thirdPersonCameras = cameras.Where(x => x != m_firstPersonCamera).ToArray(); + } + + private void Update() + { + var halfWidth = Screen.width / 2; + var halfHeight = Screen.height / 2; + SetupRenderTarget(m_topLeft, halfWidth, halfHeight); + SetupRenderTarget(m_topRight, halfWidth, halfHeight); + SetupRenderTarget(m_bottomRight, halfWidth, halfHeight); + } + + void SetupRenderTarget(CameraWithRawImage cameraWithImage, int w, int h) + { + if (cameraWithImage.Camera == null) return; + if (cameraWithImage.Image == null) return; + + if (cameraWithImage.Texture == null + || cameraWithImage.Texture.width != w + || cameraWithImage.Texture.height != h + ) + { + var texture = new RenderTexture(w, h, 16); + cameraWithImage.Texture = texture; + cameraWithImage.Camera.targetTexture = texture; + cameraWithImage.Image.texture = texture; + } + } + } +} diff --git a/Scripts/FirstPerson/VRMFirstPersonCameraManager.cs.meta b/Scripts/FirstPerson/VRMFirstPersonCameraManager.cs.meta new file mode 100644 index 000000000..c781b7cf6 --- /dev/null +++ b/Scripts/FirstPerson/VRMFirstPersonCameraManager.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 6b34fb2c039c3ce4881f04e476a2128f +timeCreated: 1519220439 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format.meta b/Scripts/Format.meta new file mode 100644 index 000000000..9f69f16cb --- /dev/null +++ b/Scripts/Format.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 8dc6b68ffeda9f54494eee1cd17af615 +folderAsset: yes +timeCreated: 1517308531 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/Editor.meta b/Scripts/Format/Editor.meta new file mode 100644 index 000000000..86e7e9b5f --- /dev/null +++ b/Scripts/Format/Editor.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: f24b76911d4f68844b9d12721ba1bb06 +folderAsset: yes +timeCreated: 1517308497 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/Editor/VRMAssetWriter.cs b/Scripts/Format/Editor/VRMAssetWriter.cs new file mode 100644 index 000000000..9b609004a --- /dev/null +++ b/Scripts/Format/Editor/VRMAssetWriter.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UniGLTF; +using UnityEditor; +using UnityEngine; + + +namespace VRM +{ + public static class VRMAssetWriter + { + interface ISubAssetWriter + { + void WriteIfHas(GameObject go); + } + + class SubAssetWriter: ISubAssetWriter where T : UnityEngine.Object + { + HashSet m_set = new HashSet(); + + String m_assetPath; + public delegate IEnumerable GetterFunc(GameObject go); + GetterFunc m_getter; + public SubAssetWriter(string assetPath, GetterFunc getter) + { + m_assetPath = assetPath; + m_getter = getter; + } + + public void WriteIfHas(GameObject go) + { + foreach(var o in m_getter(go)) + { + if (!m_set.Contains(o)) + { + AssetDatabase.AddObjectToAsset(o, m_assetPath); + m_set.Add(o); + } + } + } + } + + static IEnumerable GetMeshs(GameObject go) + { + var skinnedMesh = go.GetComponent(); + if (skinnedMesh != null) + { + yield return skinnedMesh.sharedMesh; + } + + var filter = go.GetComponent(); + if (filter != null) + { + yield return filter.sharedMesh; + } + } + + static IEnumerable GetMaterials(GameObject go) + { + var renderer = go.GetComponent(); + if (renderer != null) + { + return renderer.sharedMaterials; + } + else + { + return Enumerable.Empty(); + } + } + + static IEnumerable GetTextures(GameObject go) + { + foreach (var m in GetMaterials(go)) + { + foreach(Texture2D x in m.GetTextures()) + { + if (x != null) + { + yield return x; + } + } + } + } + + static IEnumerable GetAvatars(GameObject go) + { + var animator = go.GetComponent(); + if(animator!=null && animator.avatar != null) + { + yield return animator.avatar; + } + } + + static IEnumerable GetBlendShapeClips(GameObject go) + { + var proxy = go.GetComponent(); + if (proxy != null && proxy.BlendShapeAvatar != null) + { + return proxy.BlendShapeAvatar.Clips; + } + else + { + return Enumerable.Empty(); + } + } + + static IEnumerable GetBlendShapeAvatars(GameObject go) + { + var proxy = go.GetComponent(); + if (proxy != null && proxy.BlendShapeAvatar != null) + { + yield return proxy.BlendShapeAvatar; + } + } + + static IEnumerable GetAvatarDecriptions(GameObject go) + { + var humanoid = go.GetComponent(); + if (humanoid!=null && humanoid.Description != null) + { + yield return humanoid.Description; + } + else + { + var animator = go.GetComponent(); + if(animator!=null && animator.avatar) + { + var description= UniHumanoid.AvatarDescription.CreateFrom(animator.avatar); + if (description != null) + { + description.name = "AvatarDescription"; + yield return description; + } + } + } + } + + static IEnumerable GetThumbnails(GameObject go) + { + var meta = go.GetComponent(); + if (meta != null && meta.Thumbnail != null) + { + yield return meta.Thumbnail; + } + } + + static IEnumerable GetSubAssets(String prefabPath) + { + return AssetDatabase.LoadAllAssetsAtPath(prefabPath); + } + + public static void SaveAsPrefab(GameObject root, String path) + { + var prefabPath = path.ToUnityRelativePath(); + Debug.LogFormat("SaveAsPrefab: {0}", prefabPath); + + // clear subassets + if (File.Exists(prefabPath)) + { + //Debug.LogFormat("Exist: {0}", m_prefabPath); + + // clear subassets + foreach (var x in GetSubAssets(prefabPath)) + { + if (x is Transform + || x is GameObject) + { + continue; + } + GameObject.DestroyImmediate(x, true); + } + } + + // add subassets + var writers = new ISubAssetWriter[]{ + new SubAssetWriter(prefabPath, GetTextures), + new SubAssetWriter(prefabPath, GetMaterials), + new SubAssetWriter(prefabPath, GetMeshs), + new SubAssetWriter(prefabPath, GetAvatars), + // VRM Objects + new SubAssetWriter(prefabPath, GetBlendShapeClips), + new SubAssetWriter(prefabPath, GetBlendShapeAvatars), + new SubAssetWriter(prefabPath, GetAvatarDecriptions), + new SubAssetWriter(prefabPath, GetThumbnails), + }; + foreach (var x in root.transform.Traverse()) + { + foreach (var writer in writers) + { + writer.WriteIfHas(x.gameObject); + } + } + + /// + /// create prefab, after subasset AssetDatabase.AddObjectToAsset + /// + if (File.Exists(prefabPath)) + { + //Debug.LogFormat("ReplacePrefab: {0}", m_prefabPath); + var prefab = AssetDatabase.LoadAssetAtPath(prefabPath); + PrefabUtility.ReplacePrefab(root, prefab, ReplacePrefabOptions.ConnectToPrefab); + } + else + { + //Debug.LogFormat("CreatePrefab: {0}", m_prefabPath); + PrefabUtility.CreatePrefab(prefabPath, root, ReplacePrefabOptions.ConnectToPrefab); + } + } + } +} diff --git a/Scripts/Format/Editor/VRMAssetWriter.cs.meta b/Scripts/Format/Editor/VRMAssetWriter.cs.meta new file mode 100644 index 000000000..264ff80ec --- /dev/null +++ b/Scripts/Format/Editor/VRMAssetWriter.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8b409aa5d363b9948995cc00f7f1a0d0 +timeCreated: 1520241647 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/Editor/VRMExporter.cs b/Scripts/Format/Editor/VRMExporter.cs new file mode 100644 index 000000000..bae84eda5 --- /dev/null +++ b/Scripts/Format/Editor/VRMExporter.cs @@ -0,0 +1,219 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UniGLTF; +using UnityEngine; + + +namespace VRM +{ + public class VRMExporter : gltfExporter + { + public VRMExporter(glTF_VRM gltf) : base(gltf) + { } + + public static glTF Export(GameObject go, string path = null) + { + var gltf = new glTF_VRM(); + gltf.asset.generator = "Unity VRM Exporter"; + using (var exporter = new VRMExporter(gltf)) + { + _Export(gltf, exporter, go); + if (!string.IsNullOrEmpty(path)) + { + exporter.WriteTo(path); + } + } + return gltf; + } + + public static void _Export(glTF_VRM gltf, VRMExporter exporter, GameObject go) + { + exporter.Prepare(go); + exporter.Export(); + + // avatar + var animator = go.GetComponent(); + if (animator != null) + { + var humanoid = go.GetComponent(); + UniHumanoid.AvatarDescription description = null; + var nodes = go.transform.Traverse().Skip(1).ToList(); + { + var isCreated = false; + if (humanoid != null) + { + description = humanoid.GetDescription(out isCreated); + } + + if (description != null) + { + // use description + gltf.extensions.VRM.humanoid.Apply(description, nodes); + } + if (isCreated) + { + GameObject.DestroyImmediate(description); + } + } + + { + // set humanoid bone mapping + var avatar = animator.avatar; + foreach (HumanBodyBones key in Enum.GetValues(typeof(HumanBodyBones))) + { + if (key == HumanBodyBones.LastBone) + { + break; + } + + var transform = animator.GetBoneTransform(key); + if (transform != null) + { + gltf.extensions.VRM.humanoid.SetNodeIndex(key, nodes.IndexOf(transform)); + } + } + } + } + + // morph + var master = go.GetComponent(); + if (master != null) + { + var avatar = master.BlendShapeAvatar; + if (avatar != null) + { + var meshes = exporter.Meshes; + foreach (var x in avatar.Clips) + { + gltf.extensions.VRM.blendShapeMaster.Add(x, exporter.Copy.transform, meshes); + } + } + } + + // secondary + var secondary = exporter.Copy.transform.Find("secondary"); + if (secondary == null) + { + secondary = exporter.Copy.transform; + } + + var colliders = new List(); + foreach (var vrmColliderGroup in exporter.Copy.transform.Traverse().Select(x => x.GetComponent()).Where(x => x != null)) + { + colliders.Add(vrmColliderGroup); + + var colliderGroup = new glTF_VRM_SecondaryAnimationColliderGroup + { + node = exporter.Nodes.IndexOf(vrmColliderGroup.transform) + }; + + colliderGroup.colliders = vrmColliderGroup.Colliders.Select(x => + { + return new glTF_VRM_SecondaryAnimationCollider + { + offset = x.Offset, + radius = x.Radius, + }; + + }).ToList(); + + gltf.extensions.VRM.secondaryAnimation.colliderGroups.Add(colliderGroup); + } + + foreach (var spring in secondary.GetComponents()) + { + gltf.extensions.VRM.secondaryAnimation.boneGroups.Add(new glTF_VRM_SecondaryAnimationGroup + { + comment = spring.m_comment, + center = exporter.Nodes.IndexOf(spring.m_center), + dragForce = spring.m_dragForce, + gravityDir = spring.m_gravityDir, + gravityPower = spring.m_gravityPower, + stiffiness = spring.m_stiffnessForce, + hitRadius = spring.m_hitRadius, + colliderGroups = spring.ColliderGroups + .Select(x => + { + var index = colliders.IndexOf(x); + if (index == -1) + { + throw new IndexOutOfRangeException(); + } + return index; + }) + .ToArray(), + bones = spring.RootBones.Select(x => exporter.Nodes.IndexOf(x)).ToArray(), + }); + } + + // meta + var meta = exporter.Copy.GetComponent(); + if (meta != null) + { + gltf.extensions.VRM.meta.author = meta.Author; + gltf.extensions.VRM.meta.contactInformation = meta.ContactInformation; + gltf.extensions.VRM.meta.title = meta.Title; + if (meta.Thumbnail != null) + { + gltf.extensions.VRM.meta.texture = gltfExporter.ExportTexture(gltf, gltf.buffers.Count - 1, meta.Thumbnail); + } + gltf.extensions.VRM.meta.licenseType = meta.LicenseType; + gltf.extensions.VRM.meta.otherLicenseUrl = meta.OtherLicenseUrl; + gltf.extensions.VRM.meta.reference = meta.Reference; + } + + // firstPerson + var firstPerson = exporter.Copy.GetComponent(); + if (firstPerson != null) + { + if (firstPerson.FirstPersonBone != null) + { + gltf.extensions.VRM.firstPerson.firstPersonBone = exporter.Nodes.IndexOf(firstPerson.FirstPersonBone); + gltf.extensions.VRM.firstPerson.firstPersonBoneOffset = firstPerson.FirstPersonOffset; + gltf.extensions.VRM.firstPerson.meshAnnotations = firstPerson.Renderers.Select(x => new glTF_VRM_MeshAnnotation + { + mesh = exporter.Meshes.IndexOf(x.SharedMesh), + firstPersonFlag = x.FirstPersonFlag.ToString(), + }).ToList(); + } + + // lookAt + { + var lookAtHead = exporter.Copy.GetComponent(); + var lookAt = exporter.Copy.GetComponent(); + if (lookAtHead != null) + { + var boneApplyer = exporter.Copy.GetComponent(); + var blendShapeApplyer = exporter.Copy.GetComponent(); + if (boneApplyer != null) + { + gltf.extensions.VRM.firstPerson.lookAtHorizontalInner.Apply(boneApplyer.HorizontalInner); + gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(boneApplyer.HorizontalOuter); + gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(boneApplyer.VerticalDown); + gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(boneApplyer.VerticalUp); + } + else if (blendShapeApplyer != null) + { + // ToDo + throw new NotImplementedException(); + } + } + else if (lookAt != null) + { + gltf.extensions.VRM.firstPerson.lookAtHorizontalInner.Apply(lookAt.HorizontalInner); + gltf.extensions.VRM.firstPerson.lookAtHorizontalOuter.Apply(lookAt.HorizontalOuter); + gltf.extensions.VRM.firstPerson.lookAtVerticalDown.Apply(lookAt.VerticalDown); + gltf.extensions.VRM.firstPerson.lookAtVerticalUp.Apply(lookAt.VerticalUp); + } + } + } + + // materials + foreach (var m in exporter.Materials) + { + gltf.extensions.VRM.materialProperties.Add(glTF_VRM_Material.CreateFromMaterial(m, exporter.Textures)); + } + } + } +} diff --git a/Scripts/Format/Editor/VRMExporter.cs.meta b/Scripts/Format/Editor/VRMExporter.cs.meta new file mode 100644 index 000000000..f286ab348 --- /dev/null +++ b/Scripts/Format/Editor/VRMExporter.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 73f9ea5f415aa1d449d6cd63aeaccb67 +timeCreated: 1516612766 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/Editor/VRMExporterMenu.cs b/Scripts/Format/Editor/VRMExporterMenu.cs new file mode 100644 index 000000000..e990f2a9f --- /dev/null +++ b/Scripts/Format/Editor/VRMExporterMenu.cs @@ -0,0 +1,124 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UniGLTF; +using System.IO; + +namespace VRM +{ + public class VRMExporterWizard : ScriptableWizard + { + const string EXTENSION = ".vrm"; + + public GameObject Target; + + public bool PoseNormalization; + + public static void CreateWizard() + { + var wiz = ScriptableWizard.DisplayWizard( + "VRM Exporter", "Export"); + wiz.Target = Selection.activeObject as GameObject; + + // update checkbox + var desc = wiz.Target.GetComponent(); + if (desc == null) + { + wiz.PoseNormalization = true; + } + } + + static string m_dir = Path.GetFullPath(Application.dataPath); + + void OnWizardCreate() + { + // save dialog + Debug.LogFormat("OnWizardCreate: {0}", m_dir); + var path = EditorUtility.SaveFilePanel( + "Save vrm", + m_dir, + Target.name + EXTENSION, + EXTENSION.Substring(1)); + if (string.IsNullOrEmpty(path)) + { + return; + } + m_dir = Path.GetDirectoryName(path); + + // export + var target = Target; + if (PoseNormalization) + { + Undo.RecordObjects(Target.transform.Traverse().ToArray(), "before normalize"); + var map = new Dictionary(); + target = VRM.BoneNormalizer.Execute(Target, map); + VRMHumanoidNorimalizerMenu.CopyVRMComponents(Target, target, map); + Undo.PerformUndo(); + } + + VRMExporter.Export(target, path); + + if (Target!=target) + { + GameObject.DestroyImmediate(target); + } + + if (path.StartsWithUnityAssetPath()) + { + AssetDatabase.ImportAsset(path.ToUnityRelativePath()); + } + } + + void OnWizardUpdate() + { + helpString = @"select humanoid root(require Animator with valid humanoid avatar). +"; + } + } + + public static class VRMExporterMenu + { + const string CONVERT_HUMANOID_KEY = "VRM/export humanoid"; + + [MenuItem(CONVERT_HUMANOID_KEY, true, 1)] + private static bool ExportValidate() + { + var root = Selection.activeObject as GameObject; + if (root == null) + { + return false; + } + + var animator = root.GetComponent(); + if (animator == null) + { + return false; + } + + var avatar = animator.avatar; + if (avatar == null) + { + return false; + } + + if (!avatar.isValid) + { + return false; + } + + if (!avatar.isHuman) + { + return false; + } + + return true; + } + + [MenuItem(CONVERT_HUMANOID_KEY, false, 1)] + private static void ExportFromMenu() + { + VRMExporterWizard.CreateWizard(); + } + } +} diff --git a/Scripts/Format/Editor/VRMExporterMenu.cs.meta b/Scripts/Format/Editor/VRMExporterMenu.cs.meta new file mode 100644 index 000000000..ee2067f06 --- /dev/null +++ b/Scripts/Format/Editor/VRMExporterMenu.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a8e41aa30fcc76e43ad8588aef8572ea +timeCreated: 1520491195 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/Editor/VRMHumanoidNormalizerMenu.cs b/Scripts/Format/Editor/VRMHumanoidNormalizerMenu.cs new file mode 100644 index 000000000..f5be4099b --- /dev/null +++ b/Scripts/Format/Editor/VRMHumanoidNormalizerMenu.cs @@ -0,0 +1,162 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UniGLTF; + + +namespace VRM +{ + public static class VRMHumanoidNorimalizerMenu + { + const string MENU_KEY = "VRM/create normalized humanoid"; + [MenuItem(MENU_KEY, true, 1)] + private static bool ExportValidate() + { + var root=Selection.activeObject as GameObject; + if (root == null) + { + return false; + } + + var animator = root.GetComponent(); + if (animator == null) + { + return false; + } + + var avatar = animator.avatar; + if (avatar == null) + { + return false; + } + + if (!avatar.isValid) { + return false; + } + + if (!avatar.isHuman) + { + return false; + } + + return true; + } + + [MenuItem(MENU_KEY, false, 1)] + private static void ExportFromMenu() + { + var go = Selection.activeObject as GameObject; + Undo.RecordObjects(go.transform.Traverse().ToArray(), "before normalize"); + var map = new Dictionary(); + var normalized = VRM.BoneNormalizer.Execute(go, map); + CopyVRMComponents(go, normalized, map); + Undo.PerformUndo(); + } + + // + // トップレベルのMonoBehaviourを移植する + // + public static void CopyVRMComponents(GameObject go, GameObject root, + Dictionary map) + { + { + // blendshape + var src = go.GetComponent(); + if (src != null) + { + var dst = root.AddComponent(); + dst.BlendShapeAvatar = src.BlendShapeAvatar; + } + } + + { + var secondary = go.transform.Find("secondary"); + if (secondary == null) + { + secondary = go.transform; + } + + var dstSecondary = root.transform.Find("secondary"); + if (dstSecondary == null) + { + dstSecondary = new GameObject("secondary").transform; + dstSecondary.SetParent(root.transform, false); + } + + // 揺れモノ + foreach (var src in go.transform.Traverse().Select(x => x.GetComponent()).Where(x => x != null)) + { + var dst = map[src.transform]; + var dstColliderGroup = dst.gameObject.AddComponent(); + dstColliderGroup.Colliders = src.Colliders.Select(y => + { + var offset = dst.worldToLocalMatrix.MultiplyPoint(src.transform.localToWorldMatrix.MultiplyPoint(y.Offset)); + return new VRMSpringBoneColliderGroup.SphereCollider + { + Offset = offset, + Radius = y.Radius + }; + }).ToArray(); + } + + foreach (var src in secondary.GetComponents()) + { + var dst = dstSecondary.gameObject.AddComponent(); + dst.m_comment = src.m_comment; + dst.RootBones = src.RootBones.Select(x => map[x]).ToList(); + if (src.ColliderGroups != null) + { + dst.ColliderGroups = src.ColliderGroups.Select(x => map[x.transform].GetComponent()).ToArray(); + } + } + } + + { + // meta + var src = go.GetComponent(); + if (src != null) + { + src.CopyTo(root); + } + } + + { + // firstPerson + var src = go.GetComponent(); + if (src != null) + { + src.CopyTo(root, map); + } + } + + { + // lookAt + var src = go.GetComponent(); + if (src != null) + { + src.CopyTo(root, map); + } + } + + { + // humanoid + var dst = root.AddComponent(); + var src = go.GetComponent(); + if (src != null) + { + dst.Avatar = src.Avatar; + dst.Description = src.Description; + } + else + { + var animator = go.GetComponent(); + if (animator != null) + { + dst.Avatar = animator.avatar; + } + } + } + } + } +} diff --git a/Scripts/Format/Editor/VRMHumanoidNormalizerMenu.cs.meta b/Scripts/Format/Editor/VRMHumanoidNormalizerMenu.cs.meta new file mode 100644 index 000000000..619ee0967 --- /dev/null +++ b/Scripts/Format/Editor/VRMHumanoidNormalizerMenu.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b3e1aacd7b7e1fb468b3378de03e5629 +timeCreated: 1520488809 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/Editor/VRMImporterMenu.cs b/Scripts/Format/Editor/VRMImporterMenu.cs new file mode 100644 index 000000000..3c905321e --- /dev/null +++ b/Scripts/Format/Editor/VRMImporterMenu.cs @@ -0,0 +1,54 @@ +#if USE_VRMIMPORTER_MENU +using System.IO; +using UnityEditor; +using UnityEngine; + +namespace VRM +{ + public static class VRMImporterMenu + { + [MenuItem("VRM/import from external file")] + static void ImportMenu() + { + var path = EditorUtility.OpenFilePanel("open vrm", "", "vrm"); + if (string.IsNullOrEmpty(path)) + { + return; + } + + var ext = Path.GetExtension(path).ToLower(); + if (ext != ".vrm") + { + return; + } + + if (path.StartsWithUnityAssetPath()) + { + Debug.LogWarning("vrm in AssetFolder is imported automatically"); + Selection.activeObject = AssetDatabase.LoadAssetAtPath(path.Replace(".vrm", ".prefab").ToUnityRelativePath()); + return; + } + + var root = VRMImporter.LoadFromPath(path); + + if (!EditorApplication.isPlaying) + { + // save root as Asset + var prefabPath = EditorUtility.SaveFilePanel("save vrm prefab", + "Assets", + Path.GetFileNameWithoutExtension(path) + ".prefab", + "prefab" + ); + + if (!string.IsNullOrEmpty(prefabPath)) + { + VRMAssetWriter.SaveAsPrefab(root, prefabPath); + + var prefab = AssetDatabase.LoadAssetAtPath(prefabPath.ToUnityRelativePath()); + Selection.activeObject = prefab; + } + } + } + } +} +#endif \ No newline at end of file diff --git a/Scripts/Format/Editor/VRMImporterMenu.cs.meta b/Scripts/Format/Editor/VRMImporterMenu.cs.meta new file mode 100644 index 000000000..921acdc6f --- /dev/null +++ b/Scripts/Format/Editor/VRMImporterMenu.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: da5decfeae53a6444977caf85d09bc88 +timeCreated: 1517153624 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/Editor/VRMVersionMenu.cs b/Scripts/Format/Editor/VRMVersionMenu.cs new file mode 100644 index 000000000..f6f778644 --- /dev/null +++ b/Scripts/Format/Editor/VRMVersionMenu.cs @@ -0,0 +1,46 @@ +using System.IO; +using UnityEditor; + + +namespace VRM +{ + public static class VRMVersionMenu + { + const string path = "Assets/VRM/Scripts/Format/VRMVersion.cs"; + const string template = @" +namespace VRM +{{ + public static class VRMVersion + {{ + public const int MAJOR = {0}; + public const int MINOR = {1}; + + public const string VERSION = ""{0}.{1}""; + + public const string DecrementMenuName = ""VRM/Version({0}.{1}) Decrement""; + public const string IncrementMenuName = ""VRM/Version({0}.{1}) Increment""; + }} +}} +"; + +#if VRM_DEVELOP + [MenuItem(VRMVersion.IncrementMenuName)] +#endif + public static void IncrementVersion() + { + var source = string.Format(template, VRMVersion.MAJOR, VRMVersion.MINOR + 1); + File.WriteAllText(path, source); + AssetDatabase.Refresh(); + } + +#if VRM_DEVELOP + [MenuItem(VRMVersion.DecrementMenuName)] +#endif + public static void DecrementVersion() + { + var source = string.Format(template, VRMVersion.MAJOR, VRMVersion.MINOR - 1); + File.WriteAllText(path, source); + AssetDatabase.Refresh(); + } + } +} diff --git a/Scripts/Format/Editor/VRMVersionMenu.cs.meta b/Scripts/Format/Editor/VRMVersionMenu.cs.meta new file mode 100644 index 000000000..9d7c9e567 --- /dev/null +++ b/Scripts/Format/Editor/VRMVersionMenu.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 0c69abb555d67f647a7d3175e35e37d8 +timeCreated: 1522130550 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/Editor/vrmAssetPostprocessor.cs b/Scripts/Format/Editor/vrmAssetPostprocessor.cs new file mode 100644 index 000000000..ddf649074 --- /dev/null +++ b/Scripts/Format/Editor/vrmAssetPostprocessor.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; +using UnityEditor; +using UnityEngine; + + +namespace VRM +{ + public class vrmAssetPostprocessor : AssetPostprocessor + { + static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) + { + foreach (string path in importedAssets) + { + var ext = Path.GetExtension(path).ToLower(); + if (ext == ".vrm") + { + VRMImporterContext context = null; + try + { + context=VRMImporter.LoadFromPath(path); + + /* + var prefabPath = String.Format("{0}/{1}.prefab", + Path.GetDirectoryName(path), + Path.GetFileNameWithoutExtension(path)); + + VRMAssetWriter.SaveAsPrefab(context.Root, prefabPath); + + var prefab = AssetDatabase.LoadAssetAtPath(prefabPath.ToUnityRelativePath()); + Selection.activeObject = prefab; + */ + + context.SaveAsAsset(); + context.Destroy(false); + } + catch(Exception ex) + { + Debug.LogError(ex); + if (context != null) + { + context.Destroy(true); + } + } + } + } + } + } +} diff --git a/Scripts/Format/Editor/vrmAssetPostprocessor.cs.meta b/Scripts/Format/Editor/vrmAssetPostprocessor.cs.meta new file mode 100644 index 000000000..162103e60 --- /dev/null +++ b/Scripts/Format/Editor/vrmAssetPostprocessor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 561392fdfe88bf14e83b6e89a075cc52 +timeCreated: 1517119659 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/VRMException.cs b/Scripts/Format/VRMException.cs new file mode 100644 index 000000000..e56a276ab --- /dev/null +++ b/Scripts/Format/VRMException.cs @@ -0,0 +1,15 @@ +using System; + + +namespace VRM +{ + class VRMException : Exception + { + public VRMException() + { } + public VRMException(string msg) : base(msg) + { } + public VRMException(string msg, params object[] args) : base(string.Format(msg, args)) + { } + } +} diff --git a/Scripts/Format/VRMException.cs.meta b/Scripts/Format/VRMException.cs.meta new file mode 100644 index 000000000..1ce57a3ff --- /dev/null +++ b/Scripts/Format/VRMException.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c34ca281dd113124cbe3d277d0955291 +timeCreated: 1519982614 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/VRMFormat.cs b/Scripts/Format/VRMFormat.cs new file mode 100644 index 000000000..11478f33e --- /dev/null +++ b/Scripts/Format/VRMFormat.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using UniGLTF; + + +namespace VRM +{ + [Serializable] + public class glTF_VRM_extensions : JsonSerializableBase + { + public string version = VRMVersion.VERSION; + public glTF_VRM_Meta meta = new glTF_VRM_Meta(); + public glTF_VRM_Humanoid humanoid = new glTF_VRM_Humanoid(); + public glTF_VRM_Firstperson firstPerson = new glTF_VRM_Firstperson(); + public glTF_VRM_BlendShapeMaster blendShapeMaster = new glTF_VRM_BlendShapeMaster(); + public glTF_VRM_SecondaryAnimation secondaryAnimation = new glTF_VRM_SecondaryAnimation(); + public List materialProperties = new List(); + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => version); + f.KeyValue(() => meta); + f.KeyValue(() => humanoid); + f.KeyValue(() => firstPerson); + f.KeyValue(() => blendShapeMaster); + f.KeyValue(() => secondaryAnimation); + f.KeyValue(() => materialProperties); + } + } + + [Serializable] + public class glTF_extensions : JsonSerializableBase + { + public glTF_VRM_extensions VRM = new glTF_VRM_extensions(); + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => VRM); + } + } + + [Serializable] + public class glTF_VRM : glTF + { + public glTF_extensions extensions = new glTF_extensions(); + public List extensionsUsed = new List + { + "VRM", + }; + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => extensions); + base.SerializeMembers(f); + } + } +} diff --git a/Scripts/Format/VRMFormat.cs.meta b/Scripts/Format/VRMFormat.cs.meta new file mode 100644 index 000000000..ae2eaf1f5 --- /dev/null +++ b/Scripts/Format/VRMFormat.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 20eca00211c61d047b586f852b818b8f +timeCreated: 1517308526 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/VRMImporter.cs b/Scripts/Format/VRMImporter.cs new file mode 100644 index 000000000..da579b1e2 --- /dev/null +++ b/Scripts/Format/VRMImporter.cs @@ -0,0 +1,661 @@ +using System; +using System.IO; +using System.Linq; +using UnityEngine; +using UniGLTF; +using System.Collections.Generic; +using System.Text; +using System.Collections; +using UniTask; + + +namespace VRM +{ + public static class VRMImporter + { + const string HUMANOID_KEY = "humanoid"; + const string MATERIAL_KEY = "materialProperties"; + + public static VRMImporterContext LoadFromPath(string path) + { + return LoadFromBytes(File.ReadAllBytes(path), path); + } + + public static VRMImporterContext LoadFromBytes(byte[] bytes, string path=null) + { + var context = new VRMImporterContext(); + if (!string.IsNullOrEmpty(path)) + { + context.Path = path; + } + + var chunks = glbImporter.ParseGlbChanks(bytes); + + if (chunks.Count != 2) + { + throw new Exception("unknown chunk count: " + chunks.Count); + } + + if (chunks[0].ChunkType != GlbChunkType.JSON) + { + throw new Exception("chunk 0 is not JSON"); + } + + if (chunks[1].ChunkType != GlbChunkType.BIN) + { + throw new Exception("chunk 1 is not BIN"); + } + + var jsonBytes = chunks[0].Bytes; + var json = Encoding.UTF8.GetString(jsonBytes.Array, jsonBytes.Offset, jsonBytes.Count); + + context.Json = json; + context.CreateMaterial = VRMImporter.GetMaterialFunc(glTF_VRM_Material.Parse(json)); + + gltfImporter.Import(context, chunks[1].Bytes); + if (string.IsNullOrEmpty(context.Path)) + { + if (string.IsNullOrEmpty(context.VRM.extensions.VRM.meta.title)) + { + context.Root.name = "VRM_LOADED"; + } + else + { + context.Root.name = context.VRM.extensions.VRM.meta.title; + } + } + else + { + context.Root.name = Path.GetFileNameWithoutExtension(context.Path); + } + + OnLoadModel(context); + + context.ShowMeshes(); + + return context; + } + + public static CreateMaterialFunc GetMaterialFunc(List materials) + { + var fallback = gltfImporter.CreateMaterialFuncFromShader(Shader.Find("Standard")); + if (materials == null && materials.Count == 0) + { + return fallback; + } + + return (ctx, i) => + { + var item = materials[i]; + var shaderName = item.shader; + var shader = Shader.Find(shaderName); + if (shader == null) + { + return fallback(ctx, i); + } + else + { + var material = new Material(shader); + material.name = item.name; + material.renderQueue = item.renderQueue; + + foreach (var kv in item.floatProperties) + { + material.SetFloat(kv.Key, kv.Value); + } + foreach (var kv in item.vectorProperties) + { + var v = new Vector4(kv.Value[0], kv.Value[1], kv.Value[2], kv.Value[3]); + material.SetVector(kv.Key, v); + } + foreach (var kv in item.textureProperties) + { + material.SetTexture(kv.Key, ctx.Textures[kv.Value].Texture); + } + foreach (var kv in item.keywordMap) + { + if (kv.Value) + { + material.EnableKeyword(kv.Key); + } + else + { + material.DisableKeyword(kv.Key); + } + } + foreach (var kv in item.tagMap) + { + material.SetOverrideTag(kv.Key, kv.Value); + } + return material; + } + }; + } + + #region OnLoad + public static Unit OnLoadModel(VRMImporterContext context) + { + try + { + LoadHumanoidObsolete(context); + Debug.LogWarning("LoadHumanoidObsolete"); + } + catch (Exception ex) + { + LoadHumanoid(context); + } + + LoadBlendShapeMaster(context); + LoadSecondaryMotions(context); + LoadFirstPerson(context); + LoadMeta(context); + + return Unit.Default; + } + + static void LoadMeta(VRMImporterContext context) + { + var meta = context.Root.AddComponent(); + var gltfMeta = context.VRM.extensions.VRM.meta; + meta.Author = gltfMeta.author; + meta.ContactInformation = gltfMeta.contactInformation; + meta.Title = gltfMeta.title; + if (gltfMeta.texture != -1) + { + meta.Thumbnail = context.Textures[gltfMeta.texture].Texture; + } + else + { + // 作る + var lookAt = context.Root.GetComponent(); + var thumbnail = lookAt.CreateThumbnail(); + thumbnail.name = "thumbnail"; + meta.Thumbnail = thumbnail; + //context.Textures.Add(new TextureItem(thumbnail)); + } + + meta.LicenseType = gltfMeta.licenseType; + meta.OtherLicenseUrl = gltfMeta.otherLicenseUrl; + meta.Reference = gltfMeta.reference; + } + + static void LoadFirstPerson(VRMImporterContext context) + { + var firstPerson = context.Root.AddComponent(); + + var gltfFirstPerson = context.VRM.extensions.VRM.firstPerson; + if (gltfFirstPerson.firstPersonBone != -1) + { + firstPerson.FirstPersonBone = context.Nodes[gltfFirstPerson.firstPersonBone]; + firstPerson.FirstPersonOffset = gltfFirstPerson.firstPersonBoneOffset; + } + else + { + // fallback + firstPerson.SetDefault(); + } + firstPerson.TraverseRenderers(context); + + // LookAt + var lookAtHead = context.Root.AddComponent(); + + var lookAt = context.Root.AddComponent(); + lookAt.HorizontalInner.Apply(gltfFirstPerson.lookAtHorizontalInner); + lookAt.HorizontalOuter.Apply(gltfFirstPerson.lookAtHorizontalOuter); + lookAt.VerticalDown.Apply(gltfFirstPerson.lookAtVerticalDown); + lookAt.VerticalUp.Apply(gltfFirstPerson.lookAtVerticalUp); + //lookAt.GetBones(); + } + + static void LoadSecondaryMotions(VRMImporterContext context) + { + var secondary = context.Root.transform.Find("secondary"); + if (secondary == null) + { + secondary = new GameObject("secondary").transform; + secondary.SetParent(context.Root.transform, false); + } + + var secondaryAnimation = context.VRM.extensions.VRM.secondaryAnimation; + var colliders = new List(); + foreach (var colliderGroup in secondaryAnimation.colliderGroups) + { + var vrmGroup = context.Nodes[colliderGroup.node].gameObject.AddComponent(); + vrmGroup.Colliders = colliderGroup.colliders.Select(x => + { + return new VRMSpringBoneColliderGroup.SphereCollider + { + Offset = x.offset, + Radius = x.radius + }; + }).ToArray(); + colliders.Add(vrmGroup); + } + + if (secondaryAnimation.boneGroups.Count > 0) + { + foreach (var boneGroup in secondaryAnimation.boneGroups) + { + var vrmBoneGroup = secondary.gameObject.AddComponent(); + if (boneGroup.center != -1) + { + vrmBoneGroup.m_center = context.Nodes[boneGroup.center]; + } + vrmBoneGroup.m_comment = boneGroup.comment; + vrmBoneGroup.m_dragForce = boneGroup.dragForce; + vrmBoneGroup.m_gravityDir = boneGroup.gravityDir; + vrmBoneGroup.m_gravityPower = boneGroup.gravityPower; + vrmBoneGroup.m_hitRadius = boneGroup.hitRadius; + vrmBoneGroup.m_stiffnessForce = boneGroup.stiffiness; + if (boneGroup.colliderGroups != null && boneGroup.colliderGroups.Any()) + { + vrmBoneGroup.ColliderGroups = boneGroup.colliderGroups.Select(x => colliders[x]).ToArray(); + } + vrmBoneGroup.RootBones = boneGroup.bones.Select(x => context.Nodes[x]).ToList(); + } + } + else + { + secondary.gameObject.AddComponent(); + } + } + + static void LoadBlendShapeMaster(VRMImporterContext context) + { + context.BlendShapeAvatar = ScriptableObject.CreateInstance(); + context.BlendShapeAvatar.name = "BlendShape"; + + var blendShapeList = context.VRM.extensions.VRM.blendShapeMaster.blendShapeGroups; + if (blendShapeList != null && blendShapeList.Count > 0) + { + foreach (var x in blendShapeList) + { + context.BlendShapeAvatar.Clips.Add(LoadBlendShapeBind(context, x)); + } + } + else + { + // set default + context.BlendShapeAvatar.Clips.Add(BlendShapeClip.Create(BlendShapePreset.Neutral)); + context.BlendShapeAvatar.Clips.Add(BlendShapeClip.Create(BlendShapePreset.A)); + context.BlendShapeAvatar.Clips.Add(BlendShapeClip.Create(BlendShapePreset.I)); + context.BlendShapeAvatar.Clips.Add(BlendShapeClip.Create(BlendShapePreset.U)); + context.BlendShapeAvatar.Clips.Add(BlendShapeClip.Create(BlendShapePreset.E)); + context.BlendShapeAvatar.Clips.Add(BlendShapeClip.Create(BlendShapePreset.O)); + context.BlendShapeAvatar.Clips.Add(BlendShapeClip.Create(BlendShapePreset.Blink)); + context.BlendShapeAvatar.Clips.Add(BlendShapeClip.Create(BlendShapePreset.Joy)); + context.BlendShapeAvatar.Clips.Add(BlendShapeClip.Create(BlendShapePreset.Angry)); + context.BlendShapeAvatar.Clips.Add(BlendShapeClip.Create(BlendShapePreset.Sorrow)); + context.BlendShapeAvatar.Clips.Add(BlendShapeClip.Create(BlendShapePreset.Fun)); + } + + var proxy = context.Root.AddComponent(); + context.BlendShapeAvatar.CreateDefault(); + proxy.BlendShapeAvatar = context.BlendShapeAvatar; + } + + private static BlendShapeClip LoadBlendShapeBind(VRMImporterContext context, + glTF_VRM_BlendShapeGroup group) + { + var asset = ScriptableObject.CreateInstance(); + var groupName = group.name; + var prefix = "BlendShape."; + while (groupName.StartsWith(prefix)) + { + groupName = groupName.Substring(prefix.Length); + } + asset.name = "BlendShape." + groupName; + + if (group != null) + { + asset.BlendShapeName = groupName; + asset.Preset = group.presetName.ToBlendShapePreset(); + if (asset.Preset == BlendShapePreset.Unknown) + { + // fallback + asset.Preset = group.name.ToBlendShapePreset(); + } + asset.Values = group.binds.Select(x => + { + var mesh = context.Meshes[x.mesh].Mesh; + var node = context.Root.transform.Traverse().First(y => y.GetSharedMesh() == mesh); + var relativePath = UniGLTF.UnityExtensions.RelativePathFrom(node, context.Root.transform); + return new BlendShapeBinding + { + //Name = name, + RelativePath = relativePath, + Index = x.index, + Weight = x.weight, + }; + }) + .ToArray(); + } + + return asset; + } + + static String ToHumanBoneName(HumanBodyBones b) + { + foreach (var x in HumanTrait.BoneName) + { + if (x.Replace(" ", "") == b.ToString()) + { + return x; + } + } + + throw new KeyNotFoundException(); + } + + static SkeletonBone ToSkeletonBone(Transform t) + { + var sb = new SkeletonBone(); + sb.name = t.name; + sb.position = t.localPosition; + sb.rotation = t.localRotation; + sb.scale = t.localScale; + return sb; + } + + [Obsolete] + private static void LoadHumanoidObsolete(VRMImporterContext context) + { + var parsed = context.Json.ParseAsJson()["extensions"]["VRM"]; + var skeleton = context.Root.transform.Traverse().Select(x => ToSkeletonBone(x)).ToArray(); + + var description = new HumanDescription + { + human = parsed[HUMANOID_KEY]["bones"] + .ObjectItems + .Select(x => new { x.Key, Index = x.Value.GetInt32() }) + .Where(x => x.Index != -1) + .Select(x => + { + var humanBone = (HumanBodyBones)Enum.Parse(typeof(HumanBodyBones), x.Key.ToUpperCamelCase()); + var hb = new HumanBone + { + boneName = context.Nodes[x.Index].name, + humanName = ToHumanBoneName(humanBone) + }; + hb.limit.useDefaultValues = true; + return hb; + }).ToArray(), + skeleton = skeleton, + lowerArmTwist = 0.5f, + upperArmTwist = 0.5f, + upperLegTwist = 0.5f, + lowerLegTwist = 0.5f, + armStretch = 0.05f, + legStretch = 0.05f, + feetSpacing = 0.0f, + }; + + context.HumanoidAvatar = AvatarBuilder.BuildHumanAvatar(context.Root, description); + context.HumanoidAvatar.name = Path.GetFileNameWithoutExtension(context.Path); + + context.AvatarDescription = UniHumanoid.AvatarDescription.CreateFrom(description); + context.AvatarDescription.name = "AvatarDescription"; + var humanoid = context.Root.AddComponent(); + humanoid.Avatar = context.HumanoidAvatar; + humanoid.Description = context.AvatarDescription; + + var animator = context.Root.GetComponent(); + if (animator == null) + { + animator = context.Root.AddComponent(); + } + animator.avatar = context.HumanoidAvatar; + } + + private static void LoadHumanoid(VRMImporterContext context) + { + context.AvatarDescription = context.VRM.extensions.VRM.humanoid.ToDescription(context.Nodes); + context.AvatarDescription.name = "AvatarDescription"; + context.HumanoidAvatar = context.AvatarDescription.CreateAvatar(context.Root.transform); + context.HumanoidAvatar.name = Path.GetFileNameWithoutExtension(context.Path); + + var humanoid = context.Root.AddComponent(); + humanoid.Avatar = context.HumanoidAvatar; + humanoid.Description = context.AvatarDescription; + + var animator = context.Root.GetComponent(); + if (animator == null) + { + animator = context.Root.AddComponent(); + } + animator.avatar = context.HumanoidAvatar; + } + #endregion + + #region LoadVrmAsync + static IEnumerator LoadTextures(VRMImporterContext context) + { + foreach (var gltfTexture in context.GLTF.textures) + { + var x = UniGLTF.gltfImporter.ImportTexture(context.GLTF, gltfTexture.source); + context.Textures.Add(x); + yield return null; + } + } + + static IEnumerator LoadMaterials(VRMImporterContext context) + { + if (context.GLTF.materials == null || !context.GLTF.materials.Any()) + { + context.Materials.Add(context.CreateMaterial(context, 0)); + } + else + { + for (int i = 0; i < context.GLTF.materials.Count; ++i) + { + context.Materials.Add(context.CreateMaterial(context, i)); + yield return null; + } + } + } + + static IEnumerator LoadMeshes(VRMImporterContext context) + { + for (int i = 0; i < context.GLTF.meshes.Count; ++i) + { + var meshWithMaterials = gltfImporter.ImportMesh(context, i); + var mesh = meshWithMaterials.Mesh; + if (string.IsNullOrEmpty(mesh.name)) + { + mesh.name = string.Format("UniGLTF import#{0}", i); + } + context.Meshes.Add(meshWithMaterials); + + yield return null; + } + } + + static IEnumerator LoadNodes(VRMImporterContext context) + { + foreach (var x in context.GLTF.nodes) + { + context.Nodes.Add(gltfImporter.ImportNode(x).transform); + yield return null; + } + } + + static IEnumerator BuildHierarchy(VRMImporterContext context) + { + var nodes = new List(); + for (int i = 0; i < context.Nodes.Count; ++i) + { + nodes.Add(gltfImporter.BuildHierarchy(context, i)); + yield return null; + } + + gltfImporter.FixCoordinate(context, nodes); + + // skinning + for (int i = 0; i < nodes.Count; ++i) + { + gltfImporter.SetupSkinning(context, nodes, i); + } + + // connect root + context.Root = new GameObject("_root_"); + foreach (var x in context.GLTF.rootnodes) + { + var t = nodes[x].Transform; + t.SetParent(context.Root.transform, false); + } + } + + public static void LoadVrmAsync(Byte[] bytes, Action onLoaded) + { + var ctx = new VRMImporterContext(); + LoadVrmAsync(ctx, bytes, onLoaded); + } + + public static void LoadVrmAsync(string path, Action onLoaded) + { + var ctx = new VRMImporterContext + { + Path = path, + }; + + var schedule = Schedulable.Create(); + + schedule.AddTask(MainThreadDispatcher.Instance.ThreadScheduler, () => + { + return File.ReadAllBytes(path); + }) + .Subscribe(MainThreadDispatcher.Instance.UnityScheduler, + bytes => + { + LoadVrmAsync(ctx, bytes, onLoaded); + }, + ex => + { + ctx.Destroy(true); + Debug.LogErrorFormat("Error in scheduler: {0}", ex); + }) + ; + } + + public static void LoadVrmAsync(VRMImporterContext ctx, Byte[] bytes, Action onLoaded) + { + var schedule = Schedulable.Create(); + + schedule + .AddTask(MainThreadDispatcher.Instance.ThreadScheduler, () => + { + return glbImporter.ParseGlbChanks(bytes); + }) + .ContinueWith(MainThreadDispatcher.Instance.ThreadScheduler, chunks => + { + if (chunks.Count != 2) + { + throw new Exception("unknown chunk count: " + chunks.Count); + } + + if (chunks[0].ChunkType != GlbChunkType.JSON) + { + throw new Exception("chunk 0 is not JSON"); + } + + if (chunks[1].ChunkType != GlbChunkType.BIN) + { + throw new Exception("chunk 1 is not BIN"); + } + + var jsonBytes = chunks[0].Bytes; + ctx.Json = Encoding.UTF8.GetString(jsonBytes.Array, jsonBytes.Offset, jsonBytes.Count); + + //var parsed = json.ParseAsJson(); + ctx.GLTF = JsonUtility.FromJson(ctx.Json); + if (ctx.GLTF.asset.version != "2.0") + { + throw new VRMException("unknown gltf version {0}", ctx.GLTF.asset.version); + } + ctx.GLTF.baseDir = Path.GetDirectoryName(ctx.Path); + foreach (var buffer in ctx.GLTF.buffers) + { + buffer.OpenStorage(ctx.GLTF.baseDir, chunks[1].Bytes); + } + + return Unit.Default; + }) + .Subscribe(MainThreadDispatcher.Instance.UnityScheduler, + _ => + { + BuildAsync(ctx, onLoaded); + }, + ex => + { + ctx.Destroy(true); + Debug.LogErrorFormat("Error in scheduler: {0}", ex); + }) + ; + } + + static void BuildAsync(VRMImporterContext ctx, Action onLoaded) + { + var schedulable = Schedulable.Create(); + + schedulable + .AddTask(MainThreadDispatcher.Instance.ThreadScheduler, () => + { + return glTF_VRM_Material.Parse(ctx.Json); + }) + .ContinueWith(MainThreadDispatcher.Instance.UnityScheduler, x => + { + // material function + ctx.CreateMaterial = VRMImporter.GetMaterialFunc(x); + }) + .OnExecute(MainThreadDispatcher.Instance.UnityScheduler, parent => + { + // textures + for (int i = 0; i < ctx.GLTF.textures.Count; ++i) + { + var index = i; + parent.AddTask(MainThreadDispatcher.Instance.UnityScheduler, + () => gltfImporter.ImportTexture(ctx.GLTF, index)) + .ContinueWith(MainThreadDispatcher.Instance.ThreadScheduler, x => ctx.Textures.Add(x)); + } + }) + .ContinueWithCoroutine(MainThreadDispatcher.Instance.UnityScheduler, () => LoadMaterials(ctx)) + .OnExecute(MainThreadDispatcher.Instance.UnityScheduler, parent => + { + // meshes + for (int i = 0; i < ctx.GLTF.meshes.Count; ++i) + { + var index = i; + parent.AddTask(MainThreadDispatcher.Instance.ThreadScheduler, + () => gltfImporter.ReadMesh(ctx, index)) + .ContinueWith(MainThreadDispatcher.Instance.UnityScheduler, x => gltfImporter.BuildMesh(ctx, x)) + .ContinueWith(MainThreadDispatcher.Instance.ThreadScheduler, x => ctx.Meshes.Add(x)) + ; + } + }) + .ContinueWithCoroutine(MainThreadDispatcher.Instance.UnityScheduler, () => LoadNodes(ctx)) + .ContinueWithCoroutine(MainThreadDispatcher.Instance.UnityScheduler, () => BuildHierarchy(ctx)) + .ContinueWith(MainThreadDispatcher.Instance.UnityScheduler, _ => VRMImporter.OnLoadModel(ctx)) + .Subscribe(MainThreadDispatcher.Instance.UnityScheduler, + _ => + { + Debug.LogFormat("task end: {0}/{1}/{2}/{3}", + ctx.Textures.Count, + ctx.Materials.Count, + ctx.Meshes.Count, + ctx.Nodes.Count + ); + ctx.Root.name = Path.GetFileNameWithoutExtension(ctx.Path); + + // 非表示のメッシュを表示する + ctx.ShowMeshes(); + + onLoaded(ctx.Root); + }, ex => + { + Debug.LogError(ex); + }) + ; + } + #endregion + } +} diff --git a/Scripts/Format/VRMImporter.cs.meta b/Scripts/Format/VRMImporter.cs.meta new file mode 100644 index 000000000..e6ca9d7b4 --- /dev/null +++ b/Scripts/Format/VRMImporter.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 7ec67bcfca2bdcc4484bcbdd1efe52f9 +timeCreated: 1517153624 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/VRMImporterContext.cs b/Scripts/Format/VRMImporterContext.cs new file mode 100644 index 000000000..5de440bb7 --- /dev/null +++ b/Scripts/Format/VRMImporterContext.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using UniGLTF; +using UnityEngine; + + +namespace VRM +{ + public class VRMImporterContext : ImporterContext + { + public UniHumanoid.AvatarDescription AvatarDescription; + public Avatar HumanoidAvatar; + public BlendShapeAvatar BlendShapeAvatar; + + public glTF_VRM VRM + { + get + { + return (glTF_VRM)GLTF; + } + } + +#if UNITY_EDITOR + protected override IEnumerable ObjectsForSubAsset() + { + foreach (var x in base.ObjectsForSubAsset()) + { + yield return x; + } + + yield return AvatarDescription; + yield return HumanoidAvatar; + yield return BlendShapeAvatar; + if (BlendShapeAvatar != null && BlendShapeAvatar.Clips != null) + { + foreach (var x in BlendShapeAvatar.Clips) + { + yield return x; + } + } + } +#endif + } +} diff --git a/Scripts/Format/VRMImporterContext.cs.meta b/Scripts/Format/VRMImporterContext.cs.meta new file mode 100644 index 000000000..d3dde769c --- /dev/null +++ b/Scripts/Format/VRMImporterContext.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3299c9bf57c48cc46a0bcd96b1394f18 +timeCreated: 1521446485 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/VRMVersion.cs b/Scripts/Format/VRMVersion.cs new file mode 100644 index 000000000..42f5a9c43 --- /dev/null +++ b/Scripts/Format/VRMVersion.cs @@ -0,0 +1,14 @@ + +namespace VRM +{ + public static class VRMVersion + { + public const int MAJOR = 0; + public const int MINOR = 1; + + public const string VERSION = "0.1"; + + public const string DecrementMenuName = "VRM/Version(0.1) Decrement"; + public const string IncrementMenuName = "VRM/Version(0.1) Increment"; + } +} diff --git a/Scripts/Format/VRMVersion.cs.meta b/Scripts/Format/VRMVersion.cs.meta new file mode 100644 index 000000000..b953c85a9 --- /dev/null +++ b/Scripts/Format/VRMVersion.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 93c46c8b64555f14bada9f5bb0b7761a +timeCreated: 1522130257 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/glTF_VRM_BlendShape.cs b/Scripts/Format/glTF_VRM_BlendShape.cs new file mode 100644 index 000000000..4af7fe14f --- /dev/null +++ b/Scripts/Format/glTF_VRM_BlendShape.cs @@ -0,0 +1,146 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using UniGLTF; +using UnityEngine; + + +namespace VRM +{ + /// + /// BlendShapeBind + /// + [Serializable] + public class glTF_VRM_BlendShapeBind : UniGLTF.JsonSerializableBase + { + public int mesh = -1; + public int index = -1; + public float weight = 0; + + protected override void SerializeMembers(UniGLTF.JsonFormatter f) + { + f.KeyValue(() => mesh); + f.KeyValue(() => index); + f.KeyValue(() => weight); + } + + public static glTF_VRM_BlendShapeBind Cerate(Transform root, List meshes, BlendShapeBinding binding) + { + var transform = UniGLTF.UnityExtensions.GetFromPath(root.transform, binding.RelativePath); + var renderer = transform.GetComponent(); + var mesh = renderer.sharedMesh; + var meshIndex = meshes.IndexOf(mesh); + + return new glTF_VRM_BlendShapeBind + { + mesh = meshIndex, + index = binding.Index, + weight = binding.Weight, + }; + } + } + + public enum BlendShapePreset + { + Unknown, + + Neutral, + + A, + I, + U, + E, + O, + + Blink, + + // 喜怒哀楽 + Joy, + Angry, + Sorrow, + Fun, + + // LookAt + LookUp, + LookDown, + LookLeft, + LookRight, + + Blink_L, + Blink_R, + } + + public static class BlendShpaePresetExtensions + { + /* + static string ToCamel(this string src) + { + if (string.IsNullOrEmpty(src)) return string.Empty; + return src.Substring(0, 1).ToUpper() + src.Substring(1); + } + */ + + public static BlendShapePreset ToBlendShapePreset(this string preset) + { + try + { + return (BlendShapePreset)Enum.Parse(typeof(BlendShapePreset), preset, true); + } + catch (Exception) + { + return default(BlendShapePreset); + } + } + } + + [Serializable] + public class glTF_VRM_BlendShapeGroup : UniGLTF.JsonSerializableBase + { + public string name; + public string presetName; + [Obsolete] + public string extendedName; + public List binds = new List(); + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => name); + f.KeyValue(() => presetName); + /* + if (name == "extended") + { + f.KeyValue(() => extendedName); + } + f.Key("flags"); f.Value((int)flags); + */ + f.KeyValue(() => binds); + } + } + + [Serializable] + public class glTF_VRM_BlendShapeMaster : UniGLTF.JsonSerializableBase + { + public List blendShapeGroups = new List(); + + public void Add(BlendShapeClip clip, Transform transform, List meshes) + { + var list = new List(); + if (clip.Values != null) + { + list.AddRange(clip.Values.Select(y => glTF_VRM_BlendShapeBind.Cerate(transform, meshes.ToList(), y))); + } + var group = new glTF_VRM_BlendShapeGroup + { + name = clip.BlendShapeName, + presetName = clip.Preset.ToString().ToLower(), + binds = list, + }; + blendShapeGroups.Add(group); + } + + protected override void SerializeMembers(UniGLTF.JsonFormatter f) + { + f.KeyValue(() => blendShapeGroups); + } + } +} diff --git a/Scripts/Format/glTF_VRM_BlendShape.cs.meta b/Scripts/Format/glTF_VRM_BlendShape.cs.meta new file mode 100644 index 000000000..043c8ab3b --- /dev/null +++ b/Scripts/Format/glTF_VRM_BlendShape.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 73f7fb3db66d55b4684333583a685757 +timeCreated: 1517549334 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/glTF_VRM_FirstPerson.cs b/Scripts/Format/glTF_VRM_FirstPerson.cs new file mode 100644 index 000000000..7f6c1b7e5 --- /dev/null +++ b/Scripts/Format/glTF_VRM_FirstPerson.cs @@ -0,0 +1,85 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using UniGLTF; +using UnityEngine; + + +namespace VRM +{ + [Serializable] + public class glTF_VRM_DegreeMap : UniGLTF.JsonSerializableBase + { + // time, value, inTangent, outTangent + public float[] curve; + public float xRange = 90.0f; + public float yRange = 10.0f; + + protected override void SerializeMembers(JsonFormatter f) + { + if (curve != null) + { + f.KeyValue(() => curve); + } + f.KeyValue(() => xRange); + f.KeyValue(() => yRange); + } + + public void Apply(CurveMapper mapper) + { + curve = mapper.Curve.keys.SelectMany(x => new float[] { x.time, x.value, x.inTangent, x.outTangent }).ToArray(); + xRange = mapper.CurveXRangeDegree; + yRange = mapper.CurveYRangeDegree; + } + } + + public enum FirstPersonFlag + { + Auto, // Create headlessModel + Both, // Default layer + ThirdPersonOnly, + FirstPersonOnly, + } + + [Serializable] + public class glTF_VRM_MeshAnnotation : JsonSerializableBase + { + public int mesh; + + public string firstPersonFlag; + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => mesh); + f.KeyValue(() => firstPersonFlag); + } + } + + [Serializable] + public class glTF_VRM_Firstperson : UniGLTF.JsonSerializableBase + { + public int firstPersonBone = -1; + + public Vector3 firstPersonBoneOffset; + + public List meshAnnotations = new List(); + + // lookat + public glTF_VRM_DegreeMap lookAtHorizontalInner = new glTF_VRM_DegreeMap(); + public glTF_VRM_DegreeMap lookAtHorizontalOuter = new glTF_VRM_DegreeMap(); + public glTF_VRM_DegreeMap lookAtVerticalDown = new glTF_VRM_DegreeMap(); + public glTF_VRM_DegreeMap lookAtVerticalUp = new glTF_VRM_DegreeMap(); + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => firstPersonBone); + f.KeyValue(() => firstPersonBoneOffset); + f.KeyValue(() => meshAnnotations); + + f.KeyValue(() => lookAtHorizontalInner); + f.KeyValue(() => lookAtHorizontalOuter); + f.KeyValue(() => lookAtVerticalDown); + f.KeyValue(() => lookAtVerticalUp); + } + } +} diff --git a/Scripts/Format/glTF_VRM_FirstPerson.cs.meta b/Scripts/Format/glTF_VRM_FirstPerson.cs.meta new file mode 100644 index 000000000..615736dc0 --- /dev/null +++ b/Scripts/Format/glTF_VRM_FirstPerson.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: fe59508ed49a5db4287c74e0061799b3 +timeCreated: 1519282840 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/glTF_VRM_Humanoid.cs b/Scripts/Format/glTF_VRM_Humanoid.cs new file mode 100644 index 000000000..d1bcdfd99 --- /dev/null +++ b/Scripts/Format/glTF_VRM_Humanoid.cs @@ -0,0 +1,221 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UniGLTF; +using UnityEngine; +using UniHumanoid; + + +namespace VRM +{ + public enum VRMBone + { + hips, + leftUpperLeg, + rightUpperLeg, + leftLowerLeg, + rightLowerLeg, + leftFoot, + rightFoot, + spine, + chest, + neck, + head, + leftShoulder, + rightShoulder, + leftUpperArm, + rightUpperArm, + leftLowerArm, + rightLowerArm, + leftHand, + rightHand, + leftToes, + rightToes, + leftEye, + rightEye, + jaw, + leftThumbProximal, + leftThumbIntermediate, + leftThumbDistal, + leftIndexProximal, + leftIndexIntermediate, + leftIndexDistal, + leftMiddleProximal, + leftMiddleIntermediate, + leftMiddleDistal, + leftRingProximal, + leftRingIntermediate, + leftRingDistal, + leftLittleProximal, + leftLittleIntermediate, + leftLittleDistal, + rightThumbProximal, + rightThumbIntermediate, + rightThumbDistal, + rightIndexProximal, + rightIndexIntermediate, + rightIndexDistal, + rightMiddleProximal, + rightMiddleIntermediate, + rightMiddleDistal, + rightRingProximal, + rightRingIntermediate, + rightRingDistal, + rightLittleProximal, + rightLittleIntermediate, + rightLittleDistal, + upperChest, + } + + public static class VRMBoneExtensions + { + public static VRMBone FromHumanBodyBone(this HumanBodyBones human) + { + return (VRMBone)Enum.Parse(typeof(VRMBone), human.ToString(), true); + } + public static HumanBodyBones ToHumanBodyBone(this VRMBone bone) + { + return (HumanBodyBones)Enum.Parse(typeof(HumanBodyBones), bone.ToString(), true); + } + } + + [Serializable] + public class glTF_VRM_HumanoidBone : JsonSerializableBase + { + public string bone; + public VRMBone vrmBone + { + set + { + bone = value.ToString(); + } + get + { + return (VRMBone)Enum.Parse(typeof(VRMBone), bone, true); + } + } + public int node = -1; + + public bool useDefaultValues = true; + public Vector3 min; + public Vector3 max; + public Vector3 center; + public float axisLength; + + protected override void SerializeMembers(JsonFormatter f) + { + f.Key("bone"); f.Value((string)bone.ToString()); + f.KeyValue(() => node); + f.KeyValue(() => useDefaultValues); + if (!useDefaultValues) + { + f.KeyValue(() => min); + f.KeyValue(() => max); + f.KeyValue(() => center); + f.KeyValue(() => axisLength); + } + } + } + + [Serializable] + public class glTF_VRM_Humanoid : JsonSerializableBase + { + public List humanBones = new List(); + public float armStretch = 0.05f; + public float legStretch = 0.05f; + public float upperArmTwist = 0.5f; + public float lowerArmTwist = 0.5f; + public float upperLegTwist = 0.5f; + public float lowerLegTwist = 0.5f; + public float feetSpacing = 0; + public bool hasTranslationDoF = false; + + public void SetNodeIndex(HumanBodyBones _key, int node) + { + var key = _key.FromHumanBodyBone(); + var index = humanBones.FindIndex(x => x.vrmBone == key); + if (index == -1 || humanBones[index] == null) + { + // not found + humanBones.Add(new glTF_VRM_HumanoidBone + { + vrmBone = key, + node = node + }); + } + else + { + humanBones[index].node = node; + } + } + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => humanBones); + f.KeyValue(() => armStretch); + f.KeyValue(() => legStretch); + f.KeyValue(() => upperArmTwist); + f.KeyValue(() => lowerArmTwist); + f.KeyValue(() => upperLegTwist); + f.KeyValue(() => lowerLegTwist); + f.KeyValue(() => feetSpacing); + f.KeyValue(() => hasTranslationDoF); + } + + public void Apply(UniHumanoid.AvatarDescription desc, List nodes) + { + armStretch = desc.armStretch; + legStretch = desc.legStretch; + upperArmTwist = desc.upperArmTwist; + lowerArmTwist = desc.lowerArmTwist; + upperLegTwist = desc.upperLegTwist; + lowerLegTwist = desc.lowerArmTwist; + feetSpacing = desc.feetSpacing; + hasTranslationDoF = desc.hasTranslationDoF; + + foreach (var x in desc.human) + { + var key = x.humanBone.FromHumanBodyBone(); + var found = humanBones.FirstOrDefault(y => y.vrmBone == key); + if (found == null) + { + found = new glTF_VRM_HumanoidBone + { + vrmBone = key + }; + humanBones.Add(found); + } + found.node = nodes.FindIndex(y => y.name == x.boneName); + + found.useDefaultValues = x.useDefaultValues; + found.axisLength = x.axisLength; + found.center = x.center; + found.max = x.max; + found.min = x.min; + } + } + + public UniHumanoid.AvatarDescription ToDescription(List nodes) + { + var description = ScriptableObject.CreateInstance(); + description.upperLegTwist = upperLegTwist; + description.lowerLegTwist = lowerLegTwist; + description.upperArmTwist = upperArmTwist; + description.lowerArmTwist = lowerArmTwist; + description.armStretch = armStretch; + description.legStretch = legStretch; + description.hasTranslationDoF = hasTranslationDoF; + description.human = humanBones.Select(x => new UniHumanoid.BoneLimit + { + boneName = nodes[x.node].name, + useDefaultValues = x.useDefaultValues, + axisLength = x.axisLength, + center = x.center, + min = x.min, + max = x.max, + humanBone = x.vrmBone.ToHumanBodyBone(), + }).ToArray(); + return description; + } + } +} diff --git a/Scripts/Format/glTF_VRM_Humanoid.cs.meta b/Scripts/Format/glTF_VRM_Humanoid.cs.meta new file mode 100644 index 000000000..5b4230832 --- /dev/null +++ b/Scripts/Format/glTF_VRM_Humanoid.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 3f9f79a650473ec46b54bf693bd745d2 +timeCreated: 1517549206 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/glTF_VRM_Material.cs b/Scripts/Format/glTF_VRM_Material.cs new file mode 100644 index 000000000..9825d54a1 --- /dev/null +++ b/Scripts/Format/glTF_VRM_Material.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UniGLTF; +using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + + +namespace VRM +{ + public class glTF_VRM_Material : UniGLTF.JsonSerializableBase + { + public string name; + public string shader; + public int renderQueue=-1; + + public Dictionary floatProperties = new Dictionary(); + public Dictionary vectorProperties = new Dictionary(); + public Dictionary textureProperties = new Dictionary(); + + public Dictionary keywordMap = new Dictionary(); + public Dictionary tagMap = new Dictionary(); + + static readonly string[] TAGS = new string[]{ + "RenderType", + // "Queue", + }; + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => name); + f.KeyValue(() => renderQueue); + f.KeyValue(() => shader); + { + f.Key("floatProperties"); f.BeginMap(); + foreach (var kv in floatProperties) + { + f.Key(kv.Key); f.Value(kv.Value); + } + f.EndMap(); + } + { + f.Key("vectorProperties"); f.BeginMap(); + foreach (var kv in vectorProperties) + { + f.Key(kv.Key); f.Value(kv.Value.ToArray()); + } + f.EndMap(); + } + { + f.Key("textureProperties"); f.BeginMap(); + foreach (var kv in textureProperties) + { + f.Key(kv.Key); f.Value(kv.Value); + } + f.EndMap(); + } + { + f.Key("keywordMap"); f.BeginMap(); + foreach(var kv in keywordMap) + { + f.Key(kv.Key); f.Value(kv.Value); + } + f.EndMap(); + } + { + f.Key("tagMap"); f.BeginMap(); + foreach (var kv in tagMap) + { + f.Key(kv.Key); f.Value(kv.Value); + } + f.EndMap(); + } + } + + public static List Parse(string src) + { + var json = src.ParseAsJson()["extensions"]["VRM"]["materialProperties"]; + var materials = json.DeserializeList(); + var jsonItems = json.ListItems.ToArray(); + for(int i=0; i x.Key, x => x.Value.GetSingle()); + materials[i].vectorProperties = + jsonItems[i]["vectorProperties"].ObjectItems.ToDictionary(x => x.Key, x => + { + return x.Value.ListItems.Select(y => y.GetSingle()).ToArray(); + }); + materials[i].keywordMap = + jsonItems[i]["keywordMap"].ObjectItems.ToDictionary(x => x.Key, x => x.Value.GetBoolean()); + materials[i].tagMap = + jsonItems[i]["tagMap"].ObjectItems.ToDictionary(x => x.Key, x => x.Value.GetString()); + materials[i].textureProperties = + jsonItems[i]["textureProperties"].ObjectItems.ToDictionary(x => x.Key, x => x.Value.GetInt32()); + } + return materials; + } + + public static glTF_VRM_Material CreateFromMaterial(Material m, List textures) + { + var material = new glTF_VRM_Material + { + name = m.name, + shader = m.shader.name, + renderQueue = m.renderQueue, + }; + +#if UNITY_EDITOR + for (int i = 0; i < ShaderUtil.GetPropertyCount(m.shader); ++i) + { + var name = ShaderUtil.GetPropertyName(m.shader, i); + var propType = ShaderUtil.GetPropertyType(m.shader, i); + switch (propType) + { + case ShaderUtil.ShaderPropertyType.Color: + { + var value = m.GetColor(name).ToArray(); + material.vectorProperties.Add(name, value); + } + break; + + case ShaderUtil.ShaderPropertyType.Range: + case ShaderUtil.ShaderPropertyType.Float: + { + var value = m.GetFloat(name); + material.floatProperties.Add(name, value); + } + break; + + case ShaderUtil.ShaderPropertyType.TexEnv: + { + var texture = m.GetTexture(name) as Texture2D; + if (texture != null) + { + var value = textures.IndexOf(texture); + if (value == -1) + { + Debug.LogFormat("not found {0}", texture.name); + } + else + { + material.textureProperties.Add(name, value); + } + } + } + break; + + case ShaderUtil.ShaderPropertyType.Vector: + { + var value = m.GetVector(name).ToArray(); + material.vectorProperties.Add(name, value); + } + break; + + default: + throw new NotImplementedException(); + } + } +#else + Debug.LogWarning("cannot export material properties on runtime"); +#endif + + foreach (var keyword in m.shaderKeywords) + { + material.keywordMap.Add(keyword, m.IsKeywordEnabled(keyword)); + } + + foreach(var tag in TAGS) + { + var value = m.GetTag(tag, false); + if (!String.IsNullOrEmpty(value)) + { + material.tagMap.Add(tag, value); + } + } + + return material; + } + } +} diff --git a/Scripts/Format/glTF_VRM_Material.cs.meta b/Scripts/Format/glTF_VRM_Material.cs.meta new file mode 100644 index 000000000..f333cb244 --- /dev/null +++ b/Scripts/Format/glTF_VRM_Material.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 130dbb872890027439584d752fe160ef +timeCreated: 1519805969 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/glTF_VRM_Meta.cs b/Scripts/Format/glTF_VRM_Meta.cs new file mode 100644 index 000000000..9fa746c6a --- /dev/null +++ b/Scripts/Format/glTF_VRM_Meta.cs @@ -0,0 +1,71 @@ +using System; +using UniGLTF; + + +namespace VRM +{ + public enum LicenseType + { + RedistributionProhibited, + + CC0, + CC_BY, + CC_BY_NC, + CC_BY_SA, + CC_BY_NC_SA, + CC_BY_ND, + CC_BY_NC_ND, + + Other + } + + public static class LicenseTypeExtensions + { + public static LicenseType ToLicenseType(this string src) + { + try + { + return (LicenseType)Enum.Parse(typeof(LicenseType), src, true); + } + catch (Exception) + { + return default(LicenseType); + } + } + } + + [Serializable] + public class glTF_VRM_Meta : JsonSerializableBase + { + public string author; + public string contactInformation; + public string licenseName; + public LicenseType licenseType + { + get + { + return licenseName.ToLicenseType(); + } + set + { + licenseName = value.ToString(); + } + } + public string otherLicenseUrl; + public string reference; + + public string title; + public int texture = -1; + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => author); + f.KeyValue(() => contactInformation); + f.KeyValue(() => licenseName); + f.KeyValue(() => otherLicenseUrl); + f.KeyValue(() => reference); + f.KeyValue(() => title); + f.KeyValue(() => texture); + } + } +} diff --git a/Scripts/Format/glTF_VRM_Meta.cs.meta b/Scripts/Format/glTF_VRM_Meta.cs.meta new file mode 100644 index 000000000..5a8af4841 --- /dev/null +++ b/Scripts/Format/glTF_VRM_Meta.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 06d4ab405dbbf9041b20a3b99f1cbe4f +timeCreated: 1520237793 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/glTF_VRM_SecondaryAnimation.cs b/Scripts/Format/glTF_VRM_SecondaryAnimation.cs new file mode 100644 index 000000000..7e8117b84 --- /dev/null +++ b/Scripts/Format/glTF_VRM_SecondaryAnimation.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using UniGLTF; +using UnityEngine; + + +namespace VRM +{ + [Serializable] + public class glTF_VRM_SecondaryAnimationCollider : JsonSerializableBase + { + public Vector3 offset; + public float radius; + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => offset); + f.KeyValue(() => radius); + } + } + + [Serializable] + public class glTF_VRM_SecondaryAnimationColliderGroup : JsonSerializableBase + { + public int node; + public List colliders = new List(); + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => node); + f.KeyValue(() => colliders); + } + } + + + [Serializable] + public class glTF_VRM_SecondaryAnimationGroup : JsonSerializableBase + { + public string comment; + public float stiffiness; + public float gravityPower; + public Vector3 gravityDir; + public float dragForce; + public int center; + public float hitRadius; + public int[] bones = new int[] { }; + public int[] colliderGroups = new int[] { }; + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => comment); + f.KeyValue(() => stiffiness); + f.KeyValue(() => gravityPower); + f.KeyValue(() => gravityDir); + f.KeyValue(() => dragForce); + f.KeyValue(() => center); + f.KeyValue(() => hitRadius); + f.KeyValue(() => bones); + f.KeyValue(() => colliderGroups); + } + } + + [Serializable] + public class glTF_VRM_SecondaryAnimation : JsonSerializableBase + { + public List boneGroups = new List(); + public List colliderGroups = new List(); + + protected override void SerializeMembers(JsonFormatter f) + { + f.KeyValue(() => boneGroups); + f.KeyValue(() => colliderGroups); + } + } +} diff --git a/Scripts/Format/glTF_VRM_SecondaryAnimation.cs.meta b/Scripts/Format/glTF_VRM_SecondaryAnimation.cs.meta new file mode 100644 index 000000000..34daa1cc8 --- /dev/null +++ b/Scripts/Format/glTF_VRM_SecondaryAnimation.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5fb9119ad9fa65849ad2379d4da417bd +timeCreated: 1519653096 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Humanoid.meta b/Scripts/Humanoid.meta new file mode 100644 index 000000000..30cc06e32 --- /dev/null +++ b/Scripts/Humanoid.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: dabe3b8d8da159f43a06701a61a69dbf +folderAsset: yes +timeCreated: 1520410756 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Humanoid/VRMHumanoidDescription.cs b/Scripts/Humanoid/VRMHumanoidDescription.cs new file mode 100644 index 000000000..515e93581 --- /dev/null +++ b/Scripts/Humanoid/VRMHumanoidDescription.cs @@ -0,0 +1,56 @@ +using UnityEngine; + + +namespace VRM +{ + public class VRMHumanoidDescription : MonoBehaviour + { + [SerializeField] + public Avatar Avatar; + + [SerializeField] + public UniHumanoid.AvatarDescription Description; + + public UniHumanoid.AvatarDescription GetDescription(out bool isCreated) + { + isCreated = false; + if (Description != null) + { + return Description; + } + +#if UNITY_EDITOR + if (Avatar != null) + { + isCreated = true; + return UniHumanoid.AvatarDescription.CreateFrom(Avatar); + } +#endif + + return null; + } + + private void OnValidate() + { + if(Avatar!=null && (!Avatar.isValid || !Avatar.isHuman)) + { + Avatar = null; + } + } + + void Reset() + { + var animator = GetComponent(); + if (animator == null) + { + return; + } + + Avatar = animator.avatar; + if (Avatar == null) + { + return; + } + } + } +} diff --git a/Scripts/Humanoid/VRMHumanoidDescription.cs.meta b/Scripts/Humanoid/VRMHumanoidDescription.cs.meta new file mode 100644 index 000000000..a9bf03673 --- /dev/null +++ b/Scripts/Humanoid/VRMHumanoidDescription.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3869812175467a143ab9cd865752b4a9 +timeCreated: 1520410765 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/LookAt.meta b/Scripts/LookAt.meta new file mode 100644 index 000000000..4ed543258 --- /dev/null +++ b/Scripts/LookAt.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: a7e29185fa574ef4eab4b030a279a64d +folderAsset: yes +timeCreated: 1518293103 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/LookAt/CurveMapper.cs b/Scripts/LookAt/CurveMapper.cs new file mode 100644 index 000000000..a3ea04107 --- /dev/null +++ b/Scripts/LookAt/CurveMapper.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + + +namespace VRM +{ + [Serializable] + public class CurveMapper + { + public AnimationCurve Curve = AnimationCurve.Linear(0, 0, 1.0f, 1.0f); + + [Range(20.0f, 90.0f)] + public float CurveXRangeDegree = 90.0f; + + [Range(0, 90.0f)] + public float CurveYRangeDegree = 10.0f; + + public void OnValidate() + { + if (CurveXRangeDegree == 0) + { + CurveXRangeDegree = 90.0f; + } + } + + public void Apply(glTF_VRM_DegreeMap degreeMap) + { + CurveXRangeDegree = degreeMap.xRange; + CurveYRangeDegree = degreeMap.yRange; + if (degreeMap.curve != null) + { + Curve = new AnimationCurve(ToKeys(degreeMap.curve).ToArray()); + } + else + { + Curve = AnimationCurve.Linear(0, 0, 1.0f, 1.0f); + } + } + + IEnumerable ToKeys(float[] values) + { + for (int i = 0; i < values.Length; i += 4) + { + yield return new Keyframe(values[i], values[i + 1], values[i + 2], values[i + 3]); + } + } + + public float Map(float src) + { + if (src < 0) + { + src = 0; + } + else if (src > CurveXRangeDegree) + { + src = CurveXRangeDegree; + } + return Curve.Evaluate(src / CurveXRangeDegree) * CurveYRangeDegree; + } + } +} diff --git a/Scripts/LookAt/CurveMapper.cs.meta b/Scripts/LookAt/CurveMapper.cs.meta new file mode 100644 index 000000000..7e0fc4de6 --- /dev/null +++ b/Scripts/LookAt/CurveMapper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: baf8dab7dcbbb03429b01dfa7e2f65cd +timeCreated: 1521805484 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/LookAt/Editor.meta b/Scripts/LookAt/Editor.meta new file mode 100644 index 000000000..30561916a --- /dev/null +++ b/Scripts/LookAt/Editor.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 458bc5bc1e011b247849b92ae7709de7 +folderAsset: yes +timeCreated: 1518293117 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/LookAt/Editor/VRMLookAtHeadEditor.cs b/Scripts/LookAt/Editor/VRMLookAtHeadEditor.cs new file mode 100644 index 000000000..670965201 --- /dev/null +++ b/Scripts/LookAt/Editor/VRMLookAtHeadEditor.cs @@ -0,0 +1,60 @@ +using UnityEditor; +using UnityEngine; + + +namespace VRM +{ + [CustomEditor(typeof(VRMLookAtHead))] + public class VRMLookAtHeadEditor : Editor + { + VRMLookAtHead m_target; + + void OnEnable() + { + m_target = (VRMLookAtHead)target; + } + + const float RADIUS = 0.5f; + + void OnSceneGUI() + { + if (!Application.isPlaying) return; + if (!m_target.DrawGizmo) return; + if (m_target.Target == null) return; + if (m_target.Head.Transform == null) return; + + { + EditorGUI.BeginChangeCheck(); + var newTargetPosition = Handles.PositionHandle(m_target.Target.position, Quaternion.identity); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(m_target.Target, "Change Look At Target Position"); + m_target.Target.position = newTargetPosition; + } + } + + Handles.color = new Color(1, 1, 1, 0.6f); + Handles.DrawDottedLine(m_target.Head.Transform.position, m_target.Target.position, 4.0f); + + Handles.matrix = m_target.Head.InitialWorldMatrix; + Handles.Label(Vector3.zero, string.Format("Yaw: {0:0.}degree\nPitch: {1:0.}degree", + m_target.Yaw, + m_target.Pitch)); + + Handles.color = new Color(0, 1, 0, 0.2f); + Handles.DrawSolidArc(Vector3.zero, + m_target.Head.OffsetRotation.GetColumn(1), + m_target.Head.OffsetRotation.GetColumn(2), + m_target.Yaw, + RADIUS); + + Handles.matrix = m_target.Head.InitialWorldMatrix * m_target.YawMatrix; + Handles.color = new Color(1, 0, 0, 0.2f); + Handles.DrawSolidArc(Vector3.zero, + m_target.Head.OffsetRotation.GetColumn(0), + m_target.Head.OffsetRotation.GetColumn(2), + -m_target.Pitch, + RADIUS); + } + } +} diff --git a/Scripts/LookAt/Editor/VRMLookAtHeadEditor.cs.meta b/Scripts/LookAt/Editor/VRMLookAtHeadEditor.cs.meta new file mode 100644 index 000000000..637bbdaee --- /dev/null +++ b/Scripts/LookAt/Editor/VRMLookAtHeadEditor.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 6c4b1a599166c48488a860a0017c884a +timeCreated: 1518293126 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/LookAt/LookTarget.cs b/Scripts/LookAt/LookTarget.cs new file mode 100644 index 000000000..5ed4d3091 --- /dev/null +++ b/Scripts/LookAt/LookTarget.cs @@ -0,0 +1,36 @@ +using UnityEngine; +using UniGLTF; + + +namespace VRM +{ + public class LookTarget : MonoBehaviour + { + [SerializeField] + public Transform Target; + + [SerializeField] + Vector3 m_offset = new Vector3(0, 0.05f, 0); + + [SerializeField, Range(0, 3.0f)] + float m_distance = 0.7f; + + public OffsetOnTransform m_offsetTransform; + + void Update() + { + if (Target != m_offsetTransform.Transform) + { + m_offsetTransform = OffsetOnTransform.Create(Target); + } + + var target = m_offsetTransform.Transform; + if (target != null) + { + var targetPosition = target.position + m_offset; + transform.position = targetPosition + (m_offsetTransform.WorldMatrix.ExtractRotation() * Vector3.forward) * m_distance; + transform.LookAt(targetPosition); + } + } + } +} diff --git a/Scripts/LookAt/LookTarget.cs.meta b/Scripts/LookAt/LookTarget.cs.meta new file mode 100644 index 000000000..3c40d1c12 --- /dev/null +++ b/Scripts/LookAt/LookTarget.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d1cc319f70f55264eb38d1959c4222c6 +timeCreated: 1519912723 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/LookAt/Matrix4x4Extensions.cs b/Scripts/LookAt/Matrix4x4Extensions.cs new file mode 100644 index 000000000..d7eeeac25 --- /dev/null +++ b/Scripts/LookAt/Matrix4x4Extensions.cs @@ -0,0 +1,38 @@ +using System; +using UniGLTF; +using UnityEngine; + + +namespace VRM +{ + public static class Matrix4x4Extensions + { + public static void CalcYawPitch(this Matrix4x4 m, Vector3 target, out float yaw, out float pitch) + { + var zaxis = Vector3.Project(target, m.GetColumn(2)); + var yaxis = Vector3.Project(target, m.GetColumn(1)); + var xaxis = Vector3.Project(target, m.GetColumn(0)); + + var yawPlusMinus = Vector3.Dot(xaxis, m.GetColumn(0)) > 0 ? 1.0f : -1.0f; + yaw = (float)Math.Atan2(xaxis.magnitude, zaxis.magnitude) * yawPlusMinus * Mathf.Rad2Deg; + + var pitchPlusMinus = Vector3.Dot(yaxis, m.GetColumn(1)) > 0 ? 1.0f : -1.0f; + pitch = (float)Math.Atan2(yaxis.magnitude, (xaxis + zaxis).magnitude) * pitchPlusMinus * Mathf.Rad2Deg; + } + + public static Quaternion YawPitchRotation(this Matrix4x4 m, float yaw, float pitch) + { + return Quaternion.AngleAxis(yaw, m.GetColumn(1)) * Quaternion.AngleAxis(-pitch, m.GetColumn(0)); + } + + public static Matrix4x4 RotationToWorldAxis(this Matrix4x4 m) + { + return UnityExtensions.Matrix4x4FromColumns( + m.MultiplyVector(Vector3.right), + m.MultiplyVector(Vector3.up), + m.MultiplyVector(Vector3.forward), + new Vector4(0, 0, 0, 1) + ); + } + } +} diff --git a/Scripts/LookAt/Matrix4x4Extensions.cs.meta b/Scripts/LookAt/Matrix4x4Extensions.cs.meta new file mode 100644 index 000000000..85d92bc0e --- /dev/null +++ b/Scripts/LookAt/Matrix4x4Extensions.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: ab9df13cea6667a4bbf488fc297bd014 +timeCreated: 1518347175 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/LookAt/OffsetOnTransform.cs b/Scripts/LookAt/OffsetOnTransform.cs new file mode 100644 index 000000000..f20519542 --- /dev/null +++ b/Scripts/LookAt/OffsetOnTransform.cs @@ -0,0 +1,52 @@ +using System; +using UnityEngine; + + +namespace VRM +{ + [Serializable] + public struct OffsetOnTransform + { + public Transform Transform; + public Matrix4x4 OffsetRotation; + + public Matrix4x4 WorldMatrix + { + get + { + if (Transform == null) return Matrix4x4.identity; + return Transform.localToWorldMatrix * OffsetRotation; + } + } + + Matrix4x4 m_initialLocalMatrix; + public void Setup() + { + if (Transform == null) return; + m_initialLocalMatrix = Transform.parent.worldToLocalMatrix * Transform.localToWorldMatrix; + } + + public Matrix4x4 InitialWorldMatrix + { + get + { + return Transform.parent.localToWorldMatrix * m_initialLocalMatrix; + } + } + + public static OffsetOnTransform Create(Transform transform) + { + var coordinate = new OffsetOnTransform + { + Transform = transform + }; + + if (transform != null) + { + coordinate.OffsetRotation = transform.worldToLocalMatrix.RotationToWorldAxis(); + } + + return coordinate; + } + } +} diff --git a/Scripts/LookAt/OffsetOnTransform.cs.meta b/Scripts/LookAt/OffsetOnTransform.cs.meta new file mode 100644 index 000000000..3a8c67c2e --- /dev/null +++ b/Scripts/LookAt/OffsetOnTransform.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: e8e294185b0b06148a057dc3a21cc55f +timeCreated: 1518347841 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/LookAt/VRMLookAt.cs b/Scripts/LookAt/VRMLookAt.cs new file mode 100644 index 000000000..79cf6b6fa --- /dev/null +++ b/Scripts/LookAt/VRMLookAt.cs @@ -0,0 +1,252 @@ +#pragma warning disable 0414, 0649 +using System; +using System.Linq; +using System.Collections.Generic; +using UniGLTF; +using UnityEngine; + + +namespace VRM +{ + public class VRMLookAt : MonoBehaviour + { + public bool DrawGizmo = true; + + [SerializeField] + public bool UseUpdate = true; + + [SerializeField] + public Transform Target; + + [SerializeField] + public OffsetOnTransform LeftEye; + + [SerializeField] + public OffsetOnTransform RightEye; + + [SerializeField] + public OffsetOnTransform Head; + + [SerializeField, Header("Degree Mapping")] + public CurveMapper HorizontalOuter = new CurveMapper(); + + [SerializeField] + public CurveMapper HorizontalInner = new CurveMapper(); + + [SerializeField] + public CurveMapper VerticalDown = new CurveMapper(); + + [SerializeField] + public CurveMapper VerticalUp = new CurveMapper(); + + public Texture2D CreateThumbnail() + { + var texture = new Texture2D(2048, 2048); + { + var go = new GameObject("ThumbCamera"); + var camera = go.AddComponent(); + CreateThumbnail(camera, texture); + if (Application.isPlaying) { GameObject.Destroy(go); } else { GameObject.DestroyImmediate(go); } + } + return texture; + } + void CreateThumbnail(Camera camera, Texture2D dst) + { + RenderTexture currentRT = RenderTexture.active; + { + var renderTexture = new RenderTexture(dst.width, dst.height, 24); + camera.targetTexture = renderTexture; + RenderTexture.active = renderTexture; + LookFace(camera.transform); + camera.Render(); + dst.ReadPixels(new Rect(0, 0, dst.width, dst.height), 0, 0); + + RenderTexture.active = currentRT; + camera.targetTexture = null; + if (Application.isPlaying) + { + UnityEngine.Object.Destroy(renderTexture); + } + else + { + UnityEngine.Object.DestroyImmediate(renderTexture); + } + } + } + + public void LookFace(Transform t) + { + if (Head.Transform == null) return; + var head = Head.Transform; + var headPosition = head.position + new Vector3(0, 0.05f, 0); + t.position = headPosition + Head.WorldMatrix.ExtractRotation() * new Vector3(0, 0, 0.7f); + t.LookAt(headPosition); + } + + public void CopyTo(GameObject _dst, Dictionary map) + { + var dst = _dst.AddComponent(); + dst.Target = Target; + dst.Head = OffsetOnTransform.Create(map[Head.Transform]); + dst.RightEye = OffsetOnTransform.Create(map[RightEye.Transform]); + dst.LeftEye = OffsetOnTransform.Create(map[LeftEye.Transform]); + + dst.HorizontalOuter = HorizontalOuter; + dst.HorizontalInner = HorizontalInner; + dst.VerticalDown = VerticalDown; + dst.VerticalUp = VerticalUp; + } + + private void Reset() + { + Target = Camera.main.transform; + + GetBones(); + } + + private void OnValidate() + { + HorizontalInner.OnValidate(); + HorizontalOuter.OnValidate(); + VerticalUp.OnValidate(); + VerticalDown.OnValidate(); + } + + public void GetBones() + { + var animator = GetComponent(); + if (animator != null) + { + LeftEye = OffsetOnTransform.Create(animator.GetBoneTransform(HumanBodyBones.LeftEye)); + RightEye = OffsetOnTransform.Create(animator.GetBoneTransform(HumanBodyBones.RightEye)); + Head = OffsetOnTransform.Create(animator.GetBoneTransform(HumanBodyBones.Head)); + } + } + + private void Awake() + { + Head.Setup(); + LeftEye.Setup(); + RightEye.Setup(); + } + + #region Gizmo + static void DrawMatrix(Matrix4x4 m, float size) + { + Gizmos.matrix = m; + Gizmos.color = Color.red; + Gizmos.DrawLine(Vector3.zero, Vector3.right * size); + Gizmos.color = Color.green; + Gizmos.DrawLine(Vector3.zero, Vector3.up * size); + Gizmos.color = Color.blue; + Gizmos.DrawLine(Vector3.zero, Vector3.forward * size); + } + + const float SIZE = 0.5f; + + private void OnDrawGizmos() + { + if (!DrawGizmo) return; + + if (LeftEye.Transform != null & RightEye.Transform != null) + { + DrawMatrix(LeftEye.WorldMatrix, SIZE); + DrawMatrix(RightEye.WorldMatrix, SIZE); + + } + else + { + DrawMatrix(Head.WorldMatrix, SIZE); + } + } + #endregion + + static Matrix4x4 LookAtMatrixFromWorld(Vector3 from, Vector3 target) + { + var pos = new Vector4(from.x, from.y, from.z, 1); + return LookAtMatrix(UnityExtensions.Matrix4x4FromColumns(Vector3.right, Vector3.up, Vector3.forward, pos), target); + } + + static Matrix4x4 LookAtMatrix(Vector3 up_vector, Vector3 localPosition) + { + var z_axis = localPosition.normalized; + var x_axis = Vector3.Cross(up_vector, z_axis).normalized; + var y_axis = Vector3.Cross(z_axis, x_axis).normalized; + return UnityExtensions.Matrix4x4FromColumns(x_axis, y_axis, z_axis, new Vector4(0, 0, 0, 1)); + } + + static Matrix4x4 LookAtMatrix(Matrix4x4 m, Vector3 target) + { + return LookAtMatrix(Vector3.up, m.inverse.MultiplyPoint(target)); + } + + public Matrix4x4 YawMatrix + { + get + { + var yaw = Quaternion.AngleAxis(Yaw, Head.OffsetRotation.GetColumn(1)); + var m = default(Matrix4x4); + m.SetTRS(Vector3.zero, yaw, Vector3.one); + return m; + } + } + + [SerializeField, Header("Debug")] + public float Yaw; + public float Pitch; + private void LateUpdate() + { + if (!UseUpdate) return; + if (Target == null) return; + + LookWorldPosition(Target.position); + } + + public void LookWorldPosition(Vector3 targetPosition) + { + var localPosition = Head.InitialWorldMatrix.inverse.MultiplyPoint(targetPosition); + Head.OffsetRotation.CalcYawPitch(localPosition, out Yaw, out Pitch); + + ApplyRotations(Yaw, Pitch); + } + + void ApplyRotations(float yaw, float pitch) + { + // horizontal + float leftYaw, rightYaw; + if (yaw < 0) + { + leftYaw = -HorizontalOuter.Map(-yaw); + rightYaw = -HorizontalInner.Map(-yaw); + } + else + { + rightYaw = HorizontalOuter.Map(yaw); + leftYaw = HorizontalInner.Map(yaw); + } + + // vertical + if (pitch < 0) + { + pitch = -VerticalDown.Map(-pitch); + } + else + { + pitch = VerticalUp.Map(pitch); + } + + // Apply + if (LeftEye.Transform != null && RightEye.Transform != null) + { + // 目に値を適用する + LeftEye.Transform.rotation = LeftEye.InitialWorldMatrix.ExtractRotation() * Head.OffsetRotation.YawPitchRotation(leftYaw, pitch); + RightEye.Transform.rotation = RightEye.InitialWorldMatrix.ExtractRotation() * Head.OffsetRotation.YawPitchRotation(rightYaw, pitch); + } + else if (Head.Transform != null) + { + // 頭に値を適用する + Head.Transform.rotation = Head.InitialWorldMatrix.ExtractRotation() * Head.OffsetRotation.YawPitchRotation(yaw, pitch); + } + } + } +} diff --git a/Scripts/LookAt/VRMLookAt.cs.meta b/Scripts/LookAt/VRMLookAt.cs.meta new file mode 100644 index 000000000..132208d6d --- /dev/null +++ b/Scripts/LookAt/VRMLookAt.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 04a3e59a0190f1647892e3709c075845 +timeCreated: 1517991576 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/LookAt/VRMLookAtBlendShapeApplyer.cs b/Scripts/LookAt/VRMLookAtBlendShapeApplyer.cs new file mode 100644 index 000000000..f54b752a2 --- /dev/null +++ b/Scripts/LookAt/VRMLookAtBlendShapeApplyer.cs @@ -0,0 +1,74 @@ +#pragma warning disable 0414, 0649 +using UnityEngine; + + +namespace VRM +{ + public class VRMLookAtBlendShapeApplyer : MonoBehaviour + { + public bool DrawGizmo = true; + + [SerializeField] + float Range = 20.0f; + + private void Reset() + { + } + + private void OnValidate() + { + } + + VRMLookAtHead m_head; + VRMBlendShapeProxy m_propxy; + + private void Awake() + { + m_head = GetComponent(); + m_propxy = GetComponent(); + } + + private void OnEnable() + { + if (m_head == null) + { + enabled = false; + return; + } + m_head.YawPitchChanged += ApplyRotations; + } + + private void OnDisable() + { + m_head.YawPitchChanged -= ApplyRotations; + } + + void ApplyRotations(float yaw, float pitch) + { + if (yaw < 0) + { + // Left + m_propxy.SetValue(BlendShapePreset.LookLeft, -yaw / Range); + m_propxy.SetValue(BlendShapePreset.LookRight, 0); + } + else{ + // Right + m_propxy.SetValue(BlendShapePreset.LookLeft, 0); + m_propxy.SetValue(BlendShapePreset.LookRight, yaw / Range); + } + + if (pitch < 0) + { + // Up + m_propxy.SetValue(BlendShapePreset.LookUp, -pitch / Range); + m_propxy.SetValue(BlendShapePreset.LookDown, 0); + } + else + { + // Down + m_propxy.SetValue(BlendShapePreset.LookUp, 0); + m_propxy.SetValue(BlendShapePreset.LookDown, pitch / Range); + } + } + } +} diff --git a/Scripts/LookAt/VRMLookAtBlendShapeApplyer.cs.meta b/Scripts/LookAt/VRMLookAtBlendShapeApplyer.cs.meta new file mode 100644 index 000000000..eff87cae3 --- /dev/null +++ b/Scripts/LookAt/VRMLookAtBlendShapeApplyer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 845471fb50db3cd4aa2f7a3fae3cc3a4 +timeCreated: 1517991576 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/LookAt/VRMLookAtBoneApplyer.cs b/Scripts/LookAt/VRMLookAtBoneApplyer.cs new file mode 100644 index 000000000..c5b3db730 --- /dev/null +++ b/Scripts/LookAt/VRMLookAtBoneApplyer.cs @@ -0,0 +1,133 @@ +#pragma warning disable 0414, 0649 +using UniGLTF; +using UnityEngine; + + +namespace VRM +{ + public class VRMLookAtBoneApplyer : MonoBehaviour + { + public bool DrawGizmo = true; + + [SerializeField] + public OffsetOnTransform LeftEye; + + [SerializeField] + public OffsetOnTransform RightEye; + + [SerializeField, Header("Degree Mapping")] + public CurveMapper HorizontalOuter = new CurveMapper(); + + [SerializeField] + public CurveMapper HorizontalInner = new CurveMapper(); + + [SerializeField] + public CurveMapper VerticalDown = new CurveMapper(); + + [SerializeField] + public CurveMapper VerticalUp = new CurveMapper(); + + private void Reset() + { + var animator = GetComponent(); + if (animator != null) + { + LeftEye = OffsetOnTransform.Create(animator.GetBoneTransform(HumanBodyBones.LeftEye)); + RightEye = OffsetOnTransform.Create(animator.GetBoneTransform(HumanBodyBones.RightEye)); + } + } + + private void OnValidate() + { + HorizontalInner.OnValidate(); + HorizontalOuter.OnValidate(); + VerticalUp.OnValidate(); + VerticalDown.OnValidate(); + } + + VRMLookAtHead m_head; + + private void Awake() + { + m_head = GetComponent(); + LeftEye.Setup(); + RightEye.Setup(); + } + + private void OnEnable() + { + if (m_head == null) + { + enabled = false; + return; + } + m_head.YawPitchChanged += ApplyRotations; + } + + private void OnDisable() + { + m_head.YawPitchChanged -= ApplyRotations; + } + + #region Gizmo + static void DrawMatrix(Matrix4x4 m, float size) + { + Gizmos.matrix = m; + Gizmos.color = Color.red; + Gizmos.DrawLine(Vector3.zero, Vector3.right * size); + Gizmos.color = Color.green; + Gizmos.DrawLine(Vector3.zero, Vector3.up * size); + Gizmos.color = Color.blue; + Gizmos.DrawLine(Vector3.zero, Vector3.forward * size); + } + + const float SIZE = 0.5f; + + private void OnDrawGizmos() + { + if (DrawGizmo) + { + if (LeftEye.Transform != null & RightEye.Transform != null) + { + DrawMatrix(LeftEye.WorldMatrix, SIZE); + DrawMatrix(RightEye.WorldMatrix, SIZE); + } + } + } + #endregion + + void ApplyRotations(float yaw, float pitch) + { + // horizontal + float leftYaw, rightYaw; + if (yaw < 0) + { + leftYaw = -HorizontalOuter.Map(-yaw); + rightYaw = -HorizontalInner.Map(-yaw); + } + else + { + rightYaw = HorizontalOuter.Map(yaw); + leftYaw = HorizontalInner.Map(yaw); + } + + // vertical + if (pitch < 0) + { + pitch = -VerticalDown.Map(-pitch); + } + else + { + pitch = VerticalUp.Map(pitch); + } + + // Apply + if (LeftEye.Transform != null && RightEye.Transform != null) + { + // 目に値を適用する + LeftEye.Transform.rotation = LeftEye.InitialWorldMatrix.ExtractRotation() * m_head.Head.OffsetRotation.YawPitchRotation(leftYaw, pitch); + RightEye.Transform.rotation = RightEye.InitialWorldMatrix.ExtractRotation() * m_head.Head.OffsetRotation.YawPitchRotation(rightYaw, pitch); + } + } + } +} diff --git a/Scripts/LookAt/VRMLookAtBoneApplyer.cs.meta b/Scripts/LookAt/VRMLookAtBoneApplyer.cs.meta new file mode 100644 index 000000000..4b6f66243 --- /dev/null +++ b/Scripts/LookAt/VRMLookAtBoneApplyer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: a8b72334adf6f7948bd98b4f0a873949 +timeCreated: 1517991576 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/LookAt/VRMLookAtHead.cs b/Scripts/LookAt/VRMLookAtHead.cs new file mode 100644 index 000000000..40277b2c4 --- /dev/null +++ b/Scripts/LookAt/VRMLookAtHead.cs @@ -0,0 +1,161 @@ +#pragma warning disable 0414, 0649 +using System; +using UniGLTF; +using UnityEngine; + + +namespace VRM +{ + public class VRMLookAtHead : MonoBehaviour + { + public bool DrawGizmo = true; + + [SerializeField] + public bool UseUpdate = true; + + [SerializeField] + public Transform Target; + + [SerializeField] + public OffsetOnTransform Head; + + #region Thumbnail + public Texture2D CreateThumbnail() + { + var texture = new Texture2D(2048, 2048); + { + var go = new GameObject("ThumbCamera"); + var camera = go.AddComponent(); + CreateThumbnail(camera, texture); + if (Application.isPlaying) { GameObject.Destroy(go); } else { GameObject.DestroyImmediate(go); } + } + return texture; + } + void CreateThumbnail(Camera camera, Texture2D dst) + { + RenderTexture currentRT = RenderTexture.active; + { + var renderTexture = new RenderTexture(dst.width, dst.height, 24); + camera.targetTexture = renderTexture; + RenderTexture.active = renderTexture; + LookFace(camera.transform); + camera.Render(); + dst.ReadPixels(new Rect(0, 0, dst.width, dst.height), 0, 0); + + RenderTexture.active = currentRT; + camera.targetTexture = null; + if (Application.isPlaying) + { + UnityEngine.Object.Destroy(renderTexture); + } + else + { + UnityEngine.Object.DestroyImmediate(renderTexture); + } + } + } + + public void LookFace(Transform t) + { + if (Head.Transform == null) return; + var head = Head.Transform; + var headPosition = head.position + new Vector3(0, 0.05f, 0); + t.position = headPosition + Head.WorldMatrix.ExtractRotation() * new Vector3(0, 0, 0.7f); + t.LookAt(headPosition); + } + #endregion + + private void Reset() + { + Target = Camera.main.transform; + + var animator = GetComponent(); + if (animator != null) + { + Head = OffsetOnTransform.Create(animator.GetBoneTransform(HumanBodyBones.Head)); + } + } + + private void Awake() + { + Head.Setup(); + } + + static Matrix4x4 LookAtMatrixFromWorld(Vector3 from, Vector3 target) + { + var pos = new Vector4(from.x, from.y, from.z, 1); + return LookAtMatrix(UnityExtensions.Matrix4x4FromColumns(Vector3.right, Vector3.up, Vector3.forward, pos), target); + } + + static Matrix4x4 LookAtMatrix(Vector3 up_vector, Vector3 localPosition) + { + var z_axis = localPosition.normalized; + var x_axis = Vector3.Cross(up_vector, z_axis).normalized; + var y_axis = Vector3.Cross(z_axis, x_axis).normalized; + return UnityExtensions.Matrix4x4FromColumns(x_axis, y_axis, z_axis, new Vector4(0, 0, 0, 1)); + } + + static Matrix4x4 LookAtMatrix(Matrix4x4 m, Vector3 target) + { + return LookAtMatrix(Vector3.up, m.inverse.MultiplyPoint(target)); + } + + public Matrix4x4 YawMatrix + { + get + { + var yaw = Quaternion.AngleAxis(m_yaw, Head.OffsetRotation.GetColumn(1)); + var m = default(Matrix4x4); + m.SetTRS(Vector3.zero, yaw, Vector3.one); + return m; + } + } + + [SerializeField, Header("Debug")] + float m_yaw; + public float Yaw + { + get { return m_yaw; } + } + + [SerializeField] + float m_pitch; + public float Pitch + { + get { return m_pitch; } + } + + public event Action YawPitchChanged; + void RaiseYawPitchChanged(float yaw, float pitch) + { + if (m_yaw == yaw && m_pitch == pitch) return; + m_yaw = yaw; + m_pitch = pitch; + var handle = YawPitchChanged; + if (handle != null) + { + handle(yaw, pitch); + } + } + private void Update() + { + if (!UseUpdate) return; + if (Target == null) return; + LookWorldPosition(); + } + + public void LookWorldPosition() + { + float yaw; + float pitch; + LookWorldPosition(Target.position, out yaw, out pitch); + } + + public void LookWorldPosition(Vector3 targetPosition, out float yaw, out float pitch) + { + var localPosition = Head.InitialWorldMatrix.inverse.MultiplyPoint(targetPosition); + Head.OffsetRotation.CalcYawPitch(localPosition, out yaw, out pitch); + RaiseYawPitchChanged(yaw, pitch); + } + } +} diff --git a/Scripts/LookAt/VRMLookAtHead.cs.meta b/Scripts/LookAt/VRMLookAtHead.cs.meta new file mode 100644 index 000000000..feb7b0470 --- /dev/null +++ b/Scripts/LookAt/VRMLookAtHead.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: e0a1a470564f16f4f94acb4b9ef56367 +timeCreated: 1517991576 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Meta.meta b/Scripts/Meta.meta new file mode 100644 index 000000000..435574026 --- /dev/null +++ b/Scripts/Meta.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1f4af4e58b683c14e93f70773938e78f +folderAsset: yes +timeCreated: 1520239983 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Meta/VRMMetaInformation.cs b/Scripts/Meta/VRMMetaInformation.cs new file mode 100644 index 000000000..b0f634947 --- /dev/null +++ b/Scripts/Meta/VRMMetaInformation.cs @@ -0,0 +1,106 @@ +using System; +using System.IO; +using UnityEngine; +using UniGLTF; + + +namespace VRM +{ + [Serializable] + [DisallowMultipleComponent] + public class VRMMetaInformation : MonoBehaviour, IEquatable + { + #region Info + [SerializeField, Header("Information")] + public string Title; + + [SerializeField] + public string Author; + + [SerializeField] + public string ContactInformation; + + [SerializeField] + public Texture2D Thumbnail; + + [SerializeField] + public string Reference; + #endregion + + #region License + [SerializeField, Header("License")] + public LicenseType LicenseType; + + [SerializeField] + public string OtherLicenseUrl; + #endregion + + public bool Equals(VRMMetaInformation other) + { + return + Author == other.Author + && Title == other.Title + && UniGLTF.MonoBehaviourComparator.AssetAreEquals(Thumbnail, other.Thumbnail) + ; + } + + private void Reset() + { + Title = name; + } + +#if UNITY_EDITOR + [ContextMenu("CreateThumbnail")] + void CreateThumbnailMenu() + { + var lookAt = GetComponent(); + if (lookAt != null) + { + var texture = lookAt.CreateThumbnail(); + +#if false + var assetPath = string.Format("Assets/{0}.thumbnail.asset", name); + assetPath = UnityEditor.AssetDatabase.GenerateUniqueAssetPath(assetPath); + UnityEditor.AssetDatabase.CreateAsset(texture, assetPath); +#else + var assetPath = string.Format("Assets/{0}.thumbnail.jpg", name); + assetPath = UnityEditor.AssetDatabase.GenerateUniqueAssetPath(assetPath); + File.WriteAllBytes(assetPath.AssetPathToFullPath(), texture.EncodeToJPG()); + + if (Application.isPlaying) + { + UnityEngine.Object.Destroy(texture); + } + else + { + UnityEngine.Object.DestroyImmediate(texture); + } + + UnityEditor.AssetDatabase.ImportAsset(assetPath); + Thumbnail = UnityEditor.AssetDatabase.LoadAssetAtPath(assetPath); +#endif + } + } +#endif + + public void CopyTo(GameObject _dst) + { + var dst = _dst.AddComponent(); + dst.Title = Title; + dst.Author = Author; + dst.Thumbnail = Thumbnail; + } + + public void OnValidate() + { + if (Thumbnail != null) + { + if (Thumbnail.width != 2048 || Thumbnail.height != 2048) + { + Thumbnail = null; + Debug.LogError("Thumbnail must 2048 x 2048"); + } + } + } + } +} diff --git a/Scripts/Meta/VRMMetaInformation.cs.meta b/Scripts/Meta/VRMMetaInformation.cs.meta new file mode 100644 index 000000000..6cc9fc5e3 --- /dev/null +++ b/Scripts/Meta/VRMMetaInformation.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8ea874a3d9d53e54a86ff1724ede087f +timeCreated: 1520239812 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/RuntimeLoader.meta b/Scripts/RuntimeLoader.meta new file mode 100644 index 000000000..f46152772 --- /dev/null +++ b/Scripts/RuntimeLoader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a0029457c7d957543a48dc39a63380a4 +folderAsset: yes +timeCreated: 1520835758 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/RuntimeLoader/CanvasManager.cs b/Scripts/RuntimeLoader/CanvasManager.cs new file mode 100644 index 000000000..bc0424b84 --- /dev/null +++ b/Scripts/RuntimeLoader/CanvasManager.cs @@ -0,0 +1,22 @@ +using System.Linq; +using UnityEngine; +using UnityEngine.UI; + + +namespace VRM +{ + public class CanvasManager : MonoBehaviour + { + [SerializeField] + public Button LoadVRMButton; + + [SerializeField] + public Button LoadBVHButton; + + private void Reset() + { + LoadVRMButton = GameObject.FindObjectsOfType