diff --git a/.gitignore b/.gitignore index bc36673..b0055c5 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ # Visual Studio 2015 cache directory /.vs/ +/.vscode/ # Autogenerated VS/MD/Consulo solution and project files ExportedObj/ diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 4edd970..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "files.exclude": - { - "**/.DS_Store":true, - "**/.git":true, - "**/.gitignore":true, - "**/.gitmodules":true, - "**/*.booproj":true, - "**/*.pidb":true, - "**/*.suo":true, - "**/*.user":true, - "**/*.userprefs":true, - "**/*.unityproj":true, - "**/*.dll":true, - "**/*.exe":true, - "**/*.pdf":true, - "**/*.mid":true, - "**/*.midi":true, - "**/*.wav":true, - "**/*.gif":true, - "**/*.ico":true, - "**/*.jpg":true, - "**/*.jpeg":true, - "**/*.png":true, - "**/*.psd":true, - "**/*.tga":true, - "**/*.tif":true, - "**/*.tiff":true, - "**/*.3ds":true, - "**/*.3DS":true, - "**/*.fbx":true, - "**/*.FBX":true, - "**/*.lxo":true, - "**/*.LXO":true, - "**/*.ma":true, - "**/*.MA":true, - "**/*.obj":true, - "**/*.OBJ":true, - "**/*.asset":true, - "**/*.cubemap":true, - "**/*.flare":true, - "**/*.mat":true, - "**/*.meta":true, - "**/*.prefab":true, - "**/*.unity":true, - "build/":true, - "Build/":true, - "Library/":true, - "library/":true, - "obj/":true, - "Obj/":true, - "ProjectSettings/":true, - "temp/":true, - "Temp/":true - } -} \ No newline at end of file diff --git a/Assets/Scenes/ui animation Sample Scene.unity b/Assets/Scenes/ui animation Sample Scene.unity new file mode 100644 index 0000000..45734bf --- /dev/null +++ b/Assets/Scenes/ui animation Sample Scene.unity @@ -0,0 +1,1712 @@ +%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: 11 + m_GIWorkflowMode: 1 + 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: 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_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 + m_NavMeshData: {fileID: 0} +--- !u!1 &60103456 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 60103457} + - component: {fileID: 60103461} + - component: {fileID: 60103460} + - component: {fileID: 60103458} + m_Layer: 5 + m_Name: Helicopter grow effect + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &60103457 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 60103456} + 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: 65850448} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 600, y: 250} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &60103458 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 60103456} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 494ccccf65c01594b87c46d7e6a1f966, type: 3} + m_Name: + m_EditorClassIdentifier: + m_desiredScale: 1 + m_timeToReachDesiredScale: 2 + m_rotationSpeed: 5 + m_rotationAngle: 35 +--- !u!114 &60103460 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 60103456} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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: 100 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 100 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Helicopter Grow Effect +--- !u!222 &60103461 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 60103456} +--- !u!1 &65850444 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 65850448} + - component: {fileID: 65850447} + - component: {fileID: 65850446} + - component: {fileID: 65850445} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &65850445 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 65850444} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &65850446 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 65850444} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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 &65850447 +Canvas: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 65850444} + 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 &65850448 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 65850444} + 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: 1549637274} + - {fileID: 60103457} + - {fileID: 1326669243} + - {fileID: 647913274} + - {fileID: 1105015894} + - {fileID: 1170391614} + - {fileID: 862420478} + - {fileID: 1669247682} + m_Father: {fileID: 0} + m_RootOrder: 2 + 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!1 &523868528 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 523868533} + - component: {fileID: 523868532} + - component: {fileID: 523868531} + - component: {fileID: 523868530} + - component: {fileID: 523868529} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &523868529 +AudioListener: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 523868528} + m_Enabled: 1 +--- !u!124 &523868530 +Behaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 523868528} + m_Enabled: 1 +--- !u!92 &523868531 +Behaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 523868528} + m_Enabled: 1 +--- !u!20 &523868532 +Camera: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 523868528} + 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: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + 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 &523868533 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 523868528} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + 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 &588481442 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 588481443} + - component: {fileID: 588481445} + - component: {fileID: 588481444} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &588481443 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 588481442} + 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: 1669247682} + 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 &588481444 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 588481442} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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: Next +--- !u!222 &588481445 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 588481442} +--- !u!1 &647913273 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 647913274} + - component: {fileID: 647913277} + - component: {fileID: 647913276} + - component: {fileID: 647913275} + m_Layer: 5 + m_Name: Lerp From Offset + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &647913274 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 647913273} + 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: 65850448} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 600, y: 250} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &647913275 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 647913273} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8a8c268e33662234199c5b926b7dfd5b, type: 3} + m_Name: + m_EditorClassIdentifier: + m_effect: 4 + m_offsetDirection: {x: 100, y: 100, z: 0} + m_offsetDistance: 100 + m_timeToReachPosition: 1.5 + m_delayStart: 0 +--- !u!114 &647913276 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 647913273} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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: 100 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 100 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Lerp From Offset +--- !u!222 &647913277 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 647913273} +--- !u!1 &764075908 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 764075909} + - component: {fileID: 764075911} + - component: {fileID: 764075910} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &764075909 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 764075908} + 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: 1105015894} + 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 &764075910 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 764075908} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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: Next +--- !u!222 &764075911 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 764075908} +--- !u!1 &862420474 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 862420478} + - component: {fileID: 862420477} + - component: {fileID: 862420476} + - component: {fileID: 862420475} + m_Layer: 5 + m_Name: ImageFadeToLerp + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!114 &862420475 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 862420474} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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: 862420476} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1326669242} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 647913273} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + - m_Target: {fileID: 862420474} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1669247681} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &862420476 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 862420474} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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 &862420477 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 862420474} +--- !u!224 &862420478 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 862420474} + 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: 1392838399} + m_Father: {fileID: 65850448} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 200, y: -200} + m_SizeDelta: {x: 200, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &1105015893 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1105015894} + - component: {fileID: 1105015897} + - component: {fileID: 1105015896} + - component: {fileID: 1105015895} + m_Layer: 5 + m_Name: GrowEffectToHelicopter + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1105015894 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1105015893} + 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: 764075909} + m_Father: {fileID: 65850448} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 200, y: -200} + m_SizeDelta: {x: 200, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1105015895 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1105015893} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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: 1105015896} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1549637273} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 60103456} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + - m_Target: {fileID: 1170391613} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + - m_Target: {fileID: 1105015893} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1105015896 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1105015893} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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 &1105015897 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1105015893} +--- !u!1 &1170391613 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1170391614} + - component: {fileID: 1170391617} + - component: {fileID: 1170391616} + - component: {fileID: 1170391615} + m_Layer: 5 + m_Name: HelicopterToImageFade + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &1170391614 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1170391613} + 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: 1851853257} + m_Father: {fileID: 65850448} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 200, y: -200} + m_SizeDelta: {x: 200, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1170391615 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1170391613} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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: 1170391616} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 60103456} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1326669242} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + - m_Target: {fileID: 1170391613} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 862420474} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1170391616 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1170391613} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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 &1170391617 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1170391613} +--- !u!1 &1326669242 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1326669243} + - component: {fileID: 1326669246} + - component: {fileID: 1326669245} + - component: {fileID: 1326669244} + m_Layer: 5 + m_Name: Image Fade + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &1326669243 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1326669242} + 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: 65850448} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 100, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1326669244 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1326669242} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9b6641416af12354c82ba88e2c919780, type: 3} + m_Name: + m_EditorClassIdentifier: + m_timeToFade: 1.5 + m_delayTimeToStart: 0 + m_isFadingIn: 1 + m_doesHaveChildText: 0 +--- !u!114 &1326669245 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1326669242} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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 &1326669246 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1326669242} +--- !u!1 &1392838398 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1392838399} + - component: {fileID: 1392838401} + - component: {fileID: 1392838400} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1392838399 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1392838398} + 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: 862420478} + 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 &1392838400 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1392838398} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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: Next +--- !u!222 &1392838401 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1392838398} +--- !u!1 &1453411760 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1453411762} + - component: {fileID: 1453411761} + 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 &1453411761 +Light: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1453411760} + m_Enabled: 1 + serializedVersion: 8 + m_Type: 1 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + 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_FalloffTable: + m_Table[0]: 0 + m_Table[1]: 0 + m_Table[2]: 0 + m_Table[3]: 0 + m_Table[4]: 0 + m_Table[5]: 0 + m_Table[6]: 0 + m_Table[7]: 0 + m_Table[8]: 0 + m_Table[9]: 0 + m_Table[10]: 0 + m_Table[11]: 0 + m_Table[12]: 0 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1453411762 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1453411760} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &1549637273 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1549637274} + - component: {fileID: 1549637277} + - component: {fileID: 1549637276} + - component: {fileID: 1549637275} + m_Layer: 5 + m_Name: Grow Effect + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1549637274 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1549637273} + 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: 65850448} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 600, y: 250} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1549637275 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1549637273} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 130f33757f672504992a0c2e741afbba, type: 3} + m_Name: + m_EditorClassIdentifier: + m_desiredScale: 1 + m_timeToReachDesiredScale: 2 + m_timeToDelayStart: 0 + m_interpolationEffect: 1 +--- !u!114 &1549637276 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1549637273} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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: 100 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 1 + m_MaxSize: 100 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Grow Effect +--- !u!222 &1549637277 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1549637273} +--- !u!1 &1560749332 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1560749335} + - component: {fileID: 1560749334} + - component: {fileID: 1560749333} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1560749333 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1560749332} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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 &1560749334 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1560749332} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1560749335 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1560749332} + 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: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1669247681 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1669247682} + - component: {fileID: 1669247685} + - component: {fileID: 1669247684} + - component: {fileID: 1669247683} + m_Layer: 5 + m_Name: LerpToGrow + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!224 &1669247682 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1669247681} + 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: 588481443} + m_Father: {fileID: 65850448} + m_RootOrder: 7 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 200, y: -200} + m_SizeDelta: {x: 200, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1669247683 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1669247681} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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: 1669247684} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 647913273} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1549637273} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + - m_Target: {fileID: 1669247681} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1105015893} + m_MethodName: SetActive + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1669247684 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1669247681} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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 &1669247685 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1669247681} +--- !u!1 &1851853256 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1851853257} + - component: {fileID: 1851853259} + - component: {fileID: 1851853258} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1851853257 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1851853256} + 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: 1170391614} + 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 &1851853258 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1851853256} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, 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: Next +--- !u!222 &1851853259 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1851853256} diff --git a/Assets/Scenes/ui animation Sample Scene.unity.meta b/Assets/Scenes/ui animation Sample Scene.unity.meta new file mode 100644 index 0000000..4048b51 --- /dev/null +++ b/Assets/Scenes/ui animation Sample Scene.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2145e601083d97c4ba64d70455d21a11 +timeCreated: 1594958189 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/2D/Colliders/ScreenEdgeColliders.cs b/Assets/Scripts/2D/Colliders/ScreenEdgeColliders.cs index bf94311..a3ae1c5 100644 --- a/Assets/Scripts/2D/Colliders/ScreenEdgeColliders.cs +++ b/Assets/Scripts/2D/Colliders/ScreenEdgeColliders.cs @@ -1,35 +1,74 @@ // adds EdgeCollider2D colliders to screen edges // only works with orthographic camera +//Includes two different ways of implementation into your project +//One is a method that uses cached fields on Awake() that requires this entire class but is more slightly more efficient (should use this if you plan to use the method in Update()) +//The other is a standalone method that doesn't need the rest of the class and can be copy-pasted directly into any project but is slightly less efficient + using UnityEngine; -using System.Collections; namespace UnityLibrary { - public class ScreenEdgeColliders : MonoBehaviour - { - void Awake () + public class ScreenEdgeColliders : MonoBehaviour { - AddCollider(); - } + private Camera cam; + private EdgeCollider2D edge; + private Vector2[] edgePoints; - void AddCollider () - { - if (Camera.main==null) {Debug.LogError("Camera.main not found, failed to create edge colliders"); return;} + void Awake() + { + if (Camera.main == null) Debug.LogError("Camera.main not found, failed to create edge colliders"); + else cam = Camera.main; + + if (!cam.orthographic) Debug.LogError("Camera.main is not Orthographic, failed to create edge colliders"); + + // add or use existing EdgeCollider2D + edge = GetComponent() == null ? gameObject.AddComponent() : GetComponent(); + + edgePoints = new Vector2[5]; + + AddCollider(); + } + + //Use this if you're okay with using the global fields and code in Awake() (more efficient) + //You can just ignore/delete StandaloneAddCollider() if thats the case + void AddCollider() + { + //Vector2's for the corners of the screen + Vector2 bottomLeft = cam.ScreenToWorldPoint(new Vector3(0, 0, cam.nearClipPlane)); + Vector2 topRight = cam.ScreenToWorldPoint(new Vector3(cam.pixelWidth, cam.pixelHeight, cam.nearClipPlane)); + Vector2 topLeft = new Vector2(bottomLeft.x, topRight.y); + Vector2 bottomRight = new Vector2(topRight.x, bottomLeft.y); + + //Update Vector2 array for edge collider + edgePoints[0] = bottomLeft; + edgePoints[1] = topLeft; + edgePoints[2] = topRight; + edgePoints[3] = bottomRight; + edgePoints[4] = bottomLeft; + + edge.points = edgePoints; + } + + //Use this if you want a single function to handle everything (less efficient) + //You can just ignore/delete the rest of this class if thats the case + void StandaloneAddCollider() + { + if (Camera.main == null) { Debug.LogError("Camera.main not found, failed to create edge colliders"); return; } - var cam = Camera.main; - if (!cam.orthographic) {Debug.LogError("Camera.main is not Orthographic, failed to create edge colliders"); return;} + var cam = Camera.main; + if (!cam.orthographic) { Debug.LogError("Camera.main is not Orthographic, failed to create edge colliders"); return; } - var bottomLeft = (Vector2)cam.ScreenToWorldPoint(new Vector3(0, 0, cam.nearClipPlane)); - var topLeft = (Vector2)cam.ScreenToWorldPoint(new Vector3(0, cam.pixelHeight, cam.nearClipPlane)); - var topRight = (Vector2)cam.ScreenToWorldPoint(new Vector3(cam.pixelWidth, cam.pixelHeight, cam.nearClipPlane)); - var bottomRight = (Vector2)cam.ScreenToWorldPoint(new Vector3(cam.pixelWidth, 0, cam.nearClipPlane)); + Vector2 bottomLeft = cam.ScreenToWorldPoint(new Vector3(0, 0, cam.nearClipPlane)); + Vector2 topRight = cam.ScreenToWorldPoint(new Vector3(cam.pixelWidth, cam.pixelHeight, cam.nearClipPlane)); + Vector2 topLeft = new Vector2(bottomLeft.x, topRight.y); + Vector2 bottomRight = new Vector2(topRight.x, bottomLeft.y); - // add or use existing EdgeCollider2D - var edge = GetComponent()==null?gameObject.AddComponent():GetComponent(); + // add or use existing EdgeCollider2D + var edge = GetComponent() == null ? gameObject.AddComponent() : GetComponent(); - var edgePoints = new [] {bottomLeft,topLeft,topRight,bottomRight, bottomLeft}; - edge.points = edgePoints; + var edgePoints = new[] { bottomLeft, topLeft, topRight, bottomRight, bottomLeft }; + edge.points = edgePoints; + } } - } } diff --git a/Assets/Scripts/2D/Geometry/Triangle2D.cs b/Assets/Scripts/2D/Geometry/Triangle2D.cs new file mode 100644 index 0000000..6d16785 --- /dev/null +++ b/Assets/Scripts/2D/Geometry/Triangle2D.cs @@ -0,0 +1,67 @@ +using UnityEngine; + +namespace UnityLibrary +{ + // if you need to run collision checks within a triangular area, the easiest + // way to do that in Unity is to use a polygon collider. this is not very + // performant. this class allows you to run those collision checks without + // the performance overhead. + + public class Triangle2D + { + Vector2[] vertices = new Vector2[3]; + + public Triangle2D(Vector2 v1, Vector2 v2, Vector2 v3) + { + Update(v1, v2, v3); + } + + // update triangle by defining all its vertices + public void Update(Vector2 v1, Vector2 v2, Vector2 v3) + { + vertices[0] = v1; + vertices[1] = v2; + vertices[2] = v3; + } + + // update triangle by redefining its origin (remaining points update relative to that) + public void Update(Vector2 v1) + { + Vector2 delta = v1 - vertices[0]; + vertices[0] = v1; + vertices[1] += delta; + vertices[2] += delta; + } + + // update triangle with rotation and pivot point + public void Update(Vector2 v1, Vector2 v2, Vector2 v3, float rotation, Vector2 pivot) + { + vertices[0] = v1.Rotate(rotation, pivot); + vertices[1] = v2.Rotate(rotation, pivot); + vertices[2] = v3.Rotate(rotation, pivot); + } + + float Sign(Vector2 p1, Vector2 p2, Vector2 p3) + { + return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y); + } + + public bool Contains(Vector2 pt, bool debug = false) + { + float d1, d2, d3; + bool has_neg, has_pos; + + d1 = Sign(pt, vertices[0], vertices[1]); + d2 = Sign(pt, vertices[1], vertices[2]); + d3 = Sign(pt, vertices[2], vertices[0]); + + has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0); + has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0); + + bool contains = ! (has_neg && has_pos); + + return contains; + } + } +} + diff --git a/Assets/Scripts/2D/Geometry/Triangle2D.cs.meta b/Assets/Scripts/2D/Geometry/Triangle2D.cs.meta new file mode 100644 index 0000000..db09c09 --- /dev/null +++ b/Assets/Scripts/2D/Geometry/Triangle2D.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5b3d23802c4b0df4db68d12d425fb251 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/AssetBundles/AssetBundleLoader.cs b/Assets/Scripts/AssetBundles/AssetBundleLoader.cs index 215d6de..db53c54 100644 --- a/Assets/Scripts/AssetBundles/AssetBundleLoader.cs +++ b/Assets/Scripts/AssetBundles/AssetBundleLoader.cs @@ -2,47 +2,34 @@ using UnityEngine; using UnityEngine.Networking; -// AssetBundle cache checker & loader with caching -// worsk by loading .manifest file from server and parsing hash string from it - namespace UnityLibrary { public class AssetBundleLoader : MonoBehaviour { public string assetBundleURL = "http://localhost/bundle"; + private string bundleName = "bundle"; void Start() { - //StartCoroutine(DownloadAndCache(assetBundleURL)); + StartCoroutine(DownloadAndCache(assetBundleURL)); } - /// - /// load assetbundle manifest, check hash, load actual bundle with hash parameter to use caching - /// instantiate gameobject - /// - /// full url to assetbundle file - /// optional parameter to access specific asset from assetbundle - /// IEnumerator DownloadAndCache(string bundleURL, string assetName = "") { - // Wait for the Caching system to be ready while (!Caching.ready) { yield return null; } - // if you want to always load from server, can clear cache first - // Caching.CleanCache(); + // Clear cache for previous versions of the asset bundle + Caching.ClearOtherCachedVersions(bundleName, Hash128.Parse("0")); - // get current bundle hash from server, random value added to avoid caching UnityWebRequest www = UnityWebRequest.Get(bundleURL + ".manifest?r=" + (Random.value * 9999999)); - Debug.Log("Loading manifest:" + bundleURL + ".manifest"); + Debug.Log("Loading manifest: " + bundleURL + ".manifest"); - // wait for load to finish - yield return www.Send(); + yield return www.SendWebRequest(); - // if received error, exit - if (www.isNetworkError == true) + if (www.isNetworkError) { Debug.LogError("www error: " + www.error); www.Dispose(); @@ -50,44 +37,39 @@ IEnumerator DownloadAndCache(string bundleURL, string assetName = "") yield break; } - // create empty hash string - Hash128 hashString = (default(Hash128));// new Hash128(0, 0, 0, 0); + Hash128 hashString = default(Hash128); - // check if received data contains 'ManifestFileVersion' if (www.downloadHandler.text.Contains("ManifestFileVersion")) { - // extract hash string from the received data, TODO should add some error checking here var hashRow = www.downloadHandler.text.ToString().Split("\n".ToCharArray())[5]; hashString = Hash128.Parse(hashRow.Split(':')[1].Trim()); - if (hashString.isValid == true) + if (hashString.isValid) { - // we can check if there is cached version or not - if (Caching.IsVersionCached(bundleURL, hashString) == true) + if (Caching.IsVersionCached(bundleURL, hashString)) { Debug.Log("Bundle with this hash is already cached!"); - } else + } + else { - Debug.Log("No cached version founded for this hash.."); + Debug.Log("No cached version found for this hash.."); } - } else + } + else { - // invalid loaded hash, just try loading latest bundle - Debug.LogError("Invalid hash:" + hashString); + Debug.LogError("Invalid hash: " + hashString); yield break; } - - } else + } + else { Debug.LogError("Manifest doesn't contain string 'ManifestFileVersion': " + bundleURL + ".manifest"); yield break; } - // now download the actual bundle, with hashString parameter it uses cached version if available - www = UnityWebRequest.GetAssetBundle(bundleURL + "?r=" + (Random.value * 9999999), hashString, 0); + www = UnityWebRequestAssetBundle.GetAssetBundle(bundleURL + "?r=" + (Random.value * 9999999), hashString, 0); - // wait for load to finish - yield return www.Send(); + yield return www.SendWebRequest(); if (www.error != null) { @@ -97,42 +79,26 @@ IEnumerator DownloadAndCache(string bundleURL, string assetName = "") yield break; } - // get bundle from downloadhandler AssetBundle bundle = ((DownloadHandlerAssetBundle)www.downloadHandler).assetBundle; - GameObject bundlePrefab = null; - // if no asset name is given, take the first/main asset if (assetName == "") { bundlePrefab = (GameObject)bundle.LoadAsset(bundle.GetAllAssetNames()[0]); - } else - { // use asset name to access inside bundle + } + else + { bundlePrefab = (GameObject)bundle.LoadAsset(assetName); } - // if we got something out if (bundlePrefab != null) { - - // instantiate at 0,0,0 and without rotation Instantiate(bundlePrefab, Vector3.zero, Quaternion.identity); - - /* - // fix pink shaders, NOTE: not always needed.. - foreach (Renderer r in go.GetComponentsInChildren(includeInactive: true)) - { - // FIXME: creates multiple materials, not good - var material = Shader.Find(r.material.shader.name); - r.material.shader = null; - r.material.shader = material; - }*/ } www.Dispose(); www = null; - // try to cleanup memory Resources.UnloadUnusedAssets(); bundle.Unload(false); bundle = null; diff --git a/Assets/Scripts/Camera/AutoResolution.cs b/Assets/Scripts/Camera/AutoResolution.cs new file mode 100644 index 0000000..87fd874 --- /dev/null +++ b/Assets/Scripts/Camera/AutoResolution.cs @@ -0,0 +1,58 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class AutoResolution : MonoBehaviour +{ + public int setWidth = 1440; + public int setHeight = 2560; + + private void Start() + { + // Get the main camera and its current dimensions + Camera camera = Camera.main; + Rect rect = camera.rect; + + // Calculate the scale height and width of the screen + float scaleHeight = ((float)Screen.width / Screen.height) / ((float)9 / 16); + float scaleWidth = 1f / scaleHeight; + + // Adjust the camera's dimensions based on the scale height and width + if (scaleHeight < 1) + { + rect.height = scaleHeight; + rect.y = (1f - scaleHeight) / 2f; + } + else + { + rect.width = scaleWidth; + rect.x = (1f - scaleWidth) / 2f; + } + + camera.rect = rect; + + SetResolution(); + } + + public void SetResolution() + { + // Get the current device's screen dimensions + int deviceWidth = Screen.width; + int deviceHeight = Screen.height; + + // Set the screen resolution to the desired dimensions, while maintaining aspect ratio + Screen.SetResolution(setWidth, (int)(((float)deviceHeight / deviceWidth) * setWidth), true); + + // Adjust the camera's dimensions based on the new resolution + if ((float)setWidth / setHeight < (float)deviceWidth / deviceHeight) + { + float newWidth = ((float)setWidth / setHeight) / ((float)deviceWidth / deviceHeight); + Camera.main.rect = new Rect((1f - newWidth) / 2f, 0f, newWidth, 1f); + } + else + { + float newHeight = ((float)deviceWidth / deviceHeight) / ((float)setWidth / setHeight); + Camera.main.rect = new Rect(0f, (1f - newHeight) / 2f, 1f, newHeight); // 새로운 Rect 적용 + } + } +} diff --git a/Assets/Scripts/Camera/CameraShake.cs b/Assets/Scripts/Camera/CameraShake.cs index d8814bb..48a88e6 100644 --- a/Assets/Scripts/Camera/CameraShake.cs +++ b/Assets/Scripts/Camera/CameraShake.cs @@ -1,58 +1,66 @@ using UnityEngine; using System.Collections; -// usage: attach this script into camera, call Shake() method to start -// source: http://answers.unity3d.com/answers/992509/view.html +/* + * Usage: attach this script to a camera or any other object, call Shake() method to start shaking it +* To turn off, change influence to zero +* Attach the camera to an empty game object to keep its local position and rotation +*/ namespace UnityLibrary { public class CameraShake : MonoBehaviour { - public bool shakePosition; - public bool shakeRotation; - - public float shakeIntensityMin = 0.1f; - public float shakeIntensityMax = 0.5f; - public float shakeDecay = 0.02f; + [Range(0f, 1f)] + public float shakeInfluence = 0.5f; + [Range(0f, 10f)] + public float rotationInfluence = 0f; private Vector3 OriginalPos; private Quaternion OriginalRot; - private bool isShakeRunning = false; - // call this function to start shaking - public void Shake() +/// +/// Will shake the camera with a random value between minIntensity and maxIntensity for duration +/// +/// +/// +/// + public void Shake(float minIntensity, float maxIntensity, float duration) { + if (isShakeRunning) + return; + OriginalPos = transform.position; OriginalRot = transform.rotation; - StartCoroutine("ProcessShake"); + + float shake = Random.Range(minIntensity, maxIntensity) * shakeInfluence; + duration *= shakeInfluence; + + StartCoroutine(ProcessShake(shake, duration)); } - IEnumerator ProcessShake() + IEnumerator ProcessShake(float shake, float duration) { - if (!isShakeRunning) + isShakeRunning = true; + float countdown = duration; + float initialShake = shake; + + while (countdown > 0) { - isShakeRunning = true; - float currentShakeIntensity = Random.Range(shakeIntensityMin, shakeIntensityMax); - - while (currentShakeIntensity > 0) - { - if (shakePosition) - { - transform.position = OriginalPos + Random.insideUnitSphere * currentShakeIntensity; - } - if (shakeRotation) - { - transform.rotation = new Quaternion(OriginalRot.x + Random.Range(-currentShakeIntensity, currentShakeIntensity) * .2f, - OriginalRot.y + Random.Range(-currentShakeIntensity, currentShakeIntensity) * .2f, - OriginalRot.z + Random.Range(-currentShakeIntensity, currentShakeIntensity) * .2f, - OriginalRot.w + Random.Range(-currentShakeIntensity, currentShakeIntensity) * .2f); - } - currentShakeIntensity -= shakeDecay; - yield return null; - } - - isShakeRunning = false; + countdown -= Time.deltaTime; + + float lerpIntensity = countdown / duration; + shake = Mathf.Lerp(0f, initialShake, lerpIntensity); + + transform.position = OriginalPos + Random.insideUnitSphere * shake; + transform.rotation = Quaternion.Euler(OriginalRot.eulerAngles + Random.insideUnitSphere * shake * rotationInfluence); + + yield return null; } + + transform.position = OriginalPos; + transform.rotation = OriginalRot; + isShakeRunning = false; } } } \ No newline at end of file diff --git a/Assets/Scripts/Camera/EditorCardboardCamera.cs b/Assets/Scripts/Camera/EditorCardboardCamera.cs new file mode 100644 index 0000000..c73bd45 --- /dev/null +++ b/Assets/Scripts/Camera/EditorCardboardCamera.cs @@ -0,0 +1,23 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +// editor only Google Carboard VR cam simulation with left alt + mouse + +public class EditorCardboardCamera : MonoBehaviour +{ +#if UNITY_EDITOR + Vector2 rotation = Vector2.zero; + public float speed = 3; + + void Update() + { + if (Input.GetKey(KeyCode.LeftAlt)) + { + rotation.y += Input.GetAxis("Mouse X"); + rotation.x += -Input.GetAxis("Mouse Y"); + transform.eulerAngles = (Vector2)rotation * speed; + } + } +#endif +} diff --git a/Assets/Scripts/Camera/MarrtsSmoothedMouseLook.cs b/Assets/Scripts/Camera/MarrtsSmoothedMouseLook.cs new file mode 100644 index 0000000..c10daf6 --- /dev/null +++ b/Assets/Scripts/Camera/MarrtsSmoothedMouseLook.cs @@ -0,0 +1,208 @@ +using UnityEngine; + +//Marrt's simplest Mouselook for https://forum.unity.com/threads/a-free-simple-smooth-mouselook.73117/page-2#post-4652755 + +namespace UnityLibrary +{ + public class MarrtsSmoothedMouseLook : MonoBehaviour + { + [Header("CameraTransform")] + public Transform targetTrans; + [Header("On/Off & Settings")] + public bool inputActive = true; + public bool controlCursor = false; + [Header("Smoothing")] + public bool byPassSmoothing = false; + public float mLambda = 20F; //higher = less latency but also less smoothing + [Header("Sensitivity")] + public float hSens = 4F; + public float vSens = 4F; + public BufferV2 mouseBuffer = new BufferV2(); + + public enum AxisClampMode { None, Hard, Soft } + + [Header("Restricting Look")] + + public AxisClampMode pitchClamp = AxisClampMode.Soft; + [Range(-180F,180F)] public float pMin = -80F; + [Range(-180F,180F)] public float pMax = 80F; + + + [Header("Yaw should be left None, Message me if you really need this functionality")] + + public AxisClampMode yawClamp = AxisClampMode.None; + [Range(-180F,180F)] public float yMin = -140F; + [Range(-180F,180F)] public float yMax = 140F; + + + + //public bool smoothingDependence = Timescale Framerate + + void Update () + { + //if(Input.GetKeyDown(KeyCode.Space)){inputActive = !inputActive;} + if(controlCursor){ //Cursor Control + if( inputActive && Cursor.lockState != CursorLockMode.Locked) { Cursor.lockState = CursorLockMode.Locked; } + if( !inputActive && Cursor.lockState != CursorLockMode.None) { Cursor.lockState = CursorLockMode.None; } + } + if(!inputActive){ return; } //active? + + //Update input + UpdateMouseBuffer(); + targetTrans.rotation = Quaternion.Euler( mouseBuffer.curAbs ); + } + + //consider late Update for applying the rotation if your game needs it (e.g. if camera parents are rotated in Update for some reason) + void LateUpdate() {} + + private void UpdateMouseBuffer() + { + + float rawPitchDelta = vSens * -Input.GetAxisRaw("Mouse Y"); + + switch(pitchClamp){ + case AxisClampMode.None: mouseBuffer.target.x += rawPitchDelta; break; + case AxisClampMode.Hard: mouseBuffer.target.x = Mathf.Clamp(mouseBuffer.target.x +rawPitchDelta, pMin, pMax); break; + case AxisClampMode.Soft: mouseBuffer.target.x += SoftPitchClamping.DeltaMod( mouseBuffer.target.x, rawPitchDelta, Mathf.Abs(pMax*0.5F), Mathf.Abs(pMax) ); break; //symetric clamping only for now, max is used + } + + float rawYawDelta = hSens * Input.GetAxisRaw("Mouse X"); + + switch(yawClamp){ + case AxisClampMode.None: mouseBuffer.target.y += rawYawDelta; break; + case AxisClampMode.Hard: mouseBuffer.target.y = Mathf.Clamp(mouseBuffer.target.y +rawYawDelta, yMin, yMax); break; + case AxisClampMode.Soft: Debug.LogWarning("SoftYaw clamp should be implemented with Quaternions to work in every situation"); + mouseBuffer.target.y += SoftPitchClamping.DeltaMod( mouseBuffer.target.y, rawYawDelta, Mathf.Abs(yMax*0.5F), Mathf.Abs(yMax) ); + break; + } + + mouseBuffer.Update( mLambda, Time.deltaTime, byPassSmoothing ); + } + } + + + + + + #region Helpers + [System.Serializable] + public class BufferV2{ + + public BufferV2(){ + this.target = Vector2.zero; + this.buffer = Vector2.zero; + } + public BufferV2( Vector2 targetInit, Vector2 bufferInit ) { + this.target = targetInit; + this.buffer = bufferInit; + } + + /*private*/public Vector2 target; + /*private*/public Vector2 buffer; + + public Vector2 curDelta; //Delta: apply difference from lastBuffer state to current BufferState //get difference between last and new buffer + public Vector2 curAbs; //absolute + + + + /// Update Buffer By supplying new target + public void UpdateByNewTarget( Vector2 newTarget, float dampLambda, float deltaTime ){ + this.target = newTarget; + Update(dampLambda, deltaTime); + } + /// Update Buffer By supplying the rawDelta to the last target + public void UpdateByDelta( Vector2 rawDelta, float dampLambda, float deltaTime ){ + this.target = this.target +rawDelta; //update Target + Update(dampLambda, deltaTime); + } + + /// Update Buffer + public void Update( float dampLambda, float deltaTime, bool byPass = false ){ + Vector2 last = buffer; //last state of Buffer + this.buffer = byPass? target : DampToTargetLambda( buffer, this.target, dampLambda, deltaTime); //damp current to target + this.curDelta = buffer -last; + this.curAbs = buffer; + } + public static Vector2 DampToTargetLambda( Vector2 current, Vector2 target, float lambda, float dt){ + return Vector2. Lerp(current, target, 1F -Mathf.Exp( -lambda *dt) ); + } + } + + + + + public static class SoftPitchClamping{ + public static float DeltaMod( float currentPitch, float delta, float softMax = 45F, float hardMax = 85F ){ + + //doesnt work for input above 90F pitch, unity might invert roll and decrease pitch again + + //transform into -180 to 180 range (allowed input range = 0-360F ) + float wrapped = Wrap.Float( currentPitch, -180F, 180F ); + + float sign = Mathf.Sign( wrapped ); + float absolute = Mathf.Abs ( wrapped ); + + // treat current as mapped value, so unmap it via reversing + // https://rechneronline.de/function-graphs/ + // revert remap: e^((((log(x/45)+1)*45)/45)-1)*45 + // remap: (log(x/45)+1)*45 + + float remapped = absolute; + if( absolute > softMax ){ + // e^ (( (( log( x/45 )+1 )*45 ) /45 ) -1 )*45 + // remapped = Mathf.Exp(( (( Mathf.Log(remapped/softMax)+1F )*softMax ) /softMax) -1F)*softMax ; + remapped = Mathf.Exp(( remapped /softMax) -1F)*softMax ; + //x*0.5+45*0.5 + } + + //apply delta to unmapped, sign needs to be taken into consideration for delta + remapped += (delta *sign); //float raw = remapped +(delta *sign); + + //remap, only needed if exceeding softrange + if( remapped > softMax ){ + // (( log( x/45 )+1 )*45 ) + remapped = (( Mathf.Log(remapped/softMax)+1F )*softMax ); + + //x*0.5+45*0.5 + + } + + remapped *= sign; + remapped = Mathf.Clamp( remapped, -hardMax, +hardMax); + + float newDelta = ( remapped -wrapped ); + + //print( "wrapped\t"+wrapped+" (from:"+currentPitch+")"+"\nremapped\t"+remapped +" (raw :"+raw+")"); + + return newDelta; + // return delta; + } + + public static class Wrap{ + + //can be used to clamp angles from 0-360 to 0-180 by feeding (value,-180,180) + //https://stackoverflow.com/questions/1628386/normalise-orientation-between-0-and-360 + + //Normalizes any number to an arbitrary range + //by assuming the range wraps around when going below min or above max + public static float Float( float value, float start, float end ){ + float width = end - start ; // + float offsetValue = value - start ; // value relative to 0 + + return ( offsetValue - ( Mathf.Floor( offsetValue / width ) * width ) ) + start ; + // + start to reset back to start of original range + } + + //Normalizes any number to an arbitrary range + //by assuming the range wraps around when going below min or above max + public static int Int( int value, int start, int end ){ + int width = end - start ; // + int offsetValue = value - start ; // value relative to 0 + + return ( offsetValue - ( ( offsetValue / width ) * width ) ) + start ; + // + start to reset back to start of original range + } + } + } + #endregion Helpers +} diff --git a/Assets/Scripts/Camera/MarrtsSmoothedMouseLook.cs.meta b/Assets/Scripts/Camera/MarrtsSmoothedMouseLook.cs.meta new file mode 100644 index 0000000..3eccce9 --- /dev/null +++ b/Assets/Scripts/Camera/MarrtsSmoothedMouseLook.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 10e595b96bab7724a99b2b273e92011e +timeCreated: 1594958193 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Camera/MobileCamera.cs b/Assets/Scripts/Camera/MobileCamera.cs new file mode 100644 index 0000000..99fd6f5 --- /dev/null +++ b/Assets/Scripts/Camera/MobileCamera.cs @@ -0,0 +1,135 @@ +// https://forum.unity.com/threads/mobile-touch-to-orbit-pan-and-zoom-camera-without-fix-target-in-one-script.522607/#post-3531342 + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class MobileCamera : MonoBehaviour +{ + public Transform target; + public Vector3 targetOffset; + public float distance = 5.0f; + public float maxDistance = 20; + public float minDistance = .6f; + public float xSpeed = 5.0f; + public float ySpeed = 5.0f; + public int yMinLimit = -80; + public int yMaxLimit = 80; + public float zoomRate = 10.0f; + public float panSpeed = 0.3f; + public float zoomDampening = 5.0f; + + private float xDeg = 0.0f; + private float yDeg = 0.0f; + private float currentDistance; + private float desiredDistance; + private Quaternion currentRotation; + private Quaternion desiredRotation; + private Quaternion rotation; + private Vector3 position; + + private Vector3 FirstPosition; + private Vector3 SecondPosition; + private Vector3 delta; + private Vector3 lastOffset; + private Vector3 lastOffsettemp; + //private Vector3 CameraPosition; + //private Vector3 Targetposition; + //private Vector3 MoveDistance; + + public float offsetSpeed = 0.03f; + + void Start() { Init(); } + void OnEnable() { Init(); } + + public void Init() + { + //If there is no target, create a temporary target at 'distance' from the cameras current viewpoint + if (!target) + { + GameObject go = new GameObject("Cam Target"); + go.transform.position = transform.position + (transform.forward * distance); + target = go.transform; + } + + distance = Vector3.Distance(transform.position, target.position); + currentDistance = distance; + desiredDistance = distance; + + //be sure to grab the current rotations as starting points. + position = transform.position; + rotation = transform.rotation; + currentRotation = transform.rotation; + desiredRotation = transform.rotation; + + //xDeg = Vector3.Angle(Vector3.right, transform.right); + //yDeg = Vector3.Angle(Vector3.up, transform.up); + + xDeg = transform.eulerAngles.y + Vector3.Angle(Vector3.right, transform.right); + yDeg = transform.eulerAngles.x + Vector3.Angle(Vector3.up, transform.up); + + } + + void LateUpdate() + { + // If Control and Alt and Middle button? ZOOM! + if (Input.touchCount == 2) + { + Touch touchZero = Input.GetTouch(0); + Touch touchOne = Input.GetTouch(1); + Vector2 touchZeroPreviousPosition = touchZero.position - touchZero.deltaPosition; + Vector2 touchOnePreviousPosition = touchOne.position - touchOne.deltaPosition; + float prevTouchDeltaMag = (touchZeroPreviousPosition - touchOnePreviousPosition).magnitude; + float TouchDeltaMag = (touchZero.position - touchOne.position).magnitude; + float deltaMagDiff = prevTouchDeltaMag - TouchDeltaMag; + desiredDistance += deltaMagDiff * Time.deltaTime * zoomRate * 0.0025f * Mathf.Abs(desiredDistance); + } + + // If middle mouse and left alt are selected? ORBIT + if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved) + { + Vector2 touchposition = Input.GetTouch(0).deltaPosition; + xDeg += touchposition.x * xSpeed * 0.002f; + yDeg -= touchposition.y * ySpeed * 0.002f; + yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit); + + } + + desiredRotation = Quaternion.Euler(yDeg, xDeg, 0); + currentRotation = transform.rotation; + rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening); + transform.rotation = rotation; + + if (Input.GetMouseButtonDown(1)) + { + FirstPosition = Input.mousePosition; + lastOffset = targetOffset; + } + + if (Input.GetMouseButton(1)) + { + SecondPosition = Input.mousePosition; + delta = SecondPosition - FirstPosition; + targetOffset = lastOffset + transform.right * delta.x * offsetSpeed + transform.up * delta.y * offsetSpeed; + + } + + ////////Orbit Position + // affect the desired Zoom distance if we roll the scrollwheel + desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance); + currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening); + position = target.position - (rotation * Vector3.forward * currentDistance); + position = position - targetOffset; + transform.position = position; + } + + private static float ClampAngle(float angle, float min, float max) + { + if (angle < -360) + angle += 360; + if (angle > 360) + angle -= 360; + return Mathf.Clamp(angle, min, max); + } +} + diff --git a/Assets/Scripts/Camera/PlayerMovement.cs b/Assets/Scripts/Camera/PlayerMovement.cs new file mode 100644 index 0000000..901af41 --- /dev/null +++ b/Assets/Scripts/Camera/PlayerMovement.cs @@ -0,0 +1,41 @@ +using UnityEngine; +using System.Collections.Generic; +using System.Collections; + +//Script for moving a gameObject smoothly +//Usage: Attach the character controller component to the gameobject that you want to move + +namespace UnityLibary +{ + public class PlayerMovement : MonoBehaviour + { + // place the gameobject that you want to move to the controller placeholder + public CharacterController controller; + + public float speed = 5f; + + void Update() + { + float x = Input.GetAxis("Horizontal"); + float z = Input.GetAxis("Vertical"); + + Vector3 move = transform.right * x + transform.forward * z; + + controller.Move(move * speed * Time.deltaTime); + + //Rotate clockwise + if (Input.GetKey(KeyCode.E)) + { + transform.RotateAround(transform.position, Vector3.up, 100 * Time.deltaTime); + } + + // Rotate anticlockwise + if (Input.GetKey(KeyCode.Q)) + { + transform.RotateAround(transform.position, -Vector3.up, 100 * Time.deltaTime); + } + + } + + } +} diff --git a/Assets/Scripts/Camera/PlayerMovement.cs.meta b/Assets/Scripts/Camera/PlayerMovement.cs.meta new file mode 100644 index 0000000..058aaca --- /dev/null +++ b/Assets/Scripts/Camera/PlayerMovement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c1dd692b70ceca4439544f5a72fa7f70 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Camera/SimpleSmoothMouseLookNewInput.cs b/Assets/Scripts/Camera/SimpleSmoothMouseLookNewInput.cs new file mode 100644 index 0000000..2864d24 --- /dev/null +++ b/Assets/Scripts/Camera/SimpleSmoothMouseLookNewInput.cs @@ -0,0 +1,260 @@ +using UnityEngine; +using UnityEngine.InputSystem; + +namespace UnityLibrary +{ + public class SimpleSmoothMouseLookNewInput : MonoBehaviour + { + [Header("Mouse Look")] + [Tooltip("Hold right mouse button down to rotate")] + public bool rotateWithRightMouse = true; + public Vector2 clampInDegrees = new Vector2(360, 180); + public bool lockCursor = false; + public Vector2 sensitivity = new Vector2(2, 2); + public Vector2 smoothing = new Vector2(3, 3); + Vector2 targetDirection; + Vector2 _mouseAbsolute; + Vector2 _smoothMouse; + + [Header("Camera Pan")] + public bool enablePanning = true; + public float panSpeed = 40; + + [Header("Camera Orbit")] + public bool enableOrbit = false; + public KeyCode orbitKey = KeyCode.LeftAlt; + [Tooltip("Set this to -1, if you dont require any mousebutton pressed for orbit")] + public int orbitMouseKey = 2; + public float orbitXSpeed = 400; + public float orbitYSpeed = 400; + Vector3 targetposition; + float orbitDistance = 10.0f; + private float xDeg = 0.0f; + private float yDeg = 0.0f; + + [Header("Camera Zoom")] + public bool scrollZoom = false; + public int zoomRate = 40; + public float zoomDampening = 5.0f; + public KeyCode zoomExtends = KeyCode.F; // whole cloud + + [Header("Camera Fly")] + public float flySpeed = 20; // default speed + public float accelerationRatio = 5; // when shift is pressed + public float slowDownRatio = 0.5f; // when ctrl is pressed + public KeyCode increaseSpeedKey = KeyCode.LeftShift; + public KeyCode decreaseSpeedKey = KeyCode.LeftControl; + public KeyCode upKey = KeyCode.E; + public KeyCode downKey = KeyCode.Q; + public string horizontalAxisKey = "Horizontal"; + public string verticalAxisKey = "Vertical"; + + public bool moveRoot = false; + Transform moveTransform; + + Camera cam; + + void Awake() + { + cam = Camera.main; + + moveTransform = moveRoot ? transform.root : transform; + } + + private void Start() + { + + } + + private void OnEnable() + { + // Set target direction to the camera's initial orientation, NOTE need to do this if you move camera manually elsewhere + targetDirection = transform.localRotation.eulerAngles; + } + + void Update() + { + Framing(); + if (MouseOrbit() == true) return; + MouseLook(); + CameraFly(); + } + + void Framing() + { + + } + + public void GetOrbitTarget() + { + targetposition = transform.forward * orbitDistance; + //orbitDistance = Vector3.Distance(transform.position, targetposition); + } + + + bool MouseOrbit() + { + // early exit, if not enabled, or no key is pressed, or if mousekey is set, but not pressed + if (enableOrbit == false || Input.GetKey(orbitKey) == false || (orbitMouseKey > -1 == true && Input.GetMouseButton(orbitMouseKey) == false)) + { + return false; + } + + orbitDistance += Input.GetAxis("Mouse ScrollWheel") * zoomRate * Time.deltaTime; + + xDeg = (Input.GetAxis("Mouse X") * orbitXSpeed); + yDeg = -(Input.GetAxis("Mouse Y") * orbitYSpeed); + transform.RotateAround(targetposition, Vector3.up, xDeg * Time.deltaTime); + transform.RotateAround(targetposition, transform.right, yDeg * Time.deltaTime); + + targetDirection = transform.rotation.eulerAngles; + + return true; + } + + static float ClampAngle(float angle, float min, float max) + { + if (angle < -360) + angle += 360; + if (angle > 360) + angle -= 360; + return Mathf.Clamp(angle, min, max); + } + + void MouseLook() + { + // Get raw mouse input for a cleaner reading on more sensitive mice. + //var mouseDelta = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y")); + var mouseDelta = Mouse.current.delta.ReadValue() * Time.deltaTime*3; + + // panning with middle moouse button + if (enablePanning == true) + { + //if (Input.GetMouseButton(2)) + if (Mouse.current.middleButton.isPressed) + { + transform.Translate(-mouseDelta * panSpeed * Time.deltaTime, Space.Self); + GetOrbitTarget(); // update orbit target + } + } + + // Ensure the cursor is always locked when set + if (lockCursor == true) Cursor.lockState = CursorLockMode.Locked; + + //if (rotateWithRightMouse == true && !Input.GetMouseButton(1)) return; + if (rotateWithRightMouse == true && !Mouse.current.rightButton.isPressed) return; + + // Allow the script to clamp based on a desired target value. + Quaternion targetOrientation = Quaternion.Euler(targetDirection); + + // Scale input against the sensitivity setting and multiply that against the smoothing value. + mouseDelta = Vector2.Scale(mouseDelta, new Vector2(sensitivity.x * smoothing.x, sensitivity.y * smoothing.y)); + // Interpolate mouse movement over time to apply smoothing delta. + _smoothMouse.x = Mathf.Lerp(_smoothMouse.x, mouseDelta.x, 1f / smoothing.x); + _smoothMouse.y = Mathf.Lerp(_smoothMouse.y, mouseDelta.y, 1f / smoothing.y); + // Find the absolute mouse movement value from point zero. + _mouseAbsolute += _smoothMouse; + + // Clamp and apply the local x value first, so as not to be affected by world transforms. + if (clampInDegrees.x < 360) _mouseAbsolute.x = Mathf.Clamp(_mouseAbsolute.x, -clampInDegrees.x * 0.5f, clampInDegrees.x * 0.5f); + + var xRotation = Quaternion.AngleAxis(-_mouseAbsolute.y, targetOrientation * Vector3.right); + transform.localRotation = xRotation; + + // Then clamp and apply the global y value. + if (clampInDegrees.y < 360) _mouseAbsolute.y = Mathf.Clamp(_mouseAbsolute.y, -clampInDegrees.y * 0.5f, clampInDegrees.y * 0.5f); + + var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, transform.InverseTransformDirection(Vector3.up)); + transform.localRotation *= yRotation; + transform.rotation *= targetOrientation; + } + + void CameraFly() + { + bool moved = false; + // shift was pressed down + //if (Input.GetKeyDown(increaseSpeedKey)) + if (Keyboard.current.leftShiftKey.wasPressedThisFrame) + { + flySpeed *= accelerationRatio; // increase flyspeed + } + + //if (Input.GetKeyUp(increaseSpeedKey)) + if (Keyboard.current.leftShiftKey.wasReleasedThisFrame) + { + flySpeed /= accelerationRatio; // flyspeed back to normal + } + + //if (Input.GetKeyDown(decreaseSpeedKey)) + if (Keyboard.current.leftCtrlKey.wasPressedThisFrame) + { + flySpeed *= slowDownRatio; // decrease flyspeed + } + //if (Input.GetKeyUp(decreaseSpeedKey)) + if (Keyboard.current.leftCtrlKey.wasReleasedThisFrame) + { + flySpeed /= slowDownRatio; // flyspeed back to normal + } + + var vert = -Keyboard.current.sKey.ReadValue() + Keyboard.current.wKey.ReadValue(); + if (vert != 0) + { + moveTransform.Translate(transform.forward * flySpeed * vert * Time.deltaTime, Space.World); + moved = true; + } + + var horz = -Keyboard.current.aKey.ReadValue() + Keyboard.current.dKey.ReadValue(); + if (horz != 0) + { + moveTransform.Translate(transform.right * flySpeed * horz * Time.deltaTime, Space.World); + moved = true; + } + + // annoying in editor as it works from any window +#if !UNITY_EDITOR + if (scrollZoom == true) + { + //if (Input.GetAxis("Mouse ScrollWheel") != 0) + var scrollY = Mouse.current.scroll.ReadValue().y; + if (scrollY != 0) + { + transform.Translate(transform.forward * zoomRate * scrollY * Time.deltaTime, Space.World); + moved = true; + } + } +#endif + + //if (Input.GetKey(upKey)) + if (Keyboard.current.qKey.isPressed) + { + moveTransform.Translate(moveTransform.up * flySpeed * 0.5f * Time.deltaTime, Space.World); + moved = true; + } + //else if (Input.GetKey(downKey)) + else if (Keyboard.current.eKey.isPressed) + { + moveTransform.Translate(-moveTransform.up * flySpeed * 0.5f * Time.deltaTime, Space.World); + moved = true; + } + if (moved == true) GetOrbitTarget(); + } // CameraFly() + + // https://stackoverflow.com/questions/25368259/making-an-object-fit-exactly-inside-the-camera-frustum-in-three-js + public void FocusCameraOnGameObject(Bounds b) + { + var height = b.max.y; + var width = b.max.x - b.min.x; + var vertical_FOV = cam.fieldOfView * (Mathf.PI / 180f); + var aspectRatio = Screen.width / Screen.height; + var horizontal_FOV = 2 * Mathf.Atan(Mathf.Tan(vertical_FOV / 2) * aspectRatio); + var distance_vertical = height / (2 * Mathf.Tan(vertical_FOV / 2)); + var distance_horizontal = width / (2 * Mathf.Tan(horizontal_FOV / 2)); + var z_distance = distance_vertical >= distance_horizontal ? distance_vertical : distance_horizontal; + // current viewdir + var viewDir = transform.forward; + // move camera so that object is in front + cam.transform.position = b.center - viewDir * z_distance * 2; + } + + } // class +} // namespace diff --git a/Assets/Editor.meta b/Assets/Scripts/Docs/Mesh.meta similarity index 67% rename from Assets/Editor.meta rename to Assets/Scripts/Docs/Mesh.meta index 9c21977..836722b 100644 --- a/Assets/Editor.meta +++ b/Assets/Scripts/Docs/Mesh.meta @@ -1,7 +1,7 @@ fileFormatVersion: 2 -guid: 710e084e33216854daedf076c029ff31 +guid: dfe48b7debc5f9c4a9ab9b77ddb37e1a folderAsset: yes -timeCreated: 1501225949 +timeCreated: 1594958191 licenseType: Free DefaultImporter: userData: diff --git a/Assets/Scripts/Docs/Mesh/MeshExample.cs.meta b/Assets/Scripts/Docs/Mesh/MeshExample.cs.meta new file mode 100644 index 0000000..24cd5ab --- /dev/null +++ b/Assets/Scripts/Docs/Mesh/MeshExample.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3292a9e48eeb600418703ec125a8ef82 +timeCreated: 1594958193 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Docs/UnityEngine/CullingGroupExample.cs b/Assets/Scripts/Docs/UnityEngine/CullingGroupExample.cs new file mode 100644 index 0000000..2a5f505 --- /dev/null +++ b/Assets/Scripts/Docs/UnityEngine/CullingGroupExample.cs @@ -0,0 +1,93 @@ +// gets nearby objects using CullingGroup +// Assign this script to some gameobject, that the distance is measured from + +using UnityEngine; + +namespace UnityLibrary +{ + public class CullingGroupExample : MonoBehaviour + { + // just some dummy prefab to spawn (use default sphere for example) + public GameObject prefab; + + // distance to search objects from + public float searchDistance = 3; + + public bool colorInvisibleObjects = false; + + int objectCount = 5000; + + // collection of objects + Renderer[] objects; + CullingGroup cullGroup; + BoundingSphere[] bounds; + + void Start() + { + // create culling group + cullGroup = new CullingGroup(); + cullGroup.targetCamera = Camera.main; + + // measure distance to our transform + cullGroup.SetDistanceReferencePoint(transform); + + // search distance "bands" starts from 0, so index=0 is from 0 to searchDistance + cullGroup.SetBoundingDistances(new float[] { searchDistance, float.PositiveInfinity }); + + bounds = new BoundingSphere[objectCount]; + + // spam random objects + objects = new Renderer[objectCount]; + for (int i = 0; i < objectCount; i++) + { + var pos = Random.insideUnitCircle * 30; + var go = Instantiate(prefab, pos, Quaternion.identity); + objects[i] = go.GetComponent(); + + // collect bounds for objects + var b = new BoundingSphere(); + b.position = go.transform.position; + + // get simple radius..works for our sphere + b.radius = go.GetComponent().mesh.bounds.extents.x; + bounds[i] = b; + } + + // set bounds that we track + cullGroup.SetBoundingSpheres(bounds); + cullGroup.SetBoundingSphereCount(objects.Length); + + // subscribe to event + cullGroup.onStateChanged += StateChanged; + } + + // object state has changed in culling group + void StateChanged(CullingGroupEvent e) + { + if (colorInvisibleObjects == true && e.isVisible == false) + { + objects[e.index].material.color = Color.gray; + return; + } + + // if we are in distance band index 0, that is between 0 to searchDistance + if (e.currentDistance == 0) + { + objects[e.index].material.color = Color.green; + } + else // too far, set color to red + { + objects[e.index].material.color = Color.red; + } + } + + // cleanup + private void OnDestroy() + { + cullGroup.onStateChanged -= StateChanged; + cullGroup.Dispose(); + cullGroup = null; + } + + } +} diff --git a/Assets/Scripts/Docs/UnityEngine/CullingGroupExample.cs.meta b/Assets/Scripts/Docs/UnityEngine/CullingGroupExample.cs.meta new file mode 100644 index 0000000..3f8f80c --- /dev/null +++ b/Assets/Scripts/Docs/UnityEngine/CullingGroupExample.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a0f7bca99a1816244927583c60c3e022 +timeCreated: 1594958194 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Docs/UnityEngine/NavMeshAgentExample.cs b/Assets/Scripts/Docs/UnityEngine/NavMeshAgentExample.cs new file mode 100644 index 0000000..bae418b --- /dev/null +++ b/Assets/Scripts/Docs/UnityEngine/NavMeshAgentExample.cs @@ -0,0 +1,23 @@ +// made with chatGPT + +using UnityEngine; +using UnityEngine.AI; + +namespace UnityLibrary +{ + public class NavMeshAgentExample : MonoBehaviour + { + public Transform target; + + private NavMeshAgent agent; + + void Start() + { + // Get the NavMeshAgent component on this game object + agent = GetComponent(); + + // Set the destination of the NavMeshAgent to the target Transform + agent.destination = target.position; + } + } +} diff --git a/Assets/Scripts/Drawing/DrawLine.cs b/Assets/Scripts/Drawing/DrawLine.cs index 44d6c53..6ffbfbd 100644 --- a/Assets/Scripts/Drawing/DrawLine.cs +++ b/Assets/Scripts/Drawing/DrawLine.cs @@ -53,8 +53,9 @@ protected virtual void Update() } if (Input.GetMouseButton(0)) { - Vector3 mousePosition = m_Camera.ScreenToWorldPoint(Input.mousePosition); - mousePosition.z = m_LineRenderer.transform.position.z; + var pos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, lineRenderer.transform.position.z - m_Camera.transform.position.z); + Vector3 mousePosition = m_Camera.ScreenToWorldPoint(pos); + mousePosition.z = 0; if (!m_Points.Contains(mousePosition)) { m_Points.Add(mousePosition); diff --git a/Assets/Scripts/Editor/Animation.meta b/Assets/Scripts/Editor/Animation.meta new file mode 100644 index 0000000..a9393f4 --- /dev/null +++ b/Assets/Scripts/Editor/Animation.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 344c9e72d34584041b61214522912d71 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Animation/LegacyAnimationCreator.meta b/Assets/Scripts/Editor/Animation/LegacyAnimationCreator.meta new file mode 100644 index 0000000..9fc6b69 --- /dev/null +++ b/Assets/Scripts/Editor/Animation/LegacyAnimationCreator.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e78d070eb9ba01749a33425b62b0fe5c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Animation/LegacyAnimationCreator/LegacyAnimationCreator.cs b/Assets/Scripts/Editor/Animation/LegacyAnimationCreator/LegacyAnimationCreator.cs new file mode 100644 index 0000000..35f7ff2 --- /dev/null +++ b/Assets/Scripts/Editor/Animation/LegacyAnimationCreator/LegacyAnimationCreator.cs @@ -0,0 +1,28 @@ +using System.IO; +using UnityEditor; +using UnityEngine; + +public class LegacyAnimationCreator +{ + [MenuItem("Assets/Create/Legacy Animation", priority = 402)] + public static void CompressSelectedAnimationClips() + { + var clip = new AnimationClip(); + clip.legacy = true; + clip.name = "New Legacy Animation"; + + string path; + var selection = Selection.activeObject; + if (selection == null) + path = "Assets"; + else + path = AssetDatabase.GetAssetPath(selection.GetInstanceID()); + + path = Path.GetDirectoryName(path); + path += $"/{clip.name}.anim"; + + ProjectWindowUtil.CreateAsset(clip, path); + Selection.activeObject = clip; + EditorUtility.SetDirty(clip); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Editor/Animation/LegacyAnimationCreator/LegacyAnimationCreator.cs.meta b/Assets/Scripts/Editor/Animation/LegacyAnimationCreator/LegacyAnimationCreator.cs.meta new file mode 100644 index 0000000..5bd716f --- /dev/null +++ b/Assets/Scripts/Editor/Animation/LegacyAnimationCreator/LegacyAnimationCreator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d536889e20faa9d47b7def4f46203b81 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/BatchTools/CopyGameObjectNames.cs b/Assets/Scripts/Editor/BatchTools/CopyGameObjectNames.cs new file mode 100644 index 0000000..40bf0d0 --- /dev/null +++ b/Assets/Scripts/Editor/BatchTools/CopyGameObjectNames.cs @@ -0,0 +1,59 @@ +// editor tool to copy names of selected GameObjects to clipboard as a list (so you can paste them in Excel or others..) + +using UnityEngine; +using UnityEditor; +using System.Text; +using System.Linq; +namespace UnityLibrary.Tools +{ + public class CopyGameObjectNames : EditorWindow + { + private string gameObjectNames = string.Empty; + + [MenuItem("Tools/Copy GameObject Names")] + public static void ShowWindow() + { + GetWindow("Copy GameObject Names"); + } + + private void OnGUI() + { + GUILayout.Label("Copy Names of Selected GameObjects", EditorStyles.boldLabel); + + if (GUILayout.Button("Fetch Names")) + { + FetchNames(); + } + + GUILayout.Label("GameObject Names:", EditorStyles.label); + gameObjectNames = EditorGUILayout.TextArea(gameObjectNames, GUILayout.Height(200)); + + if (GUILayout.Button("Copy to Clipboard")) + { + CopyToClipboard(); + } + } + + private void FetchNames() + { + StringBuilder sb = new StringBuilder(); + GameObject[] selectedObjects = Selection.gameObjects; + + // Sort the selected objects by their sibling index + var sortedObjects = selectedObjects.OrderBy(go => go.transform.GetSiblingIndex()).ToArray(); + + foreach (GameObject obj in sortedObjects) + { + sb.AppendLine(obj.name); + } + + gameObjectNames = sb.ToString(); + } + + private void CopyToClipboard() + { + EditorGUIUtility.systemCopyBuffer = gameObjectNames; + Debug.Log("GameObject names copied to clipboard."); + } + } +} diff --git a/Assets/Scripts/Editor/BatchTools/ReplaceCharacterInGameObjectNames.cs b/Assets/Scripts/Editor/BatchTools/ReplaceCharacterInGameObjectNames.cs new file mode 100644 index 0000000..105bc74 --- /dev/null +++ b/Assets/Scripts/Editor/BatchTools/ReplaceCharacterInGameObjectNames.cs @@ -0,0 +1,69 @@ +// editor tool to replace string from selected GameObject names + +using UnityEngine; +using UnityEditor; +using UnityEditor.SceneManagement; + +namespace UnityLibrary.Tools +{ + public class ReplaceCharacterInGameObjectNames : EditorWindow + { + private string searchString = "|"; + private string replaceString = "@"; + + [MenuItem("Tools/Replace Characters in GameObject Names")] + public static void ShowWindow() + { + GetWindow("Replace Characters"); + } + + private void OnGUI() + { + GUILayout.Label("Replace Characters in Selected GameObject Names", EditorStyles.boldLabel); + + searchString = EditorGUILayout.TextField("Search String", searchString); + replaceString = EditorGUILayout.TextField("Replace String", replaceString); + + int selectedObjectCount = Selection.gameObjects.Length; + GUILayout.Label($"Selected GameObjects: {selectedObjectCount}", EditorStyles.label); + + if (GUILayout.Button("Replace")) + { + ReplaceCharacters(); + } + } + + private void ReplaceCharacters() + { + GameObject[] selectedObjects = Selection.gameObjects; + + if (selectedObjects.Length == 0) + { + Debug.LogWarning("No GameObjects selected."); + return; + } + + // Start a new undo group + Undo.IncrementCurrentGroup(); + Undo.SetCurrentGroupName("Replace Character in GameObject Names"); + int undoGroup = Undo.GetCurrentGroup(); + + foreach (GameObject obj in selectedObjects) + { + if (obj.name.Contains(searchString)) + { + Undo.RecordObject(obj, "Replace Character in GameObject Name"); + obj.name = obj.name.Replace(searchString, replaceString); + EditorUtility.SetDirty(obj); + } + } + + // End the undo group + Undo.CollapseUndoOperations(undoGroup); + + EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); + + Debug.Log($"Replaced '{searchString}' with '{replaceString}' in the names of selected GameObjects."); + } + } +} diff --git a/Assets/Scripts/Editor/BuildProcess/PostBuildCopyEmptyFolders.cs b/Assets/Scripts/Editor/BuildProcess/PostBuildCopyEmptyFolders.cs new file mode 100644 index 0000000..186265b --- /dev/null +++ b/Assets/Scripts/Editor/BuildProcess/PostBuildCopyEmptyFolders.cs @@ -0,0 +1,54 @@ +using System.IO; +using UnityEditor; +using UnityEditor.Callbacks; +using UnityEngine; + +// copies empty StreamingAssets/ folders into build, as they are not automatically included + +namespace UnityLibrary +{ + public class PostBuildCopyEmptyFolders : MonoBehaviour + { + [PostProcessBuildAttribute(1)] + public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) + { + // only for windows + if (target != BuildTarget.StandaloneWindows) return; + + Debug.Log("### POSTBUILD : COPY EMPTY STREAMINGASSETS-FOLDERS ###"); + Debug.Log("Build done: " + pathToBuiltProject); + + // get output root + var root = Path.GetDirectoryName(pathToBuiltProject); + var appName = Path.GetFileNameWithoutExtension(pathToBuiltProject); + + // copy empty streaming asset folders to build + var sourcePath = Application.streamingAssetsPath; + var targetPath = Path.Combine(root, appName + "_Data", "StreamingAssets"); + //Debug.Log("sourcePath= "+ sourcePath); + //Debug.Log("targetPath= " + targetPath); + CopyFolderStructure(sourcePath, targetPath); + } + + // recursive folder copier + static public void CopyFolderStructure(string sourceFolder, string destFolder) + { + if (Directory.Exists(destFolder)) + { + + } + else + { + Directory.CreateDirectory(destFolder); + } + + string[] folders = Directory.GetDirectories(sourceFolder); + foreach (string folder in folders) + { + string name = Path.GetFileName(folder); + string dest = Path.Combine(destFolder, name); + CopyFolderStructure(folder, dest); + } + } + } +} diff --git a/Assets/Scripts/Editor/ContextMenu.meta b/Assets/Scripts/Editor/ContextMenu.meta new file mode 100644 index 0000000..bbbf7ac --- /dev/null +++ b/Assets/Scripts/Editor/ContextMenu.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 07f01cf58a1140349bfac4f393266db1 +folderAsset: yes +timeCreated: 1594958190 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/ContextMenu/BoxColliderFitChildren.cs b/Assets/Scripts/Editor/ContextMenu/BoxColliderFitChildren.cs new file mode 100644 index 0000000..ce3f298 --- /dev/null +++ b/Assets/Scripts/Editor/ContextMenu/BoxColliderFitChildren.cs @@ -0,0 +1,71 @@ +using UnityEngine; +using UnityEditor; + +namespace UnityLibrary +{ + public class BoxColliderFitChildren : MonoBehaviour + { + [MenuItem("CONTEXT/BoxCollider/Fit to Children")] + static void FitColliderToChildren(MenuCommand command) + { + BoxCollider col = (BoxCollider)command.context; + + // Record undo + Undo.RecordObject(col.transform, "Fit Box Collider To Children"); + + // Get world-space bounds of all child meshes + var worldBounds = GetRecursiveMeshBounds(col.gameObject); + + if (worldBounds.size == Vector3.zero) + { + Debug.LogWarning("No valid meshes found to fit the BoxCollider."); + return; + } + + // Convert world-space center to local space + Vector3 localCenter = col.transform.InverseTransformPoint(worldBounds.center); + + // Convert world-space size to local space + Vector3 localSize = col.transform.InverseTransformVector(worldBounds.size); + + // Ensure size is positive + localSize = new Vector3(Mathf.Abs(localSize.x), Mathf.Abs(localSize.y), Mathf.Abs(localSize.z)); + + // Fix potential center flipping + if (Vector3.Dot(col.transform.right, Vector3.right) < 0) + { + localCenter.x = -localCenter.x; + } + if (Vector3.Dot(col.transform.up, Vector3.up) < 0) + { + localCenter.y = -localCenter.y; + } + if (Vector3.Dot(col.transform.forward, Vector3.forward) < 0) + { + localCenter.z = -localCenter.z; + } + + // Apply to collider + col.center = localCenter; + col.size = localSize; + } + + public static Bounds GetRecursiveMeshBounds(GameObject go) + { + Renderer[] renderers = go.GetComponentsInChildren(); + + if (renderers.Length == 0) + return new Bounds(); + + // Start with the first renderer’s bounds in world space + Bounds worldBounds = renderers[0].bounds; + + for (int i = 1; i < renderers.Length; i++) + { + worldBounds.Encapsulate(renderers[i].bounds); + } + + return worldBounds; + } + } +} diff --git a/Assets/Scripts/Editor/ContextMenu/BoxColliderFitChildren.cs.meta b/Assets/Scripts/Editor/ContextMenu/BoxColliderFitChildren.cs.meta new file mode 100644 index 0000000..08e2df8 --- /dev/null +++ b/Assets/Scripts/Editor/ContextMenu/BoxColliderFitChildren.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 687fde9d16dc6b04e934c421806d4abb +timeCreated: 1594958194 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/ContextMenu/CreateOutlineForPanelEditor.cs b/Assets/Scripts/Editor/ContextMenu/CreateOutlineForPanelEditor.cs new file mode 100644 index 0000000..539fbfa --- /dev/null +++ b/Assets/Scripts/Editor/ContextMenu/CreateOutlineForPanelEditor.cs @@ -0,0 +1,59 @@ +// Custom Contect menu for UI Image component (in WorldSpace UI canvas) +// used for creating outline for panel (image) using LineRenderer + +using UnityEngine; +using UnityEditor; +using UnityEngine.UI; + +namespace UnityLibrary +{ + public class CreateOutlineForPanelEditor : MonoBehaviour + { + [MenuItem("CONTEXT/Image/Create Outline For Panel")] + static void DoubleMass(MenuCommand command) + { + // get reference + Image comp = (Image)command.context; + if (comp == null) + { + Debug.LogError("No Image component found.."); + return; + } + + // TODO check that its worlspace canvas + + // get worldspace borders, FIXME get root canvas, instead of parent + var canvasRect = comp.transform.parent.GetComponent().GetComponent(); + Vector3[] corners = new Vector3[4]; + canvasRect.GetWorldCorners(corners); + + var line = comp.transform.GetComponent(); + if (line == null) + { + Debug.LogError("Missing LineRenderer component"); + return; + } + + if (line.useWorldSpace == true) + { + Debug.LogWarning("LineRenderer has worlspace enabled, disabling it"); + line.useWorldSpace = false; + } + + // set line points + line.positionCount = corners.Length + 1; + line.SetPositions(corners); + // connect last and first + line.SetPosition(line.positionCount - 1, corners[0]); + + // convert worldspace to localspace + for (int i = 0, len = line.positionCount; i < len; i++) + { + var worldPos = line.GetPosition(i); + var localPos = canvasRect.transform.InverseTransformPoint(worldPos); + line.SetPosition(i, localPos); + } + + } + } +} diff --git a/Assets/Scripts/Editor/ContextMenu/CreateOutlineForPanelEditor.cs.meta b/Assets/Scripts/Editor/ContextMenu/CreateOutlineForPanelEditor.cs.meta new file mode 100644 index 0000000..e5d8f63 --- /dev/null +++ b/Assets/Scripts/Editor/ContextMenu/CreateOutlineForPanelEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ea3d3337d55b5bc42a40dff5480adca0 +timeCreated: 1594958194 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/ContextMenu/GetVideoAspectRatioEditor.cs b/Assets/Scripts/Editor/ContextMenu/GetVideoAspectRatioEditor.cs new file mode 100644 index 0000000..b15992c --- /dev/null +++ b/Assets/Scripts/Editor/ContextMenu/GetVideoAspectRatioEditor.cs @@ -0,0 +1,39 @@ +// Custom Contect menu for VideoPlayer component +// used for scaling quad mesh transform localscale.y to match videoplayer aspect ratio + +using UnityEngine; +using UnityEditor; +using UnityEngine.Video; + +namespace UnityLibrary +{ + public class GetVideoAspectRatioEditor : MonoBehaviour + { + [MenuItem("CONTEXT/VideoPlayer/Get Aspect Ratio for Mesh")] + static void DoubleMass(MenuCommand command) + { + // get aspect ratio + VideoPlayer v = (VideoPlayer)command.context; + if (v.clip == null) + { + Debug.LogError("No videoclip assigned.."); + return; + } +#if UNITY_2017 + float aspectRatioY = v.texture.height / (float)v.texture.width; +#else + float aspectRatioY = v.height / (float)v.width; +#endif + + + // record undo + Undo.RecordObject(v.transform, "Set scale"); + + // scale mesh + Vector3 scale = v.transform.localScale; + // fix only height + scale.y *= aspectRatioY; + v.transform.localScale = scale; + } + } +} diff --git a/Assets/Scripts/Editor/ContextMenu/GetVideoAspectRatioEditor.cs.meta b/Assets/Scripts/Editor/ContextMenu/GetVideoAspectRatioEditor.cs.meta new file mode 100644 index 0000000..4aa5605 --- /dev/null +++ b/Assets/Scripts/Editor/ContextMenu/GetVideoAspectRatioEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: acde12b67d212ae42ab65f73b96ffd59 +timeCreated: 1594958194 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/ContextMenu/SetBoxColliderToUI.cs b/Assets/Scripts/Editor/ContextMenu/SetBoxColliderToUI.cs new file mode 100644 index 0000000..6b58cf5 --- /dev/null +++ b/Assets/Scripts/Editor/ContextMenu/SetBoxColliderToUI.cs @@ -0,0 +1,32 @@ +// Tries to move BoxCollider(3D)-component to match UI panel/image position, by adjusting collider pivot value + +using UnityEngine; +using UnityEditor; + +namespace UnityLibrary +{ + public class SetBoxColliderToUI : MonoBehaviour + { + [MenuItem("CONTEXT/BoxCollider/Match Position to UI")] + static void FixPosition(MenuCommand command) + { + BoxCollider b = (BoxCollider)command.context; + + // record undo + Undo.RecordObject(b.transform, "Set Box Collider To UI"); + + // fix pos from Pivot + var r = b.gameObject.GetComponent(); + if (r == null) return; + + //Debug.Log("pivot "+r.pivot); + + var center = b.center; + + center.x = 0.5f - r.pivot.x; + center.y = 0.5f - r.pivot.y; + + b.center = center; + } + } +} diff --git a/Assets/Scripts/Editor/ContextMenu/SetBoxColliderToUI.cs.meta b/Assets/Scripts/Editor/ContextMenu/SetBoxColliderToUI.cs.meta new file mode 100644 index 0000000..bbc5ca4 --- /dev/null +++ b/Assets/Scripts/Editor/ContextMenu/SetBoxColliderToUI.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9581bb1267ccd9e48b11127704331d49 +timeCreated: 1594958194 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/CustomInspector/CustomRectTransformCopyInspector.cs b/Assets/Scripts/Editor/CustomInspector/CustomRectTransformCopyInspector.cs new file mode 100644 index 0000000..0a5de2b --- /dev/null +++ b/Assets/Scripts/Editor/CustomInspector/CustomRectTransformCopyInspector.cs @@ -0,0 +1,114 @@ +#if UNITY_EDITOR +using System; +using System.Reflection; +using UnityEngine; + +namespace UnityEditor +{ + [CustomEditor(typeof(RectTransform), true)] + [CanEditMultipleObjects] + public class CustomRectTransformCopyInspector : Editor + { + // Unity's built-in editor + Editor defaultEditor = null; + RectTransform rectTransform; + + private static RectTransformData copiedData; + + void OnEnable() + { + // Use reflection to get the default Unity RectTransform editor + defaultEditor = Editor.CreateEditor(targets, Type.GetType("UnityEditor.RectTransformEditor, UnityEditor")); + rectTransform = target as RectTransform; + } + + void OnDisable() + { + // Destroy the default editor to avoid memory leaks + if (defaultEditor != null) + { + MethodInfo disableMethod = defaultEditor.GetType().GetMethod("OnDisable", + BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); + if (disableMethod != null) + disableMethod.Invoke(defaultEditor, null); + + DestroyImmediate(defaultEditor); + } + } + + public override void OnInspectorGUI() + { + // Draw Unity's default RectTransform Inspector + defaultEditor.OnInspectorGUI(); + + // Add Copy and Paste buttons + EditorGUILayout.Space(); + GUILayout.BeginHorizontal(); + + if (GUILayout.Button("C", GUILayout.Width(30))) // Copy + { + CopyRectTransform(rectTransform); + } + + if (GUILayout.Button("P", GUILayout.Width(30))) // Paste + { + PasteRectTransform(rectTransform); + } + + GUILayout.EndHorizontal(); + } + + private void CopyRectTransform(RectTransform rectTransform) + { + copiedData = new RectTransformData(rectTransform); + Debug.Log("RectTransform copied!"); + } + + private void PasteRectTransform(RectTransform rectTransform) + { + if (copiedData == null) + { + Debug.LogWarning("No RectTransform data to paste!"); + return; + } + + Undo.RecordObject(rectTransform, "Paste RectTransform"); + + copiedData.ApplyTo(rectTransform); + Debug.Log("RectTransform pasted!"); + + EditorUtility.SetDirty(rectTransform); + } + + private class RectTransformData + { + public Vector2 anchorMin; + public Vector2 anchorMax; + public Vector2 anchoredPosition; + public Vector2 sizeDelta; + public Vector2 pivot; + public Quaternion rotation; + + public RectTransformData(RectTransform rectTransform) + { + anchorMin = rectTransform.anchorMin; + anchorMax = rectTransform.anchorMax; + anchoredPosition = rectTransform.anchoredPosition; + sizeDelta = rectTransform.sizeDelta; + pivot = rectTransform.pivot; + rotation = rectTransform.rotation; + } + + public void ApplyTo(RectTransform rectTransform) + { + rectTransform.anchorMin = anchorMin; + rectTransform.anchorMax = anchorMax; + rectTransform.anchoredPosition = anchoredPosition; + rectTransform.sizeDelta = sizeDelta; + rectTransform.pivot = pivot; + rectTransform.rotation = rotation; + } + } + } +} +#endif diff --git a/Assets/Scripts/Editor/CustomInspector/CustomRectTransformInspector.cs b/Assets/Scripts/Editor/CustomInspector/CustomRectTransformInspector.cs new file mode 100644 index 0000000..02c51af --- /dev/null +++ b/Assets/Scripts/Editor/CustomInspector/CustomRectTransformInspector.cs @@ -0,0 +1,294 @@ +// source https://gist.github.com/GieziJo/f80bcb24c4caa68ebfb204148ccd4b18 +// =============================== +// AUTHOR : J. Giezendanner +// CREATE DATE : 12.03.2020 +// MODIFIED DATE : +// PURPOSE : Adds helper functions to the RectTransform to align the rect to the anchors and vise-versa +// SPECIAL NOTES : Sources for certain informations: +// Display anchors gizmos: +// https://forum.unity.com/threads/recttransform-custom-editor-ontop-of-unity-recttransform-custom-editor.455925/ +// Draw default inspector: +// https://forum.unity.com/threads/extending-instead-of-replacing-built-in-inspectors.407612/ +// =============================== +// Change History: +//================================== + +#if UNITY_EDITOR +using System; +using System.Reflection; +using UnityEditor.SceneManagement; +using UnityEngine; + + +namespace UnityEditor +{ + [CustomEditor(typeof(RectTransform), true)] + [CanEditMultipleObjects] + public class CustomRectTransformInspector : Editor + { + //Unity's built-in editor + Editor defaultEditor = null; + RectTransform rectTransform; + + bool rect2Anchors_foldout = false; + bool anchors2Rect_foldout = false; + bool rect2Anchors__previousState = false; + bool anchors2Rect_previousState = false; + + private bool playerPrefsChecked = false; + + void OnEnable() + { + //When this inspector is created, also create the built-in inspector + defaultEditor = Editor.CreateEditor(targets, Type.GetType("UnityEditor.RectTransformEditor, UnityEditor")); + rectTransform = target as RectTransform; + } + + void OnDisable() + { + //When OnDisable is called, the default editor we created should be destroyed to avoid memory leakage. + //Also, make sure to call any required methods like OnDisable + + if (defaultEditor != null) + { + MethodInfo disableMethod = defaultEditor.GetType().GetMethod("OnDisable", + BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); + if (disableMethod != null) + disableMethod.Invoke(defaultEditor, null); + DestroyImmediate(defaultEditor); + } + } + + void checkPlayerPrefs() + { + rect2Anchors_foldout = PlayerPrefs.GetInt("giezi_tools_rect2Anchors_foldout_bool", 0) != 0; + anchors2Rect_foldout = PlayerPrefs.GetInt("giezi_tools_anchors2Rect_foldout_bool", 0) != 0; + + rect2Anchors__previousState = rect2Anchors_foldout; + anchors2Rect_previousState = anchors2Rect_foldout; + } + + + public override void OnInspectorGUI() + { + if (!playerPrefsChecked) + { + checkPlayerPrefs(); + playerPrefsChecked = true; + } + + defaultEditor.OnInspectorGUI(); + + + if (rectTransform.parent != null) + { + var centerButtonStyle = new GUIStyle(GUI.skin.button); + centerButtonStyle.fontStyle = FontStyle.Bold; + + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Helper Functions", EditorStyles.boldLabel); + + rect2Anchors_foldout = EditorGUILayout.Foldout(rect2Anchors_foldout, "Set Rect to Anchors"); + + if (rect2Anchors_foldout) + { + GUILayout.BeginHorizontal(); + GUILayout.BeginVertical(); + if (GUILayout.Button("Top Left")) + setRectValue("topLeft"); + if (GUILayout.Button("Left")) + setRectValue("left"); + if (GUILayout.Button("Bottom Left")) + setRectValue("bottomLeft"); + GUILayout.EndVertical(); + GUILayout.BeginVertical(); + if (GUILayout.Button("Top")) + setRectValue("top"); + if (GUILayout.Button("All", centerButtonStyle)) + setRectValue("all"); + if (GUILayout.Button("Bottom")) + setRectValue("bottom"); + GUILayout.EndVertical(); + GUILayout.BeginVertical(); + if (GUILayout.Button("Top Right")) + setRectValue("topRight"); + if (GUILayout.Button("Right")) + setRectValue("right"); + if (GUILayout.Button("Bottom Right")) + setRectValue("bottomRight"); + GUILayout.EndVertical(); + GUILayout.EndHorizontal(); + } + + anchors2Rect_foldout = EditorGUILayout.Foldout(anchors2Rect_foldout, "Set Anchors to Rect"); + + if (anchors2Rect_foldout) + { + GUILayout.BeginHorizontal(); + GUILayout.BeginVertical(); + if (GUILayout.Button("Top Left")) + setAnchorsToRect("topLeft"); + if (GUILayout.Button("Left")) + setAnchorsToRect("left"); + if (GUILayout.Button("Bottom Left")) + setAnchorsToRect("bottomLeft"); + GUILayout.EndVertical(); + GUILayout.BeginVertical(); + if (GUILayout.Button("Top")) + setAnchorsToRect("top"); + if (GUILayout.Button("All", centerButtonStyle)) + setAnchorsToRect("all"); + if (GUILayout.Button("Bottom")) + setAnchorsToRect("bottom"); + GUILayout.EndVertical(); + GUILayout.BeginVertical(); + if (GUILayout.Button("Top Right")) + setAnchorsToRect("topRight"); + if (GUILayout.Button("Right")) + setAnchorsToRect("right"); + if (GUILayout.Button("Bottom Right")) + setAnchorsToRect("bottomRight"); + GUILayout.EndVertical(); + GUILayout.EndHorizontal(); + } + + + if (rect2Anchors_foldout != rect2Anchors__previousState) + { + rect2Anchors__previousState = rect2Anchors_foldout; + PlayerPrefs.SetInt("giezi_tools_rect2Anchors_foldout_bool", rect2Anchors_foldout ? 1 : 0); + } + + if (anchors2Rect_foldout != anchors2Rect_previousState) + { + anchors2Rect_previousState = anchors2Rect_foldout; + PlayerPrefs.SetInt("giezi_tools_anchors2Rect_foldout_bool", anchors2Rect_foldout ? 1 : 0); + } + } + } + + + private void OnSceneGUI() + { + MethodInfo onSceneGUI_Method = defaultEditor.GetType() + .GetMethod("OnSceneGUI", BindingFlags.NonPublic | BindingFlags.Instance); + onSceneGUI_Method.Invoke(defaultEditor, null); + } + + + private void setAnchorsToRect(string field) + { + Vector2 anchorMax = new Vector2(); + Vector2 anchorMin = new Vector2(); + var parent = rectTransform.parent; + anchorMin.x = rectTransform.offsetMin.x / parent.GetComponent().rect.size.x; + anchorMin.y = rectTransform.offsetMin.y / parent.GetComponent().rect.size.y; + anchorMax.x = rectTransform.offsetMax.x / parent.GetComponent().rect.size.x; + anchorMax.y = rectTransform.offsetMax.y / parent.GetComponent().rect.size.y; + + + switch (field) + { + case "topLeft": + anchorMax.x = 0; + rectTransform.anchorMax += anchorMax; + rectTransform.offsetMax = new Vector2(rectTransform.offsetMax.x, 0); + + anchorMin.y = 0; + rectTransform.anchorMin += anchorMin; + rectTransform.offsetMin = new Vector2(0, rectTransform.offsetMin.y); + break; + case "top": + anchorMax.x = 0; + rectTransform.anchorMax += anchorMax; + rectTransform.offsetMax = new Vector2(rectTransform.offsetMax.x, 0); + break; + case "topRight": + rectTransform.anchorMax += anchorMax; + rectTransform.offsetMax = Vector2.zero; + break; + case "bottomLeft": + rectTransform.anchorMin += anchorMin; + rectTransform.offsetMin = Vector2.zero; + break; + case "bottom": + anchorMin.x = 0; + rectTransform.anchorMin += anchorMin; + rectTransform.offsetMin = new Vector2(rectTransform.offsetMin.x, 0); + break; + case "bottomRight": + anchorMin.x = 0; + rectTransform.anchorMin += anchorMin; + rectTransform.offsetMin = new Vector2(rectTransform.offsetMin.x, 0); + anchorMax.y = 0; + rectTransform.anchorMax += anchorMax; + rectTransform.offsetMax = new Vector2(0, rectTransform.offsetMax.y); + break; + case "left": + anchorMin.y = 0; + rectTransform.anchorMin += anchorMin; + rectTransform.offsetMin = new Vector2(0, rectTransform.offsetMin.y); + break; + case "right": + anchorMax.y = 0; + rectTransform.anchorMax += anchorMax; + rectTransform.offsetMax = new Vector2(0, rectTransform.offsetMax.y); + break; + case "all": + rectTransform.anchorMax += anchorMax; + rectTransform.anchorMin += anchorMin; + rectTransform.offsetMin = Vector2.zero; + rectTransform.offsetMax = Vector2.zero; + break; + } + + handleChange(); + } + + + private void setRectValue(string field) + { + switch (field) + { + case "topLeft": + rectTransform.offsetMax = new Vector2(rectTransform.offsetMax.x, 0); + rectTransform.offsetMin = new Vector2(0, rectTransform.offsetMin.y); + break; + case "top": + rectTransform.offsetMax = new Vector2(rectTransform.offsetMax.x, 0); + break; + case "topRight": + rectTransform.offsetMax = Vector2.zero; + break; + case "bottomLeft": + rectTransform.offsetMin = Vector2.zero; + break; + case "bottom": + rectTransform.offsetMin = new Vector2(rectTransform.offsetMin.x, 0); + break; + case "bottomRight": + rectTransform.offsetMin = new Vector2(rectTransform.offsetMin.x, 0); + rectTransform.offsetMax = new Vector2(0, rectTransform.offsetMax.y); + break; + case "left": + rectTransform.offsetMin = new Vector2(0, rectTransform.offsetMin.y); + break; + case "right": + rectTransform.offsetMax = new Vector2(0, rectTransform.offsetMax.y); + break; + case "all": + rectTransform.offsetMin = new Vector2(0, 0); + rectTransform.offsetMax = new Vector2(0, 0); + break; + } + + handleChange(); + } + + private void handleChange() + { + EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); + } + } +} +#endif diff --git a/Assets/Scripts/Editor/CustomInspector/TransformEditor.cs b/Assets/Scripts/Editor/CustomInspector/TransformEditor.cs new file mode 100644 index 0000000..152989e --- /dev/null +++ b/Assets/Scripts/Editor/CustomInspector/TransformEditor.cs @@ -0,0 +1,436 @@ +// source https://gist.github.com/unitycoder/e5e6384f087639c0d9edc93aa3820468 + +using UnityEngine; +using UnityEditor; + +namespace OddTales.Framework.Core.EditorExtension +{ + /// + /// Custom inspector for Transform component. Using only DrawDefaultInspector would give different display. + /// Script based on Unity wiki implementation : https://wiki.unity3d.com/index.php/TransformInspector + /// Buttons to reset, copy, paste Transform values. + /// Context menu to round/truncate values, hide/show tools. + /// + [CanEditMultipleObjects, CustomEditor(typeof(Transform))] + public class TransformEditor : Editor + { + private const float FIELD_WIDTH = 212.0f; + private const bool WIDE_MODE = true; + + private const float POSITION_MAX = 100000.0f; + + private static GUIContent positionGUIContent = new GUIContent(LocalString("Position")); + private static GUIContent rotationGUIContent = new GUIContent(LocalString("Rotation")); + private static GUIContent scaleGUIContent = new GUIContent(LocalString("Scale")); + + private static string positionWarningText = LocalString("Due to floating-point precision limitations, it is recommended to bring the world coordinates of the GameObject within a smaller range."); + + private SerializedProperty positionProperty, rotationProperty, scaleProperty; + + private static Vector3? positionClipboard = null; + private static Quaternion? rotationClipboard = null; + private static Vector3? scaleClipboard = null; + + private const string SHOW_TOOLS_KEY = "TransformEditor_ShowTools"; + private const string SHOW_RESET_TOOLS_KEY = "TransformEditor_ShowResetTools"; + private const string SHOW_PASTE_TOOLS_KEY = "TransformEditor_ShowPasteTools"; + private const string SHOW_ADVANCED_PASTE_TOOLS_KEY = "TransformEditor_ShowAdvancedPasteTools"; + private const string SHOW_CLIPBOARD_INFORMATIONS_KEY = "TransformEditor_ShowClipboardInformations"; + private const string SHOW_SHORTCUTS_KEY = "TransformEditor_ShowHelpbox"; + + +#if UNITY_2017_3_OR_NEWER + private static System.Reflection.MethodInfo getLocalizedStringMethod; +#endif + + + /// Get translated Transform label + private static string LocalString(string text) + { +#if UNITY_2017_3_OR_NEWER + // Since Unity 2017.3, static class LocalizationDatabase is no longer public. Need to use reflection to access it. + if (getLocalizedStringMethod == null) + { + System.Reflection.Assembly assembly = typeof(UnityEditor.EditorWindow).Assembly; + System.Type localizationDatabaseType = assembly.GetType("UnityEditor.LocalizationDatabase"); + + getLocalizedStringMethod = localizationDatabaseType.GetMethod("GetLocalizedString"); + } + + return (string)getLocalizedStringMethod.Invoke(null, new object[] { text }); +#else + return LocalizationDatabase.GetLocalizedString(text); +#endif + } + + public void OnEnable() + { + positionProperty = serializedObject.FindProperty("m_LocalPosition"); + rotationProperty = serializedObject.FindProperty("m_LocalRotation"); + scaleProperty = serializedObject.FindProperty("m_LocalScale"); + + // Init options + if (!EditorPrefs.HasKey(SHOW_TOOLS_KEY)) EditorPrefs.SetBool(SHOW_TOOLS_KEY, true); + if (!EditorPrefs.HasKey(SHOW_RESET_TOOLS_KEY)) EditorPrefs.SetBool(SHOW_RESET_TOOLS_KEY, true); + if (!EditorPrefs.HasKey(SHOW_PASTE_TOOLS_KEY)) EditorPrefs.SetBool(SHOW_PASTE_TOOLS_KEY, true); + if (!EditorPrefs.HasKey(SHOW_ADVANCED_PASTE_TOOLS_KEY)) EditorPrefs.SetBool(SHOW_ADVANCED_PASTE_TOOLS_KEY, true); + if (!EditorPrefs.HasKey(SHOW_CLIPBOARD_INFORMATIONS_KEY)) EditorPrefs.SetBool(SHOW_CLIPBOARD_INFORMATIONS_KEY, true); + if (!EditorPrefs.HasKey(SHOW_SHORTCUTS_KEY)) EditorPrefs.SetBool(SHOW_SHORTCUTS_KEY, true); + } + + + public override void OnInspectorGUI() + { + Rect beginRect = GUILayoutUtility.GetRect(0, 0); + + EditorGUIUtility.wideMode = TransformEditor.WIDE_MODE; + EditorGUIUtility.labelWidth = EditorGUIUtility.currentViewWidth - TransformEditor.FIELD_WIDTH; // align field to right of inspector + + serializedObject.Update(); + + EditorGUIUtility.labelWidth = 60; // To allow float fields to expand when inspector width is increased + + // Position GUI + EditorGUILayout.BeginHorizontal(); + PositionPropertyField(positionProperty, positionGUIContent); // Note : Can't add generic menu if we use EditorGUILayout.PropertyField instead + if (EditorPrefs.GetBool(SHOW_TOOLS_KEY) && EditorPrefs.GetBool(SHOW_RESET_TOOLS_KEY)) + { + if (GUILayout.Button("Reset", GUILayout.Width(50))) + { + Undo.RecordObjects(targets, "Reset Positions"); + for (int i = 0; i < targets.Length; i++) + { + ((Transform)targets[i]).localPosition = Vector3.zero; + } + GUI.FocusControl(null); + } + } + EditorGUILayout.EndHorizontal(); + + // Rotation GUI + EditorGUILayout.BeginHorizontal(); + RotationPropertyField(rotationProperty, rotationGUIContent); // Note : Can't add generic menu if we use EditorGUILayout.PropertyField instead + if (EditorPrefs.GetBool(SHOW_TOOLS_KEY) && EditorPrefs.GetBool(SHOW_RESET_TOOLS_KEY)) + { + if (GUILayout.Button("Reset", GUILayout.Width(50))) + { + Undo.RecordObjects(targets, "Reset Rotations"); + for (int i = 0; i < targets.Length; i++) + { + TransformUtils.SetInspectorRotation(((Transform)targets[i]), Vector3.zero); + } + GUI.FocusControl(null); + } + + } + EditorGUILayout.EndHorizontal(); + + // Scale GUI + EditorGUILayout.BeginHorizontal(); + ScalePropertyField(scaleProperty, scaleGUIContent); // Note : Can't add generic menu if we use EditorGUILayout.PropertyField instead + if (EditorPrefs.GetBool(SHOW_TOOLS_KEY) && EditorPrefs.GetBool(SHOW_RESET_TOOLS_KEY)) + { + if (GUILayout.Button("Reset", GUILayout.Width(50))) + { + Undo.RecordObjects(targets, "Reset Scales"); + for (int i = 0; i < targets.Length; i++) + { + ((Transform)targets[i]).localScale = Vector3.one; + } + GUI.FocusControl(null); + } + } + EditorGUILayout.EndHorizontal(); + + + if (!ValidatePosition(((Transform)target).position)) EditorGUILayout.HelpBox(positionWarningText, MessageType.Warning); // Display floating-point warning message if values are too high + + if (EditorPrefs.GetBool(SHOW_TOOLS_KEY)) + { + // Paste Tools GUI + if (EditorPrefs.GetBool(SHOW_PASTE_TOOLS_KEY)) + { + GUILayout.BeginHorizontal(); + if (GUILayout.Button("Copy")) + { + positionClipboard = ((Transform)target).localPosition; + rotationClipboard = ((Transform)target).localRotation; + scaleClipboard = ((Transform)target).localScale; + } + + if (!positionClipboard.HasValue) EditorGUI.BeginDisabledGroup(true); + if (GUILayout.Button("Paste")) + { + Undo.RecordObjects(targets, "Paste Clipboard Values"); + for (int i = 0; i < targets.Length; i++) + { + ((Transform)targets[i]).localPosition = positionClipboard.Value; + ((Transform)targets[i]).localRotation = rotationClipboard.Value; + ((Transform)targets[i]).localScale = scaleClipboard.Value; + } + GUI.FocusControl(null); + } + if (!positionClipboard.HasValue) EditorGUI.EndDisabledGroup(); + GUILayout.EndHorizontal(); + } + + // Advanced Paste Tools GUI + if (EditorPrefs.GetBool(SHOW_ADVANCED_PASTE_TOOLS_KEY)) + { + GUILayout.BeginHorizontal(); + + if (!positionClipboard.HasValue) EditorGUI.BeginDisabledGroup(true); + if (GUILayout.Button("Paste position")) + { + Undo.RecordObjects(targets, "Paste Position Clipboard Value"); + for (int i = 0; i < targets.Length; i++) + { + ((Transform)targets[i]).localPosition = positionClipboard.Value; + } + GUI.FocusControl(null); + } + + if (GUILayout.Button("Paste rotation")) + { + Undo.RecordObjects(targets, "Paste Rotation Clipboard Value"); + for (int i = 0; i < targets.Length; i++) + { + ((Transform)targets[i]).rotation = rotationClipboard.Value; + } + GUI.FocusControl(null); + } + + if (GUILayout.Button("Paste scale")) + { + Undo.RecordObjects(targets, "Paste Scale Clipboard Value"); + for (int i = 0; i < targets.Length; i++) + { + ((Transform)targets[i]).localScale = scaleClipboard.Value; + } + GUI.FocusControl(null); + } + if (!positionClipboard.HasValue) EditorGUI.EndDisabledGroup(); + + GUILayout.EndHorizontal(); + } + + // Clipboard GUI + if (EditorPrefs.GetBool(SHOW_CLIPBOARD_INFORMATIONS_KEY)) + { + if (positionClipboard.HasValue && rotationClipboard.HasValue && scaleClipboard.HasValue) + { + + GUIStyle helpboxStyle = new GUIStyle(EditorStyles.helpBox); + helpboxStyle.richText = true; + + EditorGUILayout.TextArea("Clipboard values :\n" + + "Position : " + positionClipboard.Value.ToString("f2") + "\n" + + "Rotation : " + rotationClipboard.Value.ToString("f2") + "\n" + + "Scale : " + scaleClipboard.Value.ToString("f2"), helpboxStyle); + } + } + + + // Shortcuts GUI - Related to InspectorShortcuts.cs https://github.com/VoxelBoy/Useful-Unity-Scripts/blob/master/InspectorShortcuts.cs + if (EditorPrefs.GetBool(SHOW_SHORTCUTS_KEY)) + { + EditorGUILayout.HelpBox("Inspector shortcuts :\n" + + "Toggle inspector lock : Ctrl + Shift + L\n" + + "Toggle inspector mode : Ctrl + Shift + D", MessageType.None); + } + } + Rect endRect = GUILayoutUtility.GetLastRect(); + endRect.y += endRect.height; + + + #region Context Menu + Rect componentRect = new Rect(beginRect.x, beginRect.y, beginRect.width, endRect.y - beginRect.y); + //EditorGUI.DrawRect(componentRect, Color.green); // Debug : display GenericMenu zone + + Event currentEvent = Event.current; + + if (currentEvent.type == EventType.ContextClick) + { + if (componentRect.Contains(currentEvent.mousePosition)) + { + GUI.FocusControl(null); + + GenericMenu menu = new GenericMenu(); + + menu.AddItem(new GUIContent("Display/Tools"), EditorPrefs.GetBool(SHOW_TOOLS_KEY), ToggleOption, SHOW_TOOLS_KEY); + menu.AddSeparator("Display/"); + menu.AddItem(new GUIContent("Display/Reset Tools"), EditorPrefs.GetBool(SHOW_RESET_TOOLS_KEY), ToggleOption, SHOW_RESET_TOOLS_KEY); + menu.AddItem(new GUIContent("Display/Paste Tools"), EditorPrefs.GetBool(SHOW_PASTE_TOOLS_KEY), ToggleOption, SHOW_PASTE_TOOLS_KEY); + menu.AddItem(new GUIContent("Display/Advanced Paste Tools"), EditorPrefs.GetBool(SHOW_ADVANCED_PASTE_TOOLS_KEY), ToggleOption, SHOW_ADVANCED_PASTE_TOOLS_KEY); + menu.AddItem(new GUIContent("Display/Clipboard informations"), EditorPrefs.GetBool(SHOW_CLIPBOARD_INFORMATIONS_KEY), ToggleOption, SHOW_CLIPBOARD_INFORMATIONS_KEY); + menu.AddItem(new GUIContent("Display/Shortcuts informations"), EditorPrefs.GetBool(SHOW_SHORTCUTS_KEY), ToggleOption, SHOW_SHORTCUTS_KEY); + + // Round menu + menu.AddItem(new GUIContent("Round/Three Decimals"), false, Round, 3); + menu.AddItem(new GUIContent("Round/Two Decimals"), false, Round, 2); + menu.AddItem(new GUIContent("Round/One Decimal"), false, Round, 1); + menu.AddItem(new GUIContent("Round/Integer"), false, Round, 0); + + // Truncate menu + menu.AddItem(new GUIContent("Truncate/Three Decimals"), false, Truncate, 3); + menu.AddItem(new GUIContent("Truncate/Two Decimals"), false, Truncate, 2); + menu.AddItem(new GUIContent("Truncate/One Decimal"), false, Truncate, 1); + menu.AddItem(new GUIContent("Truncate/Integer"), false, Truncate, 0); + + menu.ShowAsContext(); + currentEvent.Use(); + } + } + #endregion + + serializedObject.ApplyModifiedProperties(); + } + + + private bool ValidatePosition(Vector3 position) + { + if (Mathf.Abs(position.x) > POSITION_MAX) return false; + if (Mathf.Abs(position.y) > POSITION_MAX) return false; + if (Mathf.Abs(position.z) > POSITION_MAX) return false; + return true; + } + + private void PositionPropertyField(SerializedProperty positionProperty, GUIContent content) + { + Transform transform = (Transform)targets[0]; + Vector3 localPosition = transform.localPosition; + for (int i = 0; i < targets.Length; i++) + { + if (!localPosition.Equals(((Transform)targets[i]).localPosition)) + { + EditorGUI.showMixedValue = true; + break; + } + } + + EditorGUI.BeginChangeCheck(); + Vector3 newLocalPosition = EditorGUILayout.Vector3Field(content, localPosition); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObjects(targets, "Position Changed"); + for (int i = 0; i < targets.Length; i++) + { + ((Transform)targets[i]).localPosition = newLocalPosition; + } + positionProperty.serializedObject.SetIsDifferentCacheDirty(); + } + EditorGUI.showMixedValue = false; + } + + private void RotationPropertyField(SerializedProperty rotationProperty, GUIContent content) + { + Transform transform = (Transform)targets[0]; + Vector3 localRotation = TransformUtils.GetInspectorRotation(transform); + + + for (int i = 0; i < targets.Length; i++) + { + if (!localRotation.Equals(TransformUtils.GetInspectorRotation((Transform)targets[i]))) + { + EditorGUI.showMixedValue = true; + break; + } + } + + EditorGUI.BeginChangeCheck(); + Vector3 eulerAngles = EditorGUILayout.Vector3Field(content, localRotation); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObjects(targets, "Rotation Changed"); + for (int i = 0; i < targets.Length; i++) + { + //((Transform)targets[i]).localEulerAngles = eulerAngles; + TransformUtils.SetInspectorRotation(((Transform)targets[i]), eulerAngles); + } + rotationProperty.serializedObject.SetIsDifferentCacheDirty(); + } + EditorGUI.showMixedValue = false; + } + + private void ScalePropertyField(SerializedProperty scaleProperty, GUIContent content) + { + Transform transform = (Transform)targets[0]; + Vector3 localScale = transform.localScale; + for (int i = 0; i < targets.Length; i++) + { + if (!localScale.Equals(((Transform)targets[i]).localScale)) + { + EditorGUI.showMixedValue = true; + break; + } + } + + EditorGUI.BeginChangeCheck(); + Vector3 newLocalScale = EditorGUILayout.Vector3Field(content, localScale); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObjects(targets, "Scale Changed"); + for (int i = 0; i < targets.Length; i++) + { + ((Transform)targets[i]).localScale = newLocalScale; + } + scaleProperty.serializedObject.SetIsDifferentCacheDirty(); + } + EditorGUI.showMixedValue = false; + } + + + #region Generic Menu Callbacks + private void ToggleOption(object obj) + { + EditorPrefs.SetBool(obj.ToString(), !EditorPrefs.GetBool(obj.ToString())); + } + + /// Round all values of the Transform to a given number of decimals + private void Round(object objNumberOfDecimals) + { + int numberOfDecimals = (int)objNumberOfDecimals; + + Undo.RecordObjects(targets, "Round to " + numberOfDecimals + " decimals"); + for (int i = 0; i < targets.Length; i++) + { + ((Transform)targets[i]).localPosition = RoundVector(((Transform)targets[i]).localPosition, numberOfDecimals); + ((Transform)targets[i]).localEulerAngles = RoundVector(((Transform)targets[i]).localEulerAngles, numberOfDecimals); + ((Transform)targets[i]).localScale = RoundVector(((Transform)targets[i]).localScale, numberOfDecimals); + } + } + + /// Round all components of a Vector3 + private Vector3 RoundVector(Vector3 vector, int numberOfDecimals) + { + vector.x = Mathf.Round(vector.x * Mathf.Pow(10.0f, (float)numberOfDecimals)) / Mathf.Pow(10.0f, (float)numberOfDecimals); + vector.y = Mathf.Round(vector.y * Mathf.Pow(10.0f, (float)numberOfDecimals)) / Mathf.Pow(10.0f, (float)numberOfDecimals); + vector.z = Mathf.Round(vector.z * Mathf.Pow(10.0f, (float)numberOfDecimals)) / Mathf.Pow(10.0f, (float)numberOfDecimals); + return vector; + } + + /// Truncate all values of the Transform to a given number of decimals + private void Truncate(object objNumberOfDecimals) + { + int numberOfDecimals = (int)objNumberOfDecimals; + + Undo.RecordObjects(targets, "Truncate to " + numberOfDecimals + " decimals"); + for (int i = 0; i < targets.Length; i++) + { + ((Transform)targets[i]).localPosition = TruncateVector(((Transform)targets[i]).localPosition, numberOfDecimals); + ((Transform)targets[i]).localEulerAngles = TruncateVector(((Transform)targets[i]).localEulerAngles, numberOfDecimals); + ((Transform)targets[i]).localScale = TruncateVector(((Transform)targets[i]).localScale, numberOfDecimals); + } + } + + /// Truncate all components of a Vector3 + private Vector3 TruncateVector(Vector3 vector, int numberOfDecimals) + { + vector.x = Mathf.Floor(vector.x * Mathf.Pow(10.0f, (float)numberOfDecimals)) / Mathf.Pow(10.0f, (float)numberOfDecimals); + vector.y = Mathf.Floor(vector.y * Mathf.Pow(10.0f, (float)numberOfDecimals)) / Mathf.Pow(10.0f, (float)numberOfDecimals); + vector.z = Mathf.Floor(vector.z * Mathf.Pow(10.0f, (float)numberOfDecimals)) / Mathf.Pow(10.0f, (float)numberOfDecimals); + return vector; + } + #endregion + } +} diff --git a/Assets/Scripts/Editor/GameObject.meta b/Assets/Scripts/Editor/GameObject.meta new file mode 100644 index 0000000..ea83061 --- /dev/null +++ b/Assets/Scripts/Editor/GameObject.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: dda0f0ad5057e2244b9a17ccd5031e99 +folderAsset: yes +timeCreated: 1594958191 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/GameObject/ResetTransform.cs b/Assets/Scripts/Editor/GameObject/ResetTransform.cs new file mode 100644 index 0000000..8726d41 --- /dev/null +++ b/Assets/Scripts/Editor/GameObject/ResetTransform.cs @@ -0,0 +1,25 @@ +using UnityEngine; +using UnityEditor; + +// reset transform position, rotation and scale + +namespace UnityLibrary +{ + public class ResetTransform : ScriptableObject + { + [MenuItem("GameObject/Reset Transform #r")] + static public void MoveSceneViewCamera() + { + // TODO add multiple object support + var go = Selection.activeGameObject; + if (go != null) + { + // TODO: add undo + go.transform.position = Vector3.zero; + go.transform.rotation = Quaternion.identity; + go.transform.localScale = Vector3.one; + } + } + + } // class +} // namespace diff --git a/Assets/Scripts/Editor/GameObject/ResetTransform.cs.meta b/Assets/Scripts/Editor/GameObject/ResetTransform.cs.meta new file mode 100644 index 0000000..0cc89a0 --- /dev/null +++ b/Assets/Scripts/Editor/GameObject/ResetTransform.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 51c038ebd5a3e0d4b92a12f03a73b6ea +timeCreated: 1594958193 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Gizmos/RendererBoundsGizmo.cs b/Assets/Scripts/Editor/Gizmos/RendererBoundsGizmo.cs new file mode 100644 index 0000000..084224f --- /dev/null +++ b/Assets/Scripts/Editor/Gizmos/RendererBoundsGizmo.cs @@ -0,0 +1,19 @@ +// attach this to mesh, draws renderer bounds when gameobject is selected +// original source: http://answers.unity.com/answers/137475/view.html + +using UnityEngine; + +namespace UnityLibrary +{ + public class RendererBoundsGizmo : MonoBehaviour + { + void OnDrawGizmosSelected() + { + Gizmos.color = Color.yellow; + //center sphere + //Gizmos.DrawSphere(transform.position, 0.1f); + var r = transform.GetComponent(); + if (r != null) Gizmos.DrawWireCube(transform.position, r.bounds.size); + } + } +} diff --git a/Assets/Scripts/Editor/Gizmos/RendererBoundsGizmo.cs.meta b/Assets/Scripts/Editor/Gizmos/RendererBoundsGizmo.cs.meta new file mode 100644 index 0000000..d097268 --- /dev/null +++ b/Assets/Scripts/Editor/Gizmos/RendererBoundsGizmo.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f1bf2afb27df5364dab899f318af7f69 +timeCreated: 1594958195 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Hierarchy.meta b/Assets/Scripts/Editor/Hierarchy.meta new file mode 100644 index 0000000..d0052a8 --- /dev/null +++ b/Assets/Scripts/Editor/Hierarchy.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4ad868ac71006a0418c8df13616a4c3e +folderAsset: yes +timeCreated: 1594958190 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Hierarchy/MoveAround.cs b/Assets/Scripts/Editor/Hierarchy/MoveAround.cs new file mode 100644 index 0000000..1ac886c --- /dev/null +++ b/Assets/Scripts/Editor/Hierarchy/MoveAround.cs @@ -0,0 +1,77 @@ +// Simple shortcuts for moving selected GameObject around in hierarchy by Factuall +// SHIFT + CTRL + ALT + +// W - Move it up in hierarchy +// S - Move it down in hierarchy +// A - Unparent it down +// D - Parent it to next object in hierarchy + +using UnityEditor; + +namespace UnityLibrary +{ + public class UnparentMe + { + [MenuItem("GameObject/Unparent %#&a")] + static void Detach() + { + + if (Selection.activeGameObject != null && Selection.activeGameObject.transform.parent != null) + { + int newIndex = Selection.activeGameObject.transform.parent.GetSiblingIndex(); + Undo.SetTransformParent(Selection.activeGameObject.transform, Selection.activeGameObject.transform.parent.parent, "unparent selection"); + Selection.activeGameObject.transform.SetSiblingIndex(newIndex + 1); + } + } + [MenuItem("GameObject/ParentDown %#&d")] + static void ParentDown() + { + if (Selection.activeGameObject != null) + { + int parentChildCount = Selection.activeGameObject.transform.parent == null ? + Selection.activeGameObject.scene.rootCount : Selection.activeGameObject.transform.parent.childCount; + if (Selection.activeGameObject.transform.GetSiblingIndex() == parentChildCount - 1) return; + if (Selection.activeGameObject.transform.parent != null) + { + if (Selection.activeGameObject.transform.parent.childCount + 1 > Selection.activeGameObject.transform.GetSiblingIndex()) + Undo.SetTransformParent(Selection.activeGameObject.transform, Selection.activeGameObject.transform.parent.GetChild(Selection.activeGameObject.transform.GetSiblingIndex() + 1), "parent selection down in hierarchy"); + + } + else + { + if (Selection.activeGameObject.scene.rootCount + 1 > Selection.activeGameObject.transform.GetSiblingIndex()) + Undo.SetTransformParent(Selection.activeGameObject.transform, Selection.activeGameObject.scene.GetRootGameObjects()[Selection.activeGameObject.transform.GetSiblingIndex() + 1].transform, "parent selection down in hierarchy"); + } + } + + } + [MenuItem("GameObject/Moveup %#&w")] + static void MoveUp() + { + if (Selection.activeGameObject != null) + { + + if (Selection.activeGameObject.transform.GetSiblingIndex() != 0) + { + Undo.RegisterCompleteObjectUndo(Selection.activeGameObject.transform, "move selction up in hierarchy"); + Selection.activeGameObject.transform.SetSiblingIndex(Selection.activeGameObject.transform.GetSiblingIndex() - 1); + } + + } + } + [MenuItem("GameObject/Movedown %#&s")] + static void MoveDown() + { + if (Selection.activeGameObject != null) + { + int parentChildCount = Selection.activeGameObject.transform.parent == null ? + Selection.activeGameObject.scene.rootCount : Selection.activeGameObject.transform.parent.childCount; + if (Selection.activeGameObject.transform.GetSiblingIndex() != parentChildCount - 1) + { + Undo.RegisterCompleteObjectUndo(Selection.activeGameObject.transform, "move selction down in hierarchy"); + Selection.activeGameObject.transform.SetSiblingIndex(Selection.activeGameObject.transform.GetSiblingIndex() + 1); + } + + } + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Editor/Hierarchy/MoveAround.cs.meta b/Assets/Scripts/Editor/Hierarchy/MoveAround.cs.meta new file mode 100644 index 0000000..41e518a --- /dev/null +++ b/Assets/Scripts/Editor/Hierarchy/MoveAround.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 18fe530f4fbd8b74096f07f377a4b9ff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Hierarchy/UnparentMe.cs b/Assets/Scripts/Editor/Hierarchy/UnparentMe.cs new file mode 100644 index 0000000..18e75b1 --- /dev/null +++ b/Assets/Scripts/Editor/Hierarchy/UnparentMe.cs @@ -0,0 +1,21 @@ +// unparents selected gameobject in hierarchy (by moving to grandparents if available) + +using UnityEditor; + +namespace UnityLibrary +{ + public class UnparentMe + { + // https://docs.unity3d.com/ScriptReference/MenuItem.html + // shift U shortcut key + [MenuItem("GameObject/Unparent #u")] + static void UnParent() + { + // TODO: add undo + if (Selection.activeGameObject != null && Selection.activeGameObject.transform.parent != null) + { + Selection.activeGameObject.transform.parent = Selection.activeGameObject.transform.parent.parent; + } + } + } +} diff --git a/Assets/Scripts/Editor/Hierarchy/UnparentMe.cs.meta b/Assets/Scripts/Editor/Hierarchy/UnparentMe.cs.meta new file mode 100644 index 0000000..f0a2192 --- /dev/null +++ b/Assets/Scripts/Editor/Hierarchy/UnparentMe.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 859aeadcffa51fe4f9cc875774621ef9 +timeCreated: 1594958194 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Importers/AnimationClipListImporter.cs b/Assets/Scripts/Editor/Importers/AnimationClipListImporter.cs new file mode 100644 index 0000000..733ac03 --- /dev/null +++ b/Assets/Scripts/Editor/Importers/AnimationClipListImporter.cs @@ -0,0 +1,65 @@ +// Checks for a .txt file with the same name as an imported .fbx file (in Assets/Models/ folder), containing a list of animation clips to add to the ModelImporter. +// .txt file should be tab-delimited with the following columns: "title", "start frame", "end frame" (and optional description, not used). +// example: +// Take0 10 40 asdf +// Take1 50 80 wasdf.. + +using System; +using System.IO; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace UnityLibrary.Importers +{ + public class AnimationClipListImporter : AssetPostprocessor + { + void OnPreprocessModel() + { + ModelImporter modelImporter = assetImporter as ModelImporter; + if (modelImporter == null) return; + + string assetPath = assetImporter.assetPath; + if (!assetPath.StartsWith("Assets/Models") || !assetPath.EndsWith(".fbx", StringComparison.OrdinalIgnoreCase)) return; + + string txtPath = Path.ChangeExtension(assetPath, ".txt"); + if (!File.Exists(txtPath)) return; + + try + { + List clips = new List(); + string[] lines = File.ReadAllLines(txtPath); + + foreach (string line in lines) + { + string[] parts = line.Split('\t'); + if (parts.Length < 3) continue; // Ensure we have at least "title, start, end" + + string title = parts[0].Trim(); + if (!int.TryParse(parts[1], out int startFrame) || !int.TryParse(parts[2], out int endFrame)) + continue; + + ModelImporterClipAnimation clip = new ModelImporterClipAnimation + { + name = title, + firstFrame = startFrame, + lastFrame = endFrame, + loopTime = false + }; + + clips.Add(clip); + } + + if (clips.Count > 0) + { + modelImporter.clipAnimations = clips.ToArray(); + Debug.Log($"Added {clips.Count} animation clips to {assetPath}"); + } + } + catch (Exception ex) + { + Debug.LogError($"Failed to process animation data for {assetPath}: {ex.Message}"); + } + } + } +} diff --git a/Assets/Scripts/Editor/Mesh.meta b/Assets/Scripts/Editor/Mesh.meta new file mode 100644 index 0000000..bf539ea --- /dev/null +++ b/Assets/Scripts/Editor/Mesh.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f45eaf3f880e5c04785b1cdca6b98021 +folderAsset: yes +timeCreated: 1594958191 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Mesh/CreatePlane.cs b/Assets/Scripts/Editor/Mesh/CreatePlane.cs new file mode 100644 index 0000000..f2633c1 --- /dev/null +++ b/Assets/Scripts/Editor/Mesh/CreatePlane.cs @@ -0,0 +1,227 @@ +// editor tools to create mesh plane with adjustable resolution +// original : http://wiki.unity3d.com/index.php?title=CreatePlane#C.23_-_CreatePlane.cs + +using UnityEngine; +using UnityEditor; +using System.Collections; + +namespace UnityLibrary +{ + public class CreatePlane : ScriptableWizard + { + + public enum Orientation + { + Horizontal, + Vertical + } + + public enum AnchorPoint + { + TopLeft, + TopHalf, + TopRight, + RightHalf, + BottomRight, + BottomHalf, + BottomLeft, + LeftHalf, + Center + } + + public int widthSegments = 1; + public int lengthSegments = 1; + public float width = 1.0f; + public float length = 1.0f; + public Orientation orientation = Orientation.Horizontal; + public AnchorPoint anchor = AnchorPoint.Center; + public bool addCollider = false; + public bool createAtOrigin = true; + public bool flipYZ = false; + public bool twoSided = false; + public string optionalName; + + static Camera cam; + static Camera lastUsedCam; + + + [MenuItem("GameObject/Create Other/Custom Plane...")] + static void CreateWizard() + { + cam = Camera.current; + // Hack because camera.current doesn't return editor camera if scene view doesn't have focus + if (!cam) + cam = lastUsedCam; + else + lastUsedCam = cam; + ScriptableWizard.DisplayWizard("Create Plane",typeof(CreatePlane)); + } + + + void OnWizardUpdate() + { + widthSegments = Mathf.Clamp(widthSegments, 1, 254); + lengthSegments = Mathf.Clamp(lengthSegments, 1, 254); + } + + + void OnWizardCreate() + { + GameObject plane = new GameObject(); + + if (!string.IsNullOrEmpty(optionalName)) + plane.name = optionalName; + else + plane.name = "Plane"; + + if (!createAtOrigin && cam) + plane.transform.position = cam.transform.position + cam.transform.forward*5.0f; + else + plane.transform.position = Vector3.zero; + + Vector2 anchorOffset; + string anchorId; + switch (anchor) + { + case AnchorPoint.TopLeft: + anchorOffset = new Vector2(-width/2.0f,length/2.0f); + anchorId = "TL"; + break; + case AnchorPoint.TopHalf: + anchorOffset = new Vector2(0.0f,length/2.0f); + anchorId = "TH"; + break; + case AnchorPoint.TopRight: + anchorOffset = new Vector2(width/2.0f,length/2.0f); + anchorId = "TR"; + break; + case AnchorPoint.RightHalf: + anchorOffset = new Vector2(width/2.0f,0.0f); + anchorId = "RH"; + break; + case AnchorPoint.BottomRight: + anchorOffset = new Vector2(width/2.0f,-length/2.0f); + anchorId = "BR"; + break; + case AnchorPoint.BottomHalf: + anchorOffset = new Vector2(0.0f,-length/2.0f); + anchorId = "BH"; + break; + case AnchorPoint.BottomLeft: + anchorOffset = new Vector2(-width/2.0f,-length/2.0f); + anchorId = "BL"; + break; + case AnchorPoint.LeftHalf: + anchorOffset = new Vector2(-width/2.0f,0.0f); + anchorId = "LH"; + break; + case AnchorPoint.Center: + default: + anchorOffset = Vector2.zero; + anchorId = "C"; + break; + } + + MeshFilter meshFilter = (MeshFilter)plane.AddComponent(typeof(MeshFilter)); + plane.AddComponent(typeof(MeshRenderer)); + + string planeAssetName = plane.name + widthSegments + "x" + lengthSegments + "W" + width + "L" + length + (orientation == Orientation.Horizontal? "H" : "V") + anchorId + ".asset"; + Mesh m = (Mesh)AssetDatabase.LoadAssetAtPath("Assets/Editor/" + planeAssetName,typeof(Mesh)); + + if (m == null) + { + m = new Mesh(); + m.name = plane.name; + + int hCount2 = widthSegments+1; + int vCount2 = lengthSegments+1; + int numTriangles = widthSegments * lengthSegments * 6; + if (twoSided) { + numTriangles *= 2; + } + int numVertices = hCount2 * vCount2; + + Vector3[] vertices = new Vector3[numVertices]; + Vector2[] uvs = new Vector2[numVertices]; + int[] triangles = new int[numTriangles]; + + int index = 0; + float uvFactorX = 1.0f/widthSegments; + float uvFactorY = 1.0f/lengthSegments; + float scaleX = width/widthSegments; + float scaleY = length/lengthSegments; + for (float y = 0.0f; y < vCount2; y++) + { + for (float x = 0.0f; x < hCount2; x++) + { + if (orientation == Orientation.Horizontal) + { + if (flipYZ) + { + vertices[index] = new Vector3(x*scaleX - width/2f - anchorOffset.x, y*scaleY - length/2f - anchorOffset.y, 0.0f); + }else{ + vertices[index] = new Vector3(x*scaleX - width/2f - anchorOffset.x, 0.0f, y*scaleY - length/2f - anchorOffset.y); + } + } + else + { + if (flipYZ) + { + vertices[index] = new Vector3(x*scaleX - width/2f - anchorOffset.x, 0.0f, y*scaleY - length/2f - anchorOffset.y); + }else{ + vertices[index] = new Vector3(x*scaleX - width/2f - anchorOffset.x, y*scaleY - length/2f - anchorOffset.y, 0.0f); + } + } + uvs[index++] = new Vector2(x*uvFactorX, y*uvFactorY); + } + } + + index = 0; + for (int y = 0; y < lengthSegments; y++) + { + for (int x = 0; x < widthSegments; x++) + { + triangles[index] = (y * hCount2) + x; + triangles[index+1] = ((y+1) * hCount2) + x; + triangles[index+2] = (y * hCount2) + x + 1; + + triangles[index+3] = ((y+1) * hCount2) + x; + triangles[index+4] = ((y+1) * hCount2) + x + 1; + triangles[index+5] = (y * hCount2) + x + 1; + index += 6; + } + if (twoSided) { + // Same tri vertices with order reversed, so normals point in the opposite direction + for (int x = 0; x < widthSegments; x++) + { + triangles[index] = (y * hCount2) + x; + triangles[index+1] = (y * hCount2) + x + 1; + triangles[index+2] = ((y+1) * hCount2) + x; + + triangles[index+3] = ((y+1) * hCount2) + x; + triangles[index+4] = (y * hCount2) + x + 1; + triangles[index+5] = ((y+1) * hCount2) + x + 1; + index += 6; + } + } + } + + m.vertices = vertices; + m.uv = uvs; + m.triangles = triangles; + m.RecalculateNormals(); + + AssetDatabase.CreateAsset(m, "Assets/Editor/" + planeAssetName); + AssetDatabase.SaveAssets(); + } + + meshFilter.sharedMesh = m; + m.RecalculateBounds(); + + if (addCollider) + plane.AddComponent(typeof(BoxCollider)); + + Selection.activeObject = plane; + } + } + } diff --git a/Assets/Scripts/Editor/Mesh/CreatePlane.cs.meta b/Assets/Scripts/Editor/Mesh/CreatePlane.cs.meta new file mode 100644 index 0000000..e2ec4a4 --- /dev/null +++ b/Assets/Scripts/Editor/Mesh/CreatePlane.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d1cea26cb1deacf48b0dd190be08a597 +timeCreated: 1594958194 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Mesh/MeshCombineWizard.cs b/Assets/Scripts/Editor/Mesh/MeshCombineWizard.cs new file mode 100644 index 0000000..5406c35 --- /dev/null +++ b/Assets/Scripts/Editor/Mesh/MeshCombineWizard.cs @@ -0,0 +1,127 @@ +// from https://forum.unity.com/threads/mesh-combine-wizard-free-unity-tool-source-code.444483/#post-5575042 + +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Linq; + +namespace UnityLibrary +{ + public class MeshCombineWizard : ScriptableWizard + { + public GameObject parentOfObjectsToCombine; + + [MenuItem("E.S. Tools/Mesh Combine Wizard")] + static void CreateWizard() + { + ScriptableWizard.DisplayWizard("Mesh Combine Wizard"); + } + + void OnWizardCreate() + { + if (parentOfObjectsToCombine == null) return; + + Vector3 originalPosition = parentOfObjectsToCombine.transform.position; + parentOfObjectsToCombine.transform.position = Vector3.zero; + + MeshFilter[] meshFilters = parentOfObjectsToCombine.GetComponentsInChildren(); + Dictionary> materialToMeshFilterList = new Dictionary>(); + List combinedObjects = new List(); + + for (int i = 0; i < meshFilters.Length; i++) + { + var materials = meshFilters[i].GetComponent().sharedMaterials; + if (materials == null) continue; + if (materials.Length > 1) + { + parentOfObjectsToCombine.transform.position = originalPosition; + Debug.LogError("Objects with multiple materials on the same mesh are not supported. Create multiple meshes from this object's sub-meshes in an external 3D tool and assign separate materials to each."); + return; + } + var material = materials[0]; + if (materialToMeshFilterList.ContainsKey(material)) materialToMeshFilterList[material].Add(meshFilters[i]); + else materialToMeshFilterList.Add(material, new List() { meshFilters[i] }); + } + + + // NC 03/2020 changes the loop to create meshes smaller than 695536 vertices + foreach (var entry in materialToMeshFilterList) + { + // get list of each meshes order by number of vertices + List meshesWithSameMaterial = entry.Value.OrderByDescending(mf => mf.sharedMesh.vertexCount).ToList(); + // split into bins of 65536 vertices max + int nrMeshes = meshesWithSameMaterial.Count; + while (nrMeshes > 0) + { + string materialName = entry.Key.ToString().Split(' ')[0]; + List meshBin = new List(); + meshBin.Add(meshesWithSameMaterial[0]); + meshesWithSameMaterial.RemoveAt(0); + nrMeshes--; + // add meshes in bin until 65536 vertices is reached + for (int i = 0; i < meshesWithSameMaterial.Count; i++) + { + if (meshBin.Sum(mf => mf.sharedMesh.vertexCount) + meshesWithSameMaterial[i].sharedMesh.vertexCount < 65536) + { + meshBin.Add(meshesWithSameMaterial[i]); + meshesWithSameMaterial.RemoveAt(i); + i--; + nrMeshes--; + } + } + + // merge this bin + CombineInstance[] combine = new CombineInstance[meshBin.Count]; + for (int i = 0; i < meshBin.Count; i++) + { + combine[i].mesh = meshBin[i].sharedMesh; + combine[i].transform = meshBin[i].transform.localToWorldMatrix; + } + Mesh combinedMesh = new Mesh(); + combinedMesh.CombineMeshes(combine); + + // save the mesh + materialName += "_" + combinedMesh.GetInstanceID(); + if (meshBin.Count > 1) + { + AssetDatabase.CreateAsset(combinedMesh, "Assets/CombinedMeshes_" + materialName + ".asset"); ; + } + + // assign the mesh to a new go + string goName = (materialToMeshFilterList.Count > 1) ? "CombinedMeshes_" + materialName : "CombinedMeshes_" + parentOfObjectsToCombine.name; + GameObject combinedObject = new GameObject(goName); + var filter = combinedObject.AddComponent(); + if (meshBin.Count > 1) + { + filter.sharedMesh = combinedMesh; + } + else + { + filter.sharedMesh = meshBin[0].sharedMesh; // the original mesh + } + var renderer = combinedObject.AddComponent(); + renderer.sharedMaterial = entry.Key; + combinedObjects.Add(combinedObject); + } + } + + GameObject resultGO = null; + if (combinedObjects.Count > 1) + { + resultGO = new GameObject("CombinedMeshes_" + parentOfObjectsToCombine.name); + foreach (var combinedObject in combinedObjects) combinedObject.transform.parent = resultGO.transform; + } + else + { + resultGO = combinedObjects[0]; + } + + Object prefab = PrefabUtility.CreateEmptyPrefab("Assets/" + resultGO.name + ".prefab"); + PrefabUtility.ReplacePrefab(resultGO, prefab, ReplacePrefabOptions.ConnectToPrefab); + + parentOfObjectsToCombine.SetActive(false); + parentOfObjectsToCombine.transform.position = originalPosition; + resultGO.transform.position = originalPosition; + } + } +} diff --git a/Assets/Scripts/Editor/Mesh/MeshCombineWizard.cs.meta b/Assets/Scripts/Editor/Mesh/MeshCombineWizard.cs.meta new file mode 100644 index 0000000..69ac2e2 --- /dev/null +++ b/Assets/Scripts/Editor/Mesh/MeshCombineWizard.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 72fbe9dd2dbf0f845ab4d30da0d8b27c +timeCreated: 1594958194 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Tools/ColorPickerWindow.cs.meta b/Assets/Scripts/Editor/Tools/ColorPickerWindow.cs.meta new file mode 100644 index 0000000..d8f24d1 --- /dev/null +++ b/Assets/Scripts/Editor/Tools/ColorPickerWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 333163797deb57f4a8d7373ac970d9bf +timeCreated: 1594958193 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Tools/CompileTime.cs b/Assets/Scripts/Editor/Tools/CompileTime.cs new file mode 100644 index 0000000..89721bc --- /dev/null +++ b/Assets/Scripts/Editor/Tools/CompileTime.cs @@ -0,0 +1,201 @@ +// compile time tracking tool (and quickly enable disable settings, and scene autosave option) +// original source: https://gist.github.com/spajus/72a74146b1bbeddd44a66e1b8a3c829c +// created by https://github.com/spajus twitch https://www.twitch.tv/dev_spajus +// 02.07.2020 added unity_2018_4 check and set autosave off by default - unitycoder.com + +using System; +using System.Collections.Generic; +using UnityEditor; +using UnityEditor.Compilation; +using UnityEditor.SceneManagement; +using UnityEngine; + +namespace UnityLibrary +{ + class CompileTime : EditorWindow + { + bool allowProfiler = false; + bool isTrackingTime; + bool isLockReload; + bool isAutoSave = false; // autosave default off + bool isLocked; + bool restartAfterCompile; + bool memoryWarned; + string lastReloadTime = ""; + string lastCompileTime = ""; + string lastAssCompileTime = ""; + double startTime, finishTime, compileTime, reloadTime; + double assStartTime, assFinishTime, assCompileTime; + Dictionary startTimes = new Dictionary(); + List lastAssCompile; + + [MenuItem("Tools/UnityLibrary/Compile Time")] + public static void Init() + { + EditorWindow.GetWindow(typeof(CompileTime)); + } + + void Update() + { + if (isLockReload) { return; } + if (EditorApplication.isCompiling && !isTrackingTime) + { + if (EditorApplication.isPlaying) + { + restartAfterCompile = true; + EditorApplication.isPlaying = false; + } + startTime = EditorApplication.timeSinceStartup; + lastReloadTime = "Reloading now"; + lastCompileTime = "Compiling now"; + lastAssCompile = new List(); + Debug.Log("Started compiling scripts"); + isTrackingTime = true; + } + else if (!EditorApplication.isCompiling && isTrackingTime) + { + finishTime = EditorApplication.timeSinceStartup; + isTrackingTime = false; + EditorApplication.Beep(); + reloadTime = finishTime - startTime; + lastReloadTime = reloadTime.ToString("0.000") + "s"; + compileTime = reloadTime - assCompileTime; + lastCompileTime = compileTime.ToString("0.000") + "s"; + if (isAutoSave && !EditorApplication.isPlaying) + { + Debug.Log("Auto Saving Scene"); + EditorSceneManager.SaveOpenScenes(); + } + if (restartAfterCompile) + { + restartAfterCompile = false; + EditorApplication.isPlaying = true; + } + } + } + + void OnGUI() + { +#if UNITY_2018_4_OR_NEWER + // Toggle domain reload + var playModeOptsEnabled = EditorSettings.enterPlayModeOptionsEnabled; + playModeOptsEnabled = EditorGUILayout.Toggle("Disable Domain Reload", playModeOptsEnabled); + EditorSettings.enterPlayModeOptionsEnabled = playModeOptsEnabled; +#endif + + if (UnityEngine.Profiling.Profiler.enabled) + { + EditorGUILayout.LabelField("PROFILER ENABLED"); + } + allowProfiler = EditorGUILayout.Toggle("Allow profiler", allowProfiler); + if (!allowProfiler && UnityEngine.Profiling.Profiler.enabled) + { + UnityEngine.Profiling.Profiler.enabled = false; + } + EditorGUILayout.LabelField("Time", Time.realtimeSinceStartup.ToString()); + float m1 = (UnityEngine.Profiling.Profiler.GetTotalAllocatedMemoryLong() / 1024f / 1024f); + float m2 = (UnityEngine.Profiling.Profiler.GetAllocatedMemoryForGraphicsDriver() / 1024f / 1024f); + float m3 = (UnityEngine.Profiling.Profiler.GetTotalReservedMemoryLong() / 1024f / 1024f); + float m = m1 + m2 + m3; + if (m > 10000 && !memoryWarned) + { + memoryWarned = true; + EditorApplication.Beep(); + Debug.LogError("Memory over 10000MB!"); + allowProfiler = false; + UnityEngine.Profiling.Profiler.enabled = false; + } + if (m < 8000 && memoryWarned) + { + memoryWarned = false; + } + EditorGUILayout.LabelField("Memory used:", m.ToString("0.00") + " MB"); + + isLockReload = EditorGUILayout.Toggle("Lock assembly reload", isLockReload); + isAutoSave = EditorGUILayout.Toggle("Auto Save", isAutoSave); + EditorGUILayout.LabelField("Full reload", lastReloadTime); + EditorGUILayout.LabelField("Compile", lastCompileTime); + if (lastAssCompileTime != null) + { + EditorGUILayout.LabelField("Assembly reload", lastAssCompileTime); + } + // For mysterious reason, iterating over a dictionary doesn't work, it gets empty! + if (lastAssCompile != null) + { + foreach (string s in lastAssCompile) + { + var ss = s.Split(':'); + EditorGUILayout.LabelField(ss[0], ss[1]); + } + } + + if (isLockReload) + { + if (!isLocked) + { + Debug.Log("Locking reload of assemblies"); + EditorApplication.LockReloadAssemblies(); + isLocked = true; + } + } + else + { + if (isLocked) + { + Debug.Log("Unlocking reload of assemblies"); + EditorApplication.UnlockReloadAssemblies(); + isLocked = false; + } + } + } + + void OnBeforeAssemblyReload() + { + assStartTime = EditorApplication.timeSinceStartup; + this.ShowNotification(new GUIContent("Started assembly reload")); + } + + void OnAfterAssemblyReload() + { + assFinishTime = EditorApplication.timeSinceStartup; + assCompileTime = assFinishTime - assStartTime; + lastAssCompileTime = assCompileTime.ToString("0.000") + "s"; + } + + void CompilationPipelineOnAssemblyCompilationStarted(string assembly) + { + Debug.Log("Assembly compile started: " + assembly); + startTimes[assembly] = DateTime.UtcNow; + } + + void CompilationPipelineOnAssemblyCompilationFinished(string assembly, CompilerMessage[] arg2) + { + var time = startTimes[assembly]; + var timeSpan = DateTime.UtcNow - startTimes[assembly]; + var bt = string.Format("{0:0.00}s", timeSpan.TotalMilliseconds / 1000f); + var cleanAss = assembly.Replace("Library/ScriptAssemblies/", ""); + + if (lastAssCompile != null) + { + lastAssCompile.Add(cleanAss + ":" + bt); + } + Debug.Log("Assembly compile ended: " + assembly + " in " + bt); + } + + void OnEnable() + { + AssemblyReloadEvents.beforeAssemblyReload += OnBeforeAssemblyReload; + AssemblyReloadEvents.afterAssemblyReload += OnAfterAssemblyReload; + CompilationPipeline.assemblyCompilationStarted += CompilationPipelineOnAssemblyCompilationStarted; + CompilationPipeline.assemblyCompilationFinished += CompilationPipelineOnAssemblyCompilationFinished; + } + + void OnDisable() + { + AssemblyReloadEvents.beforeAssemblyReload -= OnBeforeAssemblyReload; + AssemblyReloadEvents.afterAssemblyReload -= OnAfterAssemblyReload; + CompilationPipeline.assemblyCompilationStarted -= CompilationPipelineOnAssemblyCompilationStarted; + CompilationPipeline.assemblyCompilationFinished -= CompilationPipelineOnAssemblyCompilationFinished; + } + } +} diff --git a/Assets/Scripts/Editor/Tools/CompileTime.cs.meta b/Assets/Scripts/Editor/Tools/CompileTime.cs.meta new file mode 100644 index 0000000..30a9f44 --- /dev/null +++ b/Assets/Scripts/Editor/Tools/CompileTime.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a15be7d1f359a614fb4f298da7a5fa9e +timeCreated: 1594958194 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Editor/Tools/FindWhatButtonCallsMyMethod.cs b/Assets/Scripts/Editor/Tools/FindWhatButtonCallsMyMethod.cs new file mode 100644 index 0000000..e67f45b --- /dev/null +++ b/Assets/Scripts/Editor/Tools/FindWhatButtonCallsMyMethod.cs @@ -0,0 +1,69 @@ +// prints out which buttons in current scene are referencing your given method + +using UnityEngine; +using UnityEngine.UI; +using UnityEditor; +using UnityEngine.Events; +using System.Reflection; + +namespace UnityLibrary +{ + public class FindWhatButtonCallsMyMethod : EditorWindow + { + private string methodName = "MyMethodHere"; + + [MenuItem("Tools/Find Buttons with Method")] + public static void ShowWindow() + { + GetWindow("FindWhatButtonCallsMyMethod"); + } + + private void OnGUI() + { + GUILayout.Label("Find Buttons that call Method", EditorStyles.boldLabel); + methodName = EditorGUILayout.TextField("Method Name:", methodName); + + if (GUILayout.Button("Find Buttons")) + { + FindButtonsWithMethod(); + } + } + + private void FindButtonsWithMethod() + { + Button[] allButtons = FindObjectsOfType