diff --git a/.travis.yml b/.travis.yml index 2b4b2855d..334315f8b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,19 +5,18 @@ install: - sudo python2 ./scripts/install-unity.py --package Unity 2017.1.1f1 before_script: - sudo chmod -R a+rwx /Applications/Unity -- sudo chmod +x ./scripts/export-upm-package.sh script: - msbuild ./GLTFSerialization/GLTFSerialization.sln /t:GLTFSerialization /p:TargetFramework=net35 -- "./scripts/export-upm-package.sh" - "./scripts/export-unity-package.sh" deploy: provider: releases file: - "./current-package/UnityGLTF.unitypackage" - - "./current-package/org.khronos.UnityGLTF.zip" skip_cleanup: true on: repo: KhronosGroup/UnityGLTF + branch: releases tags: true api-key: secure: "KBs5cOzqEoTDzsBv6AurzlFMtgfctKbJWsGorUW9BE/+B8pnriGQxc1Lt83kzkvHkcF+MgqD5M1KK6SebB/lgpE2Xo/Zu/al1Sr0M6MNijRgHCx0aqea+/mjXfHS7qhbOqgEqQHYoR4kOqIKFhJZOohtLBylnDgFojG42Z2UFnbSelZaAT8qISxndX5qjIqV9+CgkRlpwyY4tnQ2fzVwuyFMvEqSBUzAegzPa+nQu1HgJzx64OP0ONmoTPJnUr0C741GtsD1fA6SMjSpwhjiYezQXapN2a/YoZufEkrd5wYq8Q1UVNMDmkmtg1zA0LkmK1u6dEhE7VCjxL7CW13FWGWEMKR9h2afTl+QkRIZxNRxjVHcWG122oTSCOXaAwBtNHMnWEgBy+DYFWAYD/bMmZ+g70EZ2/bFEfPprhyOvK59No5V65FOyoIMSBZvgU1z2Kl3PPTUl/0vEljX3RiON6BvIbOxU7OdR+OI35naSfos76YWK58+b99fRC0rJq6egwhNTACPItrtdmZq13k/5PWfGSJ0IAegdoXCB1eFP6SqcoXDsxLJph8/nHrEHqyjtl9PYBturvzVfQThTzL4FQuB7Fypwql/PXB7mdG7HkOvcM5jJWiupIsQxw5VkArZhnBk188ds+UC42tUhF701ZrPJz6GF0Kqem7/Fr/6l7A=" + diff --git a/UnityGLTF/Assets/Main.unity b/UnityGLTF/Assets/Main.unity new file mode 100644 index 000000000..711c40193 --- /dev/null +++ b/UnityGLTF/Assets/Main.unity @@ -0,0 +1,546 @@ +%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.45030367, g: 0.49799693, b: 0.56280375, a: 1} +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + 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: 9 + 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: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringMode: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ShowResolutionOverlay: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !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 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1001 &10002063 +Prefab: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 4000011406631220, guid: 5255039e40b37b14fbcc0b72a30fc62e, type: 2} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4000011406631220, guid: 5255039e40b37b14fbcc0b72a30fc62e, type: 2} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4000011406631220, guid: 5255039e40b37b14fbcc0b72a30fc62e, type: 2} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4000011406631220, guid: 5255039e40b37b14fbcc0b72a30fc62e, type: 2} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4000011406631220, guid: 5255039e40b37b14fbcc0b72a30fc62e, type: 2} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4000011406631220, guid: 5255039e40b37b14fbcc0b72a30fc62e, type: 2} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 4000011406631220, guid: 5255039e40b37b14fbcc0b72a30fc62e, type: 2} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4000011406631220, guid: 5255039e40b37b14fbcc0b72a30fc62e, type: 2} + propertyPath: m_RootOrder + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 114000010638385648, guid: 5255039e40b37b14fbcc0b72a30fc62e, + type: 2} + propertyPath: Url + value: http://localhost:8080/glTF-Sample-Models/2.0/AnimatedCube/glTF/AnimatedCube.gltf + objectReference: {fileID: 0} + - target: {fileID: 114000010638385648, guid: 5255039e40b37b14fbcc0b72a30fc62e, + type: 2} + propertyPath: GLTFStandard + value: + objectReference: {fileID: 4800000, guid: a5732b1b5b2e36d47a3da75e187eba06, type: 3} + - target: {fileID: 114000010638385648, guid: 5255039e40b37b14fbcc0b72a30fc62e, + type: 2} + propertyPath: Multithreaded + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 114000010638385648, guid: 5255039e40b37b14fbcc0b72a30fc62e, + type: 2} + propertyPath: GLTFUri + value: + objectReference: {fileID: 0} + - target: {fileID: 4000011406631220, guid: 5255039e40b37b14fbcc0b72a30fc62e, type: 2} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4000011406631220, guid: 5255039e40b37b14fbcc0b72a30fc62e, type: 2} + propertyPath: m_LocalScale.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 4000011406631220, guid: 5255039e40b37b14fbcc0b72a30fc62e, type: 2} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 114000010638385648, guid: 5255039e40b37b14fbcc0b72a30fc62e, + type: 2} + propertyPath: loadOnStart + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 100100000, guid: 5255039e40b37b14fbcc0b72a30fc62e, type: 2} + m_IsPrefabParent: 0 +--- !u!4 &10002064 stripped +Transform: + m_PrefabParentObject: {fileID: 4000011406631220, guid: 5255039e40b37b14fbcc0b72a30fc62e, + type: 2} + m_PrefabInternal: {fileID: 10002063} +--- !u!114 &10002067 stripped +MonoBehaviour: + m_PrefabParentObject: {fileID: 114000010638385648, guid: 5255039e40b37b14fbcc0b72a30fc62e, + type: 2} + m_PrefabInternal: {fileID: 10002063} + m_Script: {fileID: 11500000, guid: 9087a95f22bcee64ebc45f6deec08714, type: 3} +--- !u!1 &328853373 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 100002, guid: 49a0e923d39ec3c4c8bb97699e2f2903, type: 2} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 328853379} + - component: {fileID: 328853378} + - component: {fileID: 328853376} + - component: {fileID: 328853375} + - component: {fileID: 328853374} + m_Layer: 0 + m_Name: Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &328853374 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 328853373} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 70ff706d2c89cc247a850af95597fcbb, type: 3} + m_Name: + m_EditorClassIdentifier: + target: {fileID: 10002064} + distance: 5 + xSpeed: 120 + ySpeed: 120 + zoomSpeed: 0.8 + yMinLimit: -80 + yMaxLimit: 80 + distanceMin: 0.05 + distanceMax: 500 +--- !u!81 &328853375 +AudioListener: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 8100000, guid: 49a0e923d39ec3c4c8bb97699e2f2903, + type: 2} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 328853373} + m_Enabled: 1 +--- !u!124 &328853376 +Behaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 12400000, guid: 49a0e923d39ec3c4c8bb97699e2f2903, + type: 2} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 328853373} + m_Enabled: 1 +--- !u!20 &328853378 +Camera: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 2000000, guid: 49a0e923d39ec3c4c8bb97699e2f2903, + type: 2} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 328853373} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.62552905, g: 0.684092, b: 0.7761194, a: 0.019607844} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.02 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 100 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &328853379 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 400002, guid: 49a0e923d39ec3c4c8bb97699e2f2903, type: 2} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 328853373} + m_LocalRotation: {x: -0, y: 1, z: -0, w: -0.000000063325004} + m_LocalPosition: {x: 0, y: 0, z: 2} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &979359784 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 979359786} + - component: {fileID: 979359785} + m_Layer: 0 + m_Name: Server + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &979359785 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 979359784} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 946dbe02f30bd734c901251fcc62a97a, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &979359786 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 979359784} + 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: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1013584300 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1013584302} + - component: {fileID: 1013584301} + m_Layer: 0 + m_Name: Model List + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1013584301 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1013584300} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: df99c459245b3cd40be06aca24a19170, type: 3} + m_Name: + m_EditorClassIdentifier: + loader: {fileID: 10002067} + pathRoot: http://localhost:8080/glTF-Sample-Models/2.0/ + manifestRelativePath: model-index.json + modelRelativePath: + loadThisFrame: 0 +--- !u!4 &1013584302 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1013584300} + 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 &1667736112 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1667736114} + - component: {fileID: 1667736113} + m_Layer: 0 + m_Name: Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1667736113 +Light: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1667736112} + m_Enabled: 1 + serializedVersion: 8 + m_Type: 1 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1.3 + m_Range: 10 + m_SpotAngle: 30 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + 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 &1667736114 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1667736112} + m_LocalRotation: {x: 0.048932634, y: 0.9485057, z: -0.18261904, w: 0.2541514} + m_LocalPosition: {x: 3.56, y: 5.64, z: 6.41} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 21.796001, y: 150, z: 0} +--- !u!1 &1904599574 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1904599578} + - component: {fileID: 1904599577} + - component: {fileID: 1904599576} + - component: {fileID: 1904599575} + m_Layer: 0 + m_Name: Floor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &1904599575 +MeshRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1904599574} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 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_StitchLightmapSeams: 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 &1904599576 +MeshCollider: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1904599574} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Convex: 0 + m_CookingOptions: 14 + m_SkinWidth: 0.01 + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &1904599577 +MeshFilter: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1904599574} + m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1904599578 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1904599574} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: -0.778, 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} diff --git a/UnityGLTF/Assets/Main.unity.meta b/UnityGLTF/Assets/Main.unity.meta new file mode 100644 index 000000000..8ab405a13 --- /dev/null +++ b/UnityGLTF/Assets/Main.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4b3020fb0b0588247a945afb3e2d8de7 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityGLTF/Assets/UnityGLTF/Examples/OrbitCameraController.cs b/UnityGLTF/Assets/UnityGLTF/Examples/OrbitCameraController.cs index 4fd81b667..a3d678389 100644 --- a/UnityGLTF/Assets/UnityGLTF/Examples/OrbitCameraController.cs +++ b/UnityGLTF/Assets/UnityGLTF/Examples/OrbitCameraController.cs @@ -3,31 +3,43 @@ // Taken from http://wiki.unity3d.com/index.php?title=MouseOrbitImproved namespace UnityGLTF.Examples { + [RequireComponent(typeof(Camera))] [AddComponentMenu("Camera-Control/Mouse Orbit with zoom")] public class OrbitCameraController : MonoBehaviour { - public Transform target; + public Vector3 targetPosition = Vector3.zero; public float distance = 5.0f; public float xSpeed = 120.0f; public float ySpeed = 120.0f; + public float zoomSpeed = 0.8f; - public float yMinLimit = -20f; - public float yMaxLimit = 80f; + public float yMinLimit = -85f; + public float yMaxLimit = 85f; public float distanceMin = .5f; - public float distanceMax = 15f; + public float distanceMax = 150f; + + private Camera camera; private Rigidbody cameraRigidBody; - float x = 0.0f; - float y = 0.0f; + private float x = 0.0f; + private float y = 0.0f; + private Vector3 prevMousePosition; + + Quaternion rotation; // Use this for initialization void Start() { + camera = GetComponent(); + Vector3 angles = transform.eulerAngles; x = angles.y; y = angles.x; + rotation = Quaternion.Euler(y, x, 0); + + prevMousePosition = Input.mousePosition; cameraRigidBody = GetComponent(); @@ -40,28 +52,52 @@ void Start() void LateUpdate() { - if (target) + var height = Display.main.renderingHeight; + var width = Display.main.renderingWidth; + + if (Input.GetMouseButton(0)) { - x += Input.GetAxis("Mouse X") * xSpeed * distance * 0.02f; - y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f; + x += Input.GetAxis("Mouse X") * xSpeed * 0.06f; + y -= Input.GetAxis("Mouse Y") * ySpeed * 0.06f; y = ClampAngle(y, yMinLimit, yMaxLimit); - Quaternion rotation = Quaternion.Euler(y, x, 0); + rotation = Quaternion.Euler(y, x, 0); + } + else if (Input.GetMouseButton(1)) + { + var prevMouseWorldPosition = ProjectScreenPointToTargetPlane(prevMousePosition); + var mouseWorldPosition = ProjectScreenPointToTargetPlane(Input.mousePosition); - distance = Mathf.Clamp(distance - Input.GetAxis("Mouse ScrollWheel") * 5, distanceMin, distanceMax); + targetPosition += prevMouseWorldPosition - mouseWorldPosition; + } - RaycastHit hit; - if (Physics.Linecast(target.position, transform.position, out hit)) - { - distance -= hit.distance; - } - Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance); - Vector3 position = rotation * negDistance + target.position; + var mouseOverRenderArea = + Input.mousePosition.x >= 0 && + Input.mousePosition.x <= width && + Input.mousePosition.y >= 0 && + Input.mousePosition.y <= height; - transform.rotation = rotation; - transform.position = position; + if (Input.GetMouseButton(0) || mouseOverRenderArea) + { + distance = Mathf.Clamp(distance * Mathf.Exp(-Input.GetAxis("Mouse ScrollWheel") * zoomSpeed), distanceMin, distanceMax); } + + Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance); + Vector3 position = rotation * negDistance + targetPosition; + + transform.rotation = rotation; + transform.position = position; + + prevMousePosition = Input.mousePosition; + } + + private Vector3 ProjectScreenPointToTargetPlane(Vector3 screenPosition) + { + var ray = camera.ScreenPointToRay(screenPosition); + var planeDistance = distance / Mathf.Cos(Mathf.Deg2Rad * Vector3.Angle(camera.transform.forward, ray.direction)); + + return camera.transform.position + (ray.direction * planeDistance); } public static float ClampAngle(float angle, float min, float max) diff --git a/UnityGLTF/Assets/UnityGLTF/Examples/UWPTestScene.unity b/UnityGLTF/Assets/UnityGLTF/Examples/UWPTestScene.unity index c1dc1d190..1e609f5c6 100644 --- a/UnityGLTF/Assets/UnityGLTF/Examples/UWPTestScene.unity +++ b/UnityGLTF/Assets/UnityGLTF/Examples/UWPTestScene.unity @@ -306,10 +306,11 @@ MonoBehaviour: distance: 5 xSpeed: 120 ySpeed: 120 - yMinLimit: -20 - yMaxLimit: 80 + zoomSpeed: 0.8 + yMinLimit: -85 + yMaxLimit: 85 distanceMin: 0.5 - distanceMax: 15 + distanceMax: 150 --- !u!81 &1650054228 AudioListener: m_ObjectHideFlags: 0 diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Async/AsyncCoroutineHelper.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Async/AsyncCoroutineHelper.cs index 8e304ea2e..d1ea3437b 100644 --- a/UnityGLTF/Assets/UnityGLTF/Scripts/Async/AsyncCoroutineHelper.cs +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Async/AsyncCoroutineHelper.cs @@ -2,95 +2,38 @@ using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; + namespace UnityGLTF { - public interface IAsyncCoroutineHelper - { - Task RunAsTask(IEnumerator coroutine, string name); - Task YieldOnTimeout(); - } - - public class AsyncCoroutineHelper : MonoBehaviour, IAsyncCoroutineHelper - { - public float BudgetPerFrameInSeconds = 0.01f; - - private Queue _actions = new Queue(); - private WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame(); - private float _timeout; - - public Task RunAsTask(IEnumerator coroutine, string name) - { - TaskCompletionSource tcs = new TaskCompletionSource(); - lock (_actions) - { - _actions.Enqueue( - new CoroutineInfo - { - Coroutine = coroutine, - Tcs = tcs, - Name = name - } - ); - } - - return tcs.Task; - } - - public async Task YieldOnTimeout() - { - if (Time.realtimeSinceStartup > _timeout) - { - await RunAsTask(EmptyYieldEnum(), nameof(EmptyYieldEnum)); - } - } - - private void Start() - { - _timeout = Time.realtimeSinceStartup + BudgetPerFrameInSeconds; - } - - private void Update() - { - StartCoroutine(ResetFrameTimeout()); - - CoroutineInfo ? coroutineInfo = null; - - lock (_actions) - { - if (_actions.Count > 0) - { - coroutineInfo = _actions.Dequeue(); - } - } - - if (coroutineInfo != null) - { - StartCoroutine(CallMethodOnMainThread(coroutineInfo.Value)); - } - } - - private IEnumerator CallMethodOnMainThread(CoroutineInfo coroutineInfo) - { - yield return coroutineInfo.Coroutine; - coroutineInfo.Tcs.SetResult(true); - } - - private IEnumerator EmptyYieldEnum() - { - yield break; - } - - private IEnumerator ResetFrameTimeout() - { - yield return _waitForEndOfFrame; - _timeout = Time.realtimeSinceStartup + BudgetPerFrameInSeconds; - } - - private struct CoroutineInfo - { - public IEnumerator Coroutine; - public TaskCompletionSource Tcs; - public string Name; - } - } + public class AsyncCoroutineHelper : MonoBehaviour + { + public float BudgetPerFrameInSeconds = 0.01f; + + private WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame(); + private float _timeout; + + public async Task YieldOnTimeout() + { + if (Time.realtimeSinceStartup > _timeout) + { + await Task.Delay(1); + } + } + + private void Start() + { + _timeout = Time.realtimeSinceStartup + BudgetPerFrameInSeconds; + + StartCoroutine(ResetFrameTimeout()); + } + + private IEnumerator ResetFrameTimeout() + { + while (true) + { + yield return _waitForEndOfFrame; + _timeout = Time.realtimeSinceStartup + BudgetPerFrameInSeconds; + } + } + } } diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/MaterialCacheData.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/MaterialCacheData.cs index 399d576ad..ff9083198 100644 --- a/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/MaterialCacheData.cs +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/MaterialCacheData.cs @@ -1,9 +1,10 @@ using GLTF.Schema; +using System; using UnityEngine; namespace UnityGLTF.Cache { - public class MaterialCacheData + public class MaterialCacheData : IDisposable { public Material UnityMaterial { get; set; } public Material UnityMaterialWithVertexColor { get; set; } @@ -17,16 +18,18 @@ public Material GetContents(bool useVertexColors) /// /// Unloads the materials in this cache. /// - public void Unload() + public void Dispose() { if (UnityMaterial != null) { - Object.Destroy(UnityMaterial); + UnityEngine.Object.Destroy(UnityMaterial); + UnityMaterial = null; } if (UnityMaterialWithVertexColor != null) { - Object.Destroy(UnityMaterialWithVertexColor); + UnityEngine.Object.Destroy(UnityMaterialWithVertexColor); + UnityMaterialWithVertexColor = null; } } } diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/MeshCacheData.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/MeshCacheData.cs index a04b282fc..064a65e17 100644 --- a/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/MeshCacheData.cs +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/MeshCacheData.cs @@ -1,14 +1,15 @@ using GLTF; +using System; using System.Collections.Generic; using UnityEngine; namespace UnityGLTF.Cache { - public class MeshCacheData + public class MeshCacheData : IDisposable { public Mesh LoadedMesh { get; set; } public Dictionary MeshAttributes { get; set; } - public GameObject PrimitiveGO { get; set; } + public GameObject PrimitiveGO { get; set; } public MeshCacheData() { @@ -18,9 +19,13 @@ public MeshCacheData() /// /// Unloads the meshes in this cache. /// - public void Unload() + public void Dispose() { - Object.Destroy(LoadedMesh); + if (LoadedMesh != null) + { + UnityEngine.Object.Destroy(LoadedMesh); + LoadedMesh = null; + } } } } diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/RefCountedCacheData.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/RefCountedCacheData.cs index db3e96ee6..92f0d198a 100644 --- a/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/RefCountedCacheData.cs +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/RefCountedCacheData.cs @@ -25,17 +25,30 @@ public class RefCountedCacheData /// /// Meshes used by this GLTF node. /// - public MeshCacheData[][] MeshCache { get; set; } + public MeshCacheData[][] MeshCache { get; private set; } /// /// Materials used by this GLTF node. /// - public MaterialCacheData[] MaterialCache { get; set; } + public MaterialCacheData[] MaterialCache { get; private set; } /// /// Textures used by this GLTF node. /// - public TextureCacheData[] TextureCache { get; set; } + public TextureCacheData[] TextureCache { get; private set; } + + /// + /// Textures from the AssetCache that might need to be cleaned up + /// + public Texture2D[] ImageCache { get; private set; } + + public RefCountedCacheData(MaterialCacheData[] materialCache, MeshCacheData[][] meshCache, TextureCacheData[] textureCache, Texture2D[] imageCache) + { + MaterialCache = materialCache; + MeshCache = meshCache; + TextureCache = textureCache; + ImageCache = imageCache; + } public void IncreaseRefCount() { @@ -80,28 +93,32 @@ private void DestroyCachedData() { for (int j = 0; j < MeshCache[i].Length; j++) { - if (MeshCache[i][j] != null) - { - MeshCache[i][j].Unload(); - } + MeshCache[i][j]?.Dispose(); + MeshCache[i][j] = null; } } // Destroy the cached textures for (int i = 0; i < TextureCache.Length; i++) { - if (TextureCache[i] != null) - { - TextureCache[i].Unload(); - } + TextureCache[i]?.Dispose(); + TextureCache[i] = null; } // Destroy the cached materials for (int i = 0; i < MaterialCache.Length; i++) { - if (MaterialCache[i] != null) + MaterialCache[i]?.Dispose(); + MaterialCache[i] = null; + } + + // Destroy the cached images + for (int i = 0; i < ImageCache.Length; i++) + { + if (ImageCache[i] != null) { - MaterialCache[i].Unload(); + UnityEngine.Object.Destroy(ImageCache[i]); + ImageCache[i] = null; } } diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/TextureCacheData.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/TextureCacheData.cs index 90248769a..5f4bc1bdd 100644 --- a/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/TextureCacheData.cs +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Cache/TextureCacheData.cs @@ -1,9 +1,10 @@ using GLTF.Schema; +using System; using UnityEngine; namespace UnityGLTF.Cache { - public class TextureCacheData + public class TextureCacheData : IDisposable { public GLTFTexture TextureDefinition; public Texture Texture; @@ -11,9 +12,13 @@ public class TextureCacheData /// /// Unloads the textures in this cache. /// - public void Unload() + public void Dispose() { - Object.Destroy(Texture); + if (Texture != null) + { + UnityEngine.Object.Destroy(Texture); + Texture = null; + } } } } diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/UnityGLTFEditor.asmdef b/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/UnityGLTFEditor.asmdef new file mode 100644 index 000000000..c9a3347a7 --- /dev/null +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/UnityGLTFEditor.asmdef @@ -0,0 +1,16 @@ +{ + "name": "UnityGLTFEditor", + "references": [ + "UnityGLTFScripts" + ], + "optionalUnityReferences": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] +} \ No newline at end of file diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/UnityGLTFEditor.asmdef.meta b/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/UnityGLTFEditor.asmdef.meta new file mode 100644 index 000000000..68e4ef64f --- /dev/null +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Editor/UnityGLTFEditor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1a0324566af4ed544918d6837a1f4e11 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFComponent.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFComponent.cs index 0e8b17948..6f037163b 100644 --- a/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFComponent.cs +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFComponent.cs @@ -35,6 +35,7 @@ public class GLTFComponent : MonoBehaviour public int MaximumLod = 300; public int Timeout = 8; public GLTFSceneImporter.ColliderType Collider = GLTFSceneImporter.ColliderType.None; + public GameObject LastLoadedScene { get; private set; } = null; private AsyncCoroutineHelper asyncCoroutineHelper; @@ -137,6 +138,8 @@ public async Task Load() } } + LastLoadedScene = sceneImporter.LastLoadedScene; + if (PlayAnimationOnLoad) { Animation[] animations = sceneImporter.LastLoadedScene.GetComponents(); diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneImporter.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneImporter.cs index 2e9dbad67..c4758c85a 100644 --- a/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneImporter.cs +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneImporter.cs @@ -136,7 +136,7 @@ protected struct GLBStream public long StartPosition; } - protected IAsyncCoroutineHelper _asyncCoroutineHelper; + protected AsyncCoroutineHelper _asyncCoroutineHelper; protected GameObject _lastLoadedScene; protected readonly GLTFMaterial DefaultMaterial = new GLTFMaterial(); @@ -167,7 +167,7 @@ public GLTFSceneImporter(GLTFRoot rootNode, ILoader externalDataLoader, AsyncCor _loader = externalDataLoader; if (gltfStream != null) { - _gltfStream = new GLBStream {Stream = gltfStream, StartPosition = gltfStream.Position}; + _gltfStream = new GLBStream { Stream = gltfStream, StartPosition = gltfStream.Position }; } } @@ -196,8 +196,9 @@ public GameObject LastLoadedScene /// The scene to load, If the index isn't specified, we use the default index in the file. Failing that we load index 0. /// /// Callback function for when load is completed + /// Cancellation token for loading /// - public async Task LoadSceneAsync(int sceneIndex = -1, bool showSceneObj = true, Action onLoadComplete = null) + public async Task LoadSceneAsync(int sceneIndex = -1, bool showSceneObj = true, Action onLoadComplete = null, CancellationToken cancellationToken = default(CancellationToken)) { try { @@ -216,12 +217,14 @@ public async Task LoadSceneAsync(int sceneIndex = -1, bool showSceneObj = true, await LoadJson(_gltfFileName); } + cancellationToken.ThrowIfCancellationRequested(); + if (_assetCache == null) { _assetCache = new AssetCache(_gltfRoot); } - await _LoadScene(sceneIndex, showSceneObj); + await _LoadScene(sceneIndex, showSceneObj, cancellationToken); } catch (Exception ex) { @@ -273,7 +276,7 @@ public async Task LoadNodeAsync(int nodeIndex) _assetCache = new AssetCache(_gltfRoot); } - await _LoadNode(nodeIndex); + await _LoadNode(nodeIndex, CancellationToken.None); CreatedObject = _assetCache.NodeCache[nodeIndex]; InitializeGltfTopLevelObject(); } @@ -346,15 +349,18 @@ private void InitializeGltfTopLevelObject() { InstantiatedGLTFObject instantiatedGltfObject = CreatedObject.AddComponent(); instantiatedGltfObject.CachedData = new RefCountedCacheData - { - MaterialCache = _assetCache.MaterialCache, - MeshCache = _assetCache.MeshCache, - TextureCache = _assetCache.TextureCache - }; + ( + _assetCache.MaterialCache, + _assetCache.MeshCache, + _assetCache.TextureCache, + _assetCache.ImageCache + ); } - private async Task ConstructBufferData(Node node) + private async Task ConstructBufferData(Node node, CancellationToken cancellationToken) { + cancellationToken.ThrowIfCancellationRequested(); + MeshId mesh = node.Mesh; if (mesh != null) { @@ -368,7 +374,7 @@ private async Task ConstructBufferData(Node node) { foreach (NodeId child in node.Children) { - await ConstructBufferData(child.Value); + await ConstructBufferData(child.Value, cancellationToken); } } @@ -385,7 +391,7 @@ private async Task ConstructBufferData(Node node) for (int i = 0; i < lodsextension.MeshIds.Count; i++) { int lodNodeId = lodsextension.MeshIds[i]; - await ConstructBufferData(_gltfRoot.Nodes[lodNodeId]); + await ConstructBufferData(_gltfRoot.Nodes[lodNodeId], cancellationToken); } } } @@ -439,10 +445,13 @@ protected async Task ConstructImageBuffer(GLTFTexture texture, int textureIndex) } } - _assetCache.TextureCache[textureIndex] = new TextureCacheData + if (_assetCache.TextureCache[textureIndex] == null) { - TextureDefinition = texture - }; + _assetCache.TextureCache[textureIndex] = new TextureCacheData + { + TextureDefinition = texture + }; + } } protected IEnumerator WaitUntilEnum(WaitUntil waitUntil) @@ -453,19 +462,19 @@ protected IEnumerator WaitUntilEnum(WaitUntil waitUntil) private async Task LoadJson(string jsonFilePath) { #if !WINDOWS_UWP - if (IsMultithreaded && _loader.HasSyncLoadMethod) - { + if (IsMultithreaded && _loader.HasSyncLoadMethod) + { Thread loadThread = new Thread(() => _loader.LoadStreamSync(jsonFilePath)); loadThread.Priority = ThreadPriority.Highest; loadThread.Start(); RunCoroutineSync(WaitUntilEnum(new WaitUntil(() => !loadThread.IsAlive))); - } - else + } + else #endif - { + { // HACK: Force the coroutine to run synchronously in the editor await _loader.LoadStream(jsonFilePath); - } + } _gltfStream.Stream = _loader.LoadedStream; _gltfStream.StartPosition = 0; @@ -508,7 +517,7 @@ private static void RunCoroutineSync(IEnumerator streamEnum) } } - private async Task _LoadNode(int nodeIndex) + private async Task _LoadNode(int nodeIndex, CancellationToken cancellationToken) { if (nodeIndex >= _gltfRoot.Nodes.Count) { @@ -517,16 +526,18 @@ private async Task _LoadNode(int nodeIndex) Node nodeToLoad = _gltfRoot.Nodes[nodeIndex]; + cancellationToken.ThrowIfCancellationRequested(); if (!IsMultithreaded) { - await ConstructBufferData(nodeToLoad); + await ConstructBufferData(nodeToLoad, cancellationToken); } else { - await Task.Run(() => ConstructBufferData(nodeToLoad)); + await Task.Run(() => ConstructBufferData(nodeToLoad, cancellationToken)); } - await ConstructNode(nodeToLoad, nodeIndex); + cancellationToken.ThrowIfCancellationRequested(); + await ConstructNode(nodeToLoad, nodeIndex, cancellationToken); } /// @@ -534,7 +545,7 @@ private async Task _LoadNode(int nodeIndex) /// /// The bufferIndex of scene in gltf file to load /// - protected async Task _LoadScene(int sceneIndex = -1, bool showSceneObj = true) + protected async Task _LoadScene(int sceneIndex = -1, bool showSceneObj = true, CancellationToken cancellationToken = default(CancellationToken)) { GLTFScene scene; @@ -552,7 +563,7 @@ protected async Task _LoadScene(int sceneIndex = -1, bool showSceneObj = true) throw new GLTFLoadException("No default scene in gltf file."); } - await ConstructScene(scene, showSceneObj); + await ConstructScene(scene, showSceneObj, cancellationToken); if (SceneParent != null) { @@ -630,6 +641,7 @@ protected async Task ConstructImage(GLTFImage image, int imageCacheIndex, bool m protected virtual async Task ConstructUnityTexture(Stream stream, bool markGpuOnly, bool isLinear, GLTFImage image, int imageCacheIndex) { Texture2D texture = new Texture2D(0, 0, TextureFormat.RGBA32, true, isLinear); + texture.name = nameof(GLTFSceneImporter) + (image.Name != null ? ("." + image.Name) : ""); if (stream is MemoryStream) { @@ -745,11 +757,11 @@ protected void TransformAttributes(ref Dictionary att } } -#region Animation + #region Animation static string RelativePathFrom(Transform self, Transform root) { var path = new List(); - for (var current = self; current != null; current = current.parent) + for (var current = self; current != null; current = current.parent) { if (current == root) { @@ -838,7 +850,7 @@ protected void SetAnimationCurve( // copy all the key frame data to cache Keyframe[][] keyframes = new Keyframe[channelCount][]; - for( var ci = 0; ci < channelCount; ++ci) + for (var ci = 0; ci < channelCount; ++ci) { keyframes[ci] = new Keyframe[frameCount]; } @@ -849,13 +861,13 @@ protected void SetAnimationCurve( var values = getConvertedValues(output, i); - for( var ci = 0; ci < channelCount; ++ci) + for (var ci = 0; ci < channelCount; ++ci) { keyframes[ci][i] = new Keyframe(time, values[ci]); } } - for( var ci = 0; ci < channelCount; ++ci) + for (var ci = 0; ci < channelCount; ++ci) { // set interpolcation for each keyframe SetCurveMode(keyframes[ci], mode); @@ -912,9 +924,10 @@ protected AnimationClip ConstructClip(Transform root, GameObject[] nodes, int an SetAnimationCurve(clip, relativePath, propertyNames, input, output, samplerCache.Interpolation, typeof(Transform), - (data, frame) => { + (data, frame) => + { var position = data.AsVec3s[frame].ToUnityVector3Convert(); - return new float[] { position.x, position.y, position.z}; + return new float[] { position.x, position.y, position.z }; }); break; @@ -923,10 +936,11 @@ protected AnimationClip ConstructClip(Transform root, GameObject[] nodes, int an SetAnimationCurve(clip, relativePath, propertyNames, input, output, samplerCache.Interpolation, typeof(Transform), - (data, frame) => { + (data, frame) => + { var rotation = data.AsVec4s[frame]; var quaternion = new GLTF.Math.Quaternion(rotation.X, rotation.Y, rotation.Z, rotation.W).ToUnityQuaternionConvert(); - return new float[] { quaternion.x, quaternion.y, quaternion.z, quaternion.w}; + return new float[] { quaternion.x, quaternion.y, quaternion.z, quaternion.w }; }); break; @@ -936,9 +950,10 @@ protected AnimationClip ConstructClip(Transform root, GameObject[] nodes, int an SetAnimationCurve(clip, relativePath, propertyNames, input, output, samplerCache.Interpolation, typeof(Transform), - (data, frame) => { + (data, frame) => + { var scale = data.AsVec3s[frame].ToUnityVector3Raw(); - return new float[] { scale.x, scale.y, scale.z}; + return new float[] { scale.x, scale.y, scale.z }; }); break; @@ -1037,9 +1052,9 @@ public static void SetCurveMode(Keyframe[] keyframes, InterpolationType mode) key.outTangent = outtangent; } } -#endregion + #endregion - protected virtual async Task ConstructScene(GLTFScene scene, bool showSceneObj) + protected virtual async Task ConstructScene(GLTFScene scene, bool showSceneObj, CancellationToken cancellationToken) { var sceneObj = new GameObject(string.IsNullOrEmpty(scene.Name) ? ("GLTFScene") : scene.Name); sceneObj.SetActive(showSceneObj); @@ -1048,7 +1063,7 @@ protected virtual async Task ConstructScene(GLTFScene scene, bool showSceneObj) for (int i = 0; i < scene.Nodes.Count; ++i) { NodeId node = scene.Nodes[i]; - await _LoadNode(node.Id); + await _LoadNode(node.Id, cancellationToken); GameObject nodeObj = _assetCache.NodeCache[node.Id]; nodeObj.transform.SetParent(sceneObj.transform, false); nodeTransforms[i] = nodeObj.transform; @@ -1077,8 +1092,10 @@ protected virtual async Task ConstructScene(GLTFScene scene, bool showSceneObj) } - protected virtual async Task ConstructNode(Node node, int nodeIndex) + protected virtual async Task ConstructNode(Node node, int nodeIndex, CancellationToken cancellationToken) { + cancellationToken.ThrowIfCancellationRequested(); + if (_assetCache.NodeCache[nodeIndex] != null) { return; @@ -1098,7 +1115,7 @@ protected virtual async Task ConstructNode(Node node, int nodeIndex) if (node.Mesh != null) { - await ConstructMesh(node.Mesh.Value, nodeObj.transform, node.Mesh.Id, node.Skin != null ? node.Skin.Value : null); + await ConstructMesh(node.Mesh.Value, nodeObj.transform, node.Mesh.Id, node.Skin != null ? node.Skin.Value : null, cancellationToken); } /* TODO: implement camera (probably a flag to disable for VR as well) if (camera != null) @@ -1113,7 +1130,7 @@ protected virtual async Task ConstructNode(Node node, int nodeIndex) foreach (var child in node.Children) { // todo blgross: replace with an iterartive solution - await ConstructNode(child.Value, child.Id); + await ConstructNode(child.Value, child.Id, cancellationToken); GameObject childObj = _assetCache.NodeCache[child.Id]; childObj.transform.SetParent(nodeObj.transform, false); } @@ -1151,7 +1168,7 @@ protected virtual async Task ConstructNode(Node node, int nodeIndex) for (int i = 0; i < lodsextension.MeshIds.Count; i++) { int lodNodeId = lodsextension.MeshIds[i]; - await ConstructNode(_gltfRoot.Nodes[lodNodeId], lodNodeId); + await ConstructNode(_gltfRoot.Nodes[lodNodeId], lodNodeId, cancellationToken); int lodIndex = i + 1; GameObject lodNodeObj = _assetCache.NodeCache[lodNodeId]; lodNodeObj.transform.SetParent(lodGroupNodeObj.transform, false); @@ -1223,7 +1240,7 @@ protected virtual async Task SetupBones(Skin skin, MeshPrimitive primitive, Skin { if (_assetCache.NodeCache[skin.Joints[i].Id] == null) { - await ConstructNode(_gltfRoot.Nodes[skin.Joints[i].Id], skin.Joints[i].Id); + await ConstructNode(_gltfRoot.Nodes[skin.Joints[i].Id], skin.Joints[i].Id, CancellationToken.None); } bones[i] = _assetCache.NodeCache[skin.Joints[i].Id].transform; bindPoses[i] = gltfBindPoses[i].ToUnityMatrix4x4Convert(); @@ -1272,8 +1289,10 @@ private void NormalizeBoneWeightArray(Vector4[] weights) } } - protected virtual async Task ConstructMesh(GLTFMesh mesh, Transform parent, int meshId, Skin skin) + protected virtual async Task ConstructMesh(GLTFMesh mesh, Transform parent, int meshId, Skin skin, CancellationToken cancellationToken) { + cancellationToken.ThrowIfCancellationRequested(); + if (_assetCache.MeshCache[meshId] == null) { _assetCache.MeshCache[meshId] = new MeshCacheData[mesh.Primitives.Count]; @@ -1285,6 +1304,7 @@ protected virtual async Task ConstructMesh(GLTFMesh mesh, Transform parent, int int materialIndex = primitive.Material != null ? primitive.Material.Id : -1; await ConstructMeshPrimitive(primitive, meshId, i, materialIndex); + cancellationToken.ThrowIfCancellationRequested(); var primitiveObj = new GameObject("Primitive"); @@ -1305,6 +1325,7 @@ protected virtual async Task ConstructMesh(GLTFMesh mesh, Transform parent, int if (HasBones(skin)) { await SetupBones(skin, primitive, skinnedMeshRenderer, primitiveObj, curMesh); + cancellationToken.ThrowIfCancellationRequested(); } skinnedMeshRenderer.sharedMesh = curMesh; @@ -1605,7 +1626,7 @@ protected virtual async Task ConstructMaterial(GLTFMaterial def, int materialInd mrMapper.BaseColorTexCoord = pbr.BaseColorTexture.TexCoord; var ext = GetTextureTransform(pbr.BaseColorTexture); - if(ext != null) + if (ext != null) { mrMapper.BaseColorXOffset = ext.Offset.ToUnityVector2Raw(); mrMapper.BaseColorXRotation = ext.Rotation; @@ -1849,11 +1870,11 @@ protected virtual async Task ConstructTexture(GLTFTexture texture, int textureIn { case MinFilterMode.Nearest: case MinFilterMode.NearestMipmapNearest: - case MinFilterMode.NearestMipmapLinear: + case MinFilterMode.LinearMipmapNearest: desiredFilterMode = FilterMode.Point; break; case MinFilterMode.Linear: - case MinFilterMode.LinearMipmapNearest: + case MinFilterMode.NearestMipmapLinear: desiredFilterMode = FilterMode.Bilinear; break; case MinFilterMode.LinearMipmapLinear: @@ -1891,6 +1912,7 @@ protected virtual async Task ConstructTexture(GLTFTexture texture, int textureIn var matchSamplerState = source.filterMode == desiredFilterMode && source.wrapMode == desiredWrapMode; if (matchSamplerState || markGpuOnly) { + Debug.Assert(_assetCache.TextureCache[textureIndex].Texture == null, "Texture should not be reset to prevent memory leaks"); _assetCache.TextureCache[textureIndex].Texture = source; if (!matchSamplerState) @@ -1904,6 +1926,7 @@ protected virtual async Task ConstructTexture(GLTFTexture texture, int textureIn unityTexture.filterMode = desiredFilterMode; unityTexture.wrapMode = desiredWrapMode; + Debug.Assert(_assetCache.TextureCache[textureIndex].Texture == null, "Texture should not be reset to prevent memory leaks"); _assetCache.TextureCache[textureIndex].Texture = unityTexture; } } @@ -1912,6 +1935,7 @@ protected virtual async Task ConstructTexture(GLTFTexture texture, int textureIn protected virtual void ConstructImageFromGLB(GLTFImage image, int imageCacheIndex) { var texture = new Texture2D(0, 0); + texture.name = nameof(GLTFSceneImporter) + (image.Name != null ? ("." + image.Name) : ""); var bufferView = image.BufferView.Value; var data = new byte[bufferView.ByteLength]; diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/GLTFSceneTests.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/GLTFSceneTests.cs index d5c968464..60b038b85 100644 --- a/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/GLTFSceneTests.cs +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/GLTFSceneTests.cs @@ -1,22 +1,14 @@ #if UNITY_EDITOR -using AssetGenerator; -using Newtonsoft.Json; -using NUnit.Compatibility; using NUnit.Framework; using System; using System.Collections; using System.Collections.Generic; using System.IO; -using System.Linq; -using UnityEditor.SceneManagement; using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.TestTools; using UnityGLTF; using Camera = UnityEngine.Camera; -using Object = System.Object; public class GLTFSceneTests { @@ -24,10 +16,6 @@ public class GLTFSceneTests static string GLTF_SCENARIO_OUTPUT_PATH = Application.dataPath + "/../ScenarioScenesTests/Output/"; private static bool GENERATE_REFERENCEDATA = false; - private Dictionary cameras = - new Dictionary(); - - public static IEnumerable SceneFilePaths { get @@ -37,10 +25,8 @@ public static IEnumerable SceneFilePaths string[] files = Directory.GetFiles(GLTF_SCENES_PATH, "*.unity", SearchOption.AllDirectories); for (int i = 0; i < files.Length; i++) { - string filename = Path.GetFileNameWithoutExtension(files[i]); var fileUri = new Uri(files[i]); files[i] = gltfPathUri.MakeRelativeUri(fileUri).ToString(); - } return files; } diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/SampleModelListInspector.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/SampleModelListInspector.cs new file mode 100644 index 000000000..c31b14d8c --- /dev/null +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/SampleModelListInspector.cs @@ -0,0 +1,111 @@ +using Newtonsoft.Json; +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using UnityEditor; +using UnityEngine; +using UnityGLTF.Loader; + +[CustomEditor(typeof(SampleModelList))] +public class SampleModelListInspector : Editor +{ + private List models = null; + private bool requestedModelList = false; + private Vector2 scroll = Vector2.zero; + private SampleModel currentModel = null; + + public override void OnInspectorGUI() + { + EditorGUILayout.PropertyField(serializedObject.FindProperty(SampleModelList.LoaderFieldName)); + EditorGUILayout.PropertyField(serializedObject.FindProperty(SampleModelList.PathRootFieldName)); + EditorGUILayout.PropertyField(serializedObject.FindProperty(SampleModelList.ManifestRelativePathFieldName)); + EditorGUILayout.PropertyField(serializedObject.FindProperty(SampleModelList.ModelRelativePathFieldName)); + EditorGUILayout.PropertyField(serializedObject.FindProperty(SampleModelList.LoadThisFrameFieldName)); + + serializedObject.ApplyModifiedProperties(); + + if (!Application.isPlaying) + { + models = null; + requestedModelList = false; + scroll = Vector2.zero; + } + else + { + if (!requestedModelList) + { + requestedModelList = true; + + DownloadSampleModelList(); + } + + EditorGUILayout.LabelField("Models:"); + + if (models != null) + { + scroll = EditorGUILayout.BeginScrollView(scroll); + + foreach (var model in models) + { + EditorGUILayout.BeginHorizontal(); + GUIStyle style = new GUIStyle(GUI.skin.label); + if (model == currentModel) + { + style.fontStyle = FontStyle.Bold; + } + GUILayout.Label(model.Name, style); + + foreach (var variant in model.Variants) + { + var buttonPressed = GUILayout.Button(variant.Type); + + if (buttonPressed) + { + currentModel = model; + LoadModel(model.Name, variant.Type, variant.FileName); + } + } + + EditorGUILayout.EndHorizontal(); + } + + EditorGUILayout.EndScrollView(); + } + } + } + + private void LoadModel(string modelName, string variantType, string variantName) + { + string relativePath = $"{modelName}/{variantType}/{variantName}"; + + serializedObject.FindProperty(SampleModelList.ModelRelativePathFieldName).stringValue = relativePath; + serializedObject.FindProperty(SampleModelList.LoadThisFrameFieldName).boolValue = true; + serializedObject.ApplyModifiedProperties(); + } + + private async void DownloadSampleModelList() + { + var pathRoot = serializedObject.FindProperty(SampleModelList.PathRootFieldName).stringValue; + var manifestRelativePath = serializedObject.FindProperty(SampleModelList.ManifestRelativePathFieldName).stringValue; + + var loader = new WebRequestLoader(pathRoot); + try + { + await loader.LoadStream(manifestRelativePath); + } + catch (HttpRequestException) + { + Debug.LogError($"Failed to download sample model list manifest from: {pathRoot}{manifestRelativePath}", serializedObject.targetObject); + throw; + } + + loader.LoadedStream.Seek(0, SeekOrigin.Begin); + + var streamReader = new StreamReader(loader.LoadedStream); + + var reader = new JsonTextReader(streamReader); + + reader.Read(); + models = SampleModelListParser.ParseSampleModels(reader); + } +} diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/SampleModelListInspector.cs.meta b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/SampleModelListInspector.cs.meta new file mode 100644 index 000000000..61712a23b --- /dev/null +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/SampleModelListInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f28130cf15191b44ea20112e38fb9a6c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/SampleModelListParser.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/SampleModelListParser.cs new file mode 100644 index 000000000..5fbfd73cb --- /dev/null +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/SampleModelListParser.cs @@ -0,0 +1,155 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; + +public class SampleModelVariant +{ + public string Type; + public string FileName; +} + +public class SampleModel +{ + public string Name; + public string ScreenshotPath; + public List Variants; +} + +public static class SampleModelListParser +{ + public static List ParseSampleModels(JsonReader reader) + { + var models = new List(); + + ParseStartArray(reader, "models"); + + while (reader.TokenType != JsonToken.EndArray) + { + models.Add(ParseSampleModel(reader)); + } + + ParseEndArray(reader, "models"); + + return models; + } + + private static SampleModel ParseSampleModel(JsonReader reader) + { + var result = new SampleModel(); + + ParseStartObject(reader, "model"); + + while (reader.TokenType != JsonToken.EndObject) + { + if (reader.TokenType != JsonToken.PropertyName) + { + throw new Exception("Failed to parse model name property"); + } + var propertyName = reader.Value.ToString().ToLowerInvariant(); + reader.Read(); + + switch (propertyName) + { + case "name": + result.Name = ParsePropertyValueAsString(reader, propertyName); + break; + case "screenshot": + result.ScreenshotPath = ParsePropertyValueAsString(reader, propertyName); + break; + case "variants": + result.Variants = ParseVariants(reader); + break; + } + } + + ParseEndObject(reader, "model"); + + return result; + } + + private static string ParsePropertyValueAsString(JsonReader reader, string propertyName) + { + if (reader.TokenType != JsonToken.String) + { + throw new Exception($"Failed to parse string value for {propertyName}"); + } + var result = reader.Value.ToString(); + + reader.Read(); + + return result; + } + + private static List ParseVariants(JsonReader reader) + { + var variants = new List(); + + ParseStartObject(reader, "variants"); + + while (reader.TokenType != JsonToken.EndObject) + { + variants.Add(ParseVariant(reader)); + } + + ParseEndObject(reader, "variants"); + + return variants; + } + + private static SampleModelVariant ParseVariant(JsonReader reader) + { + var result = new SampleModelVariant(); + + if (reader.TokenType != JsonToken.PropertyName) + { + throw new Exception("Failed to parse model variant name"); + } + result.Type = reader.Value.ToString(); + reader.Read(); + + if (reader.TokenType != JsonToken.String) + { + throw new Exception("Failed to parse model variant filename"); + } + result.FileName = reader.Value.ToString(); + reader.Read(); + + return result; + } + + private static void ParseStartObject(JsonReader reader, string objectName) + { + if (reader.TokenType != JsonToken.StartObject) + { + throw new Exception($"Failed to parse {objectName} start"); + } + reader.Read(); + } + + private static void ParseEndObject(JsonReader reader, string objectName) + { + if (reader.TokenType != JsonToken.EndObject) + { + throw new Exception($"Failed to parse {objectName} end"); + } + reader.Read(); + } + + private static void ParseStartArray(JsonReader reader, string objectName) + { + if (reader.TokenType != JsonToken.StartArray) + { + throw new Exception($"Failed to parse {objectName} start"); + } + reader.Read(); + } + + private static void ParseEndArray(JsonReader reader, string objectName) + { + if (reader.TokenType != JsonToken.EndArray) + { + throw new Exception($"Failed to parse {objectName} end"); + } + reader.Read(); + } +} diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/SampleModelListParser.cs.meta b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/SampleModelListParser.cs.meta new file mode 100644 index 000000000..0adfd8ab6 --- /dev/null +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/SampleModelListParser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 59a81a17ba63ebb4a9897bfeb7693a26 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/Integration.meta b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Integration.meta similarity index 58% rename from UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/Integration.meta rename to UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Integration.meta index ab5ce21da..55750aa52 100644 --- a/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Editor/Integration.meta +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/Integration.meta @@ -1,9 +1,8 @@ fileFormatVersion: 2 -guid: e1c2c4a5d74bb304f8208a98cc16db22 +guid: 5783cb7e53a767047b9bbec12c1cd4cf folderAsset: yes -timeCreated: 1506549706 -licenseType: Pro DefaultImporter: + externalObjects: {} userData: assetBundleName: assetBundleVariant: diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/SampleModelList.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/SampleModelList.cs new file mode 100644 index 000000000..7efd839cf --- /dev/null +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/SampleModelList.cs @@ -0,0 +1,45 @@ +using UnityEngine; +using UnityGLTF; + +public class SampleModelList : MonoBehaviour +{ + public static string LoaderFieldName => nameof(loader); + public static string PathRootFieldName => nameof(pathRoot); + public static string ManifestRelativePathFieldName => nameof(manifestRelativePath); + public static string ModelRelativePathFieldName => nameof(modelRelativePath); + public static string LoadThisFrameFieldName => nameof(loadThisFrame); + + [SerializeField] + private GLTFComponent loader = null; + + [SerializeField] + private string pathRoot = "http://localhost:8080/glTF-Sample-Models/2.0/"; + +// Disable "unused private field" because it is accessed by SampleModelListInspector using serialization. +#pragma warning disable 414 + [SerializeField] + private string manifestRelativePath = "model-index.json"; +#pragma warning restore 414 + + [SerializeField] + private string modelRelativePath = null; + + [SerializeField] + private bool loadThisFrame = false; + + private async void Update() + { + if (loadThisFrame) + { + loadThisFrame = false; + + var path = pathRoot + modelRelativePath; + if (loader.LastLoadedScene != null) + { + Destroy(loader.LastLoadedScene); + } + loader.GLTFUri = path; + await loader.Load(); + } + } +} diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/SampleModelList.cs.meta b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/SampleModelList.cs.meta new file mode 100644 index 000000000..ba6d16c48 --- /dev/null +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/SampleModelList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: df99c459245b3cd40be06aca24a19170 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/UnityGLTFTests.asmdef b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/UnityGLTFTests.asmdef new file mode 100644 index 000000000..f5674c3bd --- /dev/null +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/UnityGLTFTests.asmdef @@ -0,0 +1,17 @@ +{ + "name": "UnityGLTFTests", + "references": [ + "UnityGLTFScripts", + "UnityGLTFEditor" + ], + "optionalUnityReferences": [ + "TestAssemblies" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [] +} \ No newline at end of file diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/UnityGLTFTests.asmdef.meta b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/UnityGLTFTests.asmdef.meta new file mode 100644 index 000000000..ff76efede --- /dev/null +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/Tests/UnityGLTFTests.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e5407060e0b39404cacbd1741581df2b +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/UniformMaps/MetalRoughMap.cs b/UnityGLTF/Assets/UnityGLTF/Scripts/UniformMaps/MetalRoughMap.cs index e886d3eca..f2e1c5a68 100644 --- a/UnityGLTF/Assets/UnityGLTF/Scripts/UniformMaps/MetalRoughMap.cs +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/UniformMaps/MetalRoughMap.cs @@ -86,6 +86,12 @@ public override int MetallicRoughnessXTexCoord set { return; } } + public override double RoughnessFactor + { + get { return _material.GetFloat("_Glossiness"); } + set { _material.SetFloat("_Glossiness", (float)value); } + } + public override IUniformMap Clone() { var copy = new MetalRoughMap(new Material(_material)); diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/UnityGLTFScripts.asmdef b/UnityGLTF/Assets/UnityGLTF/Scripts/UnityGLTFScripts.asmdef new file mode 100644 index 000000000..d949e7774 --- /dev/null +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/UnityGLTFScripts.asmdef @@ -0,0 +1,3 @@ +{ + "name": "UnityGLTFScripts" +} diff --git a/UnityGLTF/Assets/UnityGLTF/Scripts/UnityGLTFScripts.asmdef.meta b/UnityGLTF/Assets/UnityGLTF/Scripts/UnityGLTFScripts.asmdef.meta new file mode 100644 index 000000000..5ef7d0474 --- /dev/null +++ b/UnityGLTF/Assets/UnityGLTF/Scripts/UnityGLTFScripts.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 18d18f811ba286c49814567a3cfba688 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/scripts/export-upm-package.sh b/scripts/export-upm-package.sh index d1fcc202b..70ce44cd3 100644 --- a/scripts/export-upm-package.sh +++ b/scripts/export-upm-package.sh @@ -1,16 +1,41 @@ -#! /bin/sh +#! /bin/bash project_path=$(pwd)/UnityGLTF log_file=$(pwd)/build/unity-mac.log cached_folder=$(pwd) upm_name=org.khronos.UnityGLTF +echo "##vso[task.setvariable variable=UPM_NAME]$upm_name" upm_src_folder_path=$(pwd)/UnityGLTF/Assets/UnityGLTF upm_manifest_path=$(pwd)/scripts/package.json upm_staging_path=$(pwd)/current-package/$upm_name +upm_staging_UWP_plugins_path=$upm_staging_path/UnityGLTF/Plugins/uap10.0.10586 upm_zip_export_path=$(pwd)/current-package/$upm_name.zip upm_targz_export_path=$(pwd)/current-package/$upm_name.tar.gz +if [[ $BUILD_SOURCEBRANCH == *"refs/tags"* ]]; then + echo "Detected refs/tags in $BUILD_SOURCEBRANCH so this must be a tagged release build." + # Splits the string with "refs/tags", takes the second value and then + # swaps out any slashes for underscores + GIT_TAG=$(echo $BUILD_SOURCEBRANCH | awk -F'refs/tags/' '{print $2}' | tr '/' '_') + echo "Setting GIT_TAG variable to: $GIT_TAG" + echo "##vso[task.setvariable variable=GIT_TAG]$GIT_TAG" +else + echo "Did not detect refs/tags in $BUILD_SOURCEBRANCH so skipping GIT_TAG variable set" +fi + +# msbuild spits out every single dependency dll for UWP +# These are the only files that are needed by the UPM package for Unity 2018.3+ +# Including all the files in the UWP plugin directory causes name collision errors when +# building for UWP in Unity +upm_UWP_Plugins=( + "GLTFSerialization.dll" + "GLTFSerialization.dll.meta" + "GLTFSerialization.pdb" + "Newtonsoft.Json.dll" + "Newtonsoft.Json.dll.meta" +) + error_code=0 echo $upm_name echo $upm_src_folder_path @@ -28,14 +53,11 @@ cp -r $upm_src_folder_path $upm_staging_path echo "Changing to $upm_staging_path folder" cd $upm_staging_path -echo "Creating .zip of UPM package" -sudo zip -r $upm_zip_export_path ./ - -echo "Creating .tar.gz of UPM package" -tar -zcvf $upm_targz_export_path ./ - -echo "Changing back to original folder $cached_folder" -cd $cached_folder +echo "Cleaning out UWP plugin DLLs that are not needed for Unity2018.3+" +find $upm_staging_UWP_plugins_path -maxdepth 1 -type f | grep -vE "$(IFS=\| && echo "${upm_UWP_Plugins[*]}")" | xargs rm -echo "Finishing with code $error_code" -exit $error_code \ No newline at end of file +echo "Files left in $upm_staging_UWP_plugins_path" +for entry in "$upm_staging_UWP_plugins_path"/* +do + echo "$entry" +done \ No newline at end of file