diff --git a/Assets/Art/UI/photography_icon.png b/Assets/Art/UI/photography_icon.png index 0a57e801..31c5bc84 100644 Binary files a/Assets/Art/UI/photography_icon.png and b/Assets/Art/UI/photography_icon.png differ diff --git a/Assets/Art/UI/photography_icon_straight.png b/Assets/Art/UI/photography_icon_straight.png new file mode 100644 index 00000000..2375e8e8 Binary files /dev/null and b/Assets/Art/UI/photography_icon_straight.png differ diff --git a/Assets/Art/UI/photography_icon_straight.png.meta b/Assets/Art/UI/photography_icon_straight.png.meta new file mode 100644 index 00000000..80657e06 --- /dev/null +++ b/Assets/Art/UI/photography_icon_straight.png.meta @@ -0,0 +1,195 @@ +fileFormatVersion: 2 +guid: bc4336e52a4c1884dbd305f91e19b1b8 +TextureImporter: + internalIDToNameTable: + - first: + 213: -425470254376814679 + second: photography_icon_straight_0 + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 2 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: iOS + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: WebGL + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: WindowsStoreApps + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: + - serializedVersion: 2 + name: photography_icon_straight_0 + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 343 + height: 407 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + customData: + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 9a7ff51de0d681af0800000000000000 + internalID: -425470254376814679 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: + photography_icon_straight_0: -425470254376814679 + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Art/UI/photography_icon_straight_empty.png b/Assets/Art/UI/photography_icon_straight_empty.png new file mode 100644 index 00000000..b9f36192 Binary files /dev/null and b/Assets/Art/UI/photography_icon_straight_empty.png differ diff --git a/Assets/Art/UI/photography_icon_straight_empty.png.meta b/Assets/Art/UI/photography_icon_straight_empty.png.meta new file mode 100644 index 00000000..d95864e9 --- /dev/null +++ b/Assets/Art/UI/photography_icon_straight_empty.png.meta @@ -0,0 +1,195 @@ +fileFormatVersion: 2 +guid: bc1c960f657b36444a8a307034c3f159 +TextureImporter: + internalIDToNameTable: + - first: + 213: 2150077562633408806 + second: photography_icon_straight_empty_0 + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 2 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 4 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: iOS + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: WebGL + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 4 + buildTarget: WindowsStoreApps + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: + - serializedVersion: 2 + name: photography_icon_straight_empty_0 + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 343 + height: 407 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + customData: + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 6215d40d62c96dd10800000000000000 + internalID: 2150077562633408806 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: + photography_icon_straight_empty_0: 2150077562633408806 + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/UI/CameraCrosshair.prefab b/Assets/Prefabs/UI/CameraCrosshair.prefab index 0bd74e27..4c4f5d64 100644 --- a/Assets/Prefabs/UI/CameraCrosshair.prefab +++ b/Assets/Prefabs/UI/CameraCrosshair.prefab @@ -35,6 +35,7 @@ RectTransform: - {fileID: 7977007561442923662} - {fileID: 2458922740234910074} - {fileID: 5102142052451200951} + - {fileID: 3996850525007302552} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} @@ -78,6 +79,12 @@ MonoBehaviour: - {fileID: 6238430743545047181} - {fileID: 1454823446688413410} - {fileID: 4320080458651963543} + captureArea: {fileID: 5112036956614418003} + flyawayAnimation: {fileID: 406673832091221042} + uiElementsToHideDuringCapture: + - {fileID: 6361514160153350252} + - {fileID: 4595905309701925297} + - {fileID: 5728489349197067000} --- !u!222 &644215793910550285 CanvasRenderer: m_ObjectHideFlags: 0 @@ -341,3 +348,116 @@ MonoBehaviour: m_FillOrigin: 0 m_UseSpriteMesh: 0 m_PixelsPerUnitMultiplier: 2.09 +--- !u!1001 &7711541651688058913 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 5112036956614418003} + m_Modifications: + - target: {fileID: 6544162978740042398, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_Name + value: ImageFlyAway + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_AnchorMax.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_SizeDelta.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} +--- !u!114 &406673832091221042 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 7971421867619683347, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + m_PrefabInstance: {fileID: 7711541651688058913} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5600bf58913e468e883989b2cca4b0a8, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::Utils.UI.ScreenshotFlyawayAnimation +--- !u!224 &3996850525007302552 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 6661751999905284025, guid: 086e4cc411c882e498cf5e6a198145ef, type: 3} + m_PrefabInstance: {fileID: 7711541651688058913} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/Prefabs/UI/ImageFlyAway.prefab b/Assets/Prefabs/UI/ImageFlyAway.prefab new file mode 100644 index 00000000..108018de --- /dev/null +++ b/Assets/Prefabs/UI/ImageFlyAway.prefab @@ -0,0 +1,279 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1456476626180609408 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2133076180533276484} + - component: {fileID: 5262034808358904644} + - component: {fileID: 1228761523324820667} + m_Layer: 0 + m_Name: Picture + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2133076180533276484 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1456476626180609408} + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 6661751999905284025} + 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!222 &5262034808358904644 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1456476626180609408} + m_CullTransparentMesh: 1 +--- !u!114 &1228761523324820667 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1456476626180609408} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &2535137713596429325 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3389658153462302246} + - component: {fileID: 48313216925599815} + - component: {fileID: 7843554298445054406} + m_Layer: 5 + m_Name: ImageFrame + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3389658153462302246 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2535137713596429325} + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 6661751999905284025} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: -0.1, y: -0.2} + m_AnchorMax: {x: 1.1, y: 1.1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &48313216925599815 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2535137713596429325} + m_CullTransparentMesh: 1 +--- !u!114 &7843554298445054406 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2535137713596429325} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 2150077562633408806, guid: bc1c960f657b36444a8a307034c3f159, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &6544162978740042398 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6661751999905284025} + - component: {fileID: 7971421867619683347} + m_Layer: 0 + m_Name: ImageFlyAway + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6661751999905284025 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6544162978740042398} + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 2133076180533276484} + - {fileID: 3389658153462302246} + m_Father: {fileID: 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 &7971421867619683347 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6544162978740042398} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5600bf58913e468e883989b2cca4b0a8, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::Utils.UI.ScreenshotFlyawayAnimation + _frame: {fileID: 7843554298445054406} + _picture: {fileID: 1228761523324820667} + _targetOffset: {x: 0, y: 300} + _spinRotations: 2 + _duration: 1.5 + _moveCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + _scaleCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + _rotationCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 diff --git a/Assets/Prefabs/UI/ImageFlyAway.prefab.meta b/Assets/Prefabs/UI/ImageFlyAway.prefab.meta new file mode 100644 index 00000000..415558ac --- /dev/null +++ b/Assets/Prefabs/UI/ImageFlyAway.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 086e4cc411c882e498cf5e6a198145ef +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/MiniGames/DivingForPictures.unity b/Assets/Scenes/MiniGames/DivingForPictures.unity index bdfa7ce8..43b1f7dd 100644 --- a/Assets/Scenes/MiniGames/DivingForPictures.unity +++ b/Assets/Scenes/MiniGames/DivingForPictures.unity @@ -229,6 +229,7 @@ MonoBehaviour: scoreText: {fileID: 1224833350} scorePopupPrefab: {fileID: 0} popupParent: {fileID: 0} + photoIconTarget: {fileID: 495116984} --- !u!114 &116234198 MonoBehaviour: m_ObjectHideFlags: 0 @@ -420,15 +421,15 @@ LineRenderer: m_MaskInteraction: 0 m_Positions: - {x: -0.15602553, y: 4.074945, z: 0} - - {x: -0.1566351, y: 3.9736383, z: 0} - - {x: -0.1572447, y: 3.8729858, z: 0} + - {x: -0.1566351, y: 3.973638, z: 0} + - {x: -0.1572447, y: 3.8729856, z: 0} - {x: -0.15785426, y: 3.7729874, z: 0} - {x: -0.15846384, y: 3.6736436, z: 0} - - {x: -0.15907341, y: 3.5749545, z: 0} + - {x: -0.15907341, y: 3.574954, z: 0} - {x: -0.15968299, y: 3.4769192, z: 0} - - {x: -0.16029257, y: 3.379539, z: 0} - - {x: -0.16090216, y: 3.2828128, z: 0} - - {x: -0.16151173, y: 3.186741, z: 0} + - {x: -0.16029257, y: 3.3795385, z: 0} + - {x: -0.16090216, y: 3.2828126, z: 0} + - {x: -0.16151173, y: 3.1867409, z: 0} - {x: -0.16212131, y: 3.0913236, z: 0} m_Parameters: serializedVersion: 3 @@ -932,6 +933,7 @@ GameObject: - component: {fileID: 424805725} - component: {fileID: 424805727} - component: {fileID: 424805728} + - component: {fileID: 424805729} m_Layer: 0 m_Name: MinigameManagers m_TagString: Untagged @@ -962,8 +964,7 @@ MonoBehaviour: - {fileID: 173052728} surfacingTimeline: {fileID: 2064311130} flashRef: {fileID: 1419181041} - viewfinderManager: {fileID: 0} - picturesTaken: 0 + viewfinderManager: {fileID: 424805727} deathAudioPlayer: {fileID: 199536377} cameraViewfinderManager: {fileID: 424805727} scoreCanvasObject: {fileID: 341271021} @@ -1094,6 +1095,20 @@ AudioSource: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 +--- !u!114 &424805729 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 424805724} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78476907cb4b488da7a1526a8453b577, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::Minigames.DivingForPictures.Screenshot.DivingScreenshotManager + _uiElementsToHide: [] + _flashEffect: {fileID: 0} --- !u!1 &461301695 GameObject: m_ObjectHideFlags: 0 @@ -1425,7 +1440,7 @@ Transform: m_GameObject: {fileID: 747976396} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 3.1975174, z: 0} + m_LocalPosition: {x: 0, y: 3.197517, z: 0} m_LocalScale: {x: 0.57574, y: 0.57574, z: 0.57574} m_ConstrainProportionsScale: 0 m_Children: @@ -1983,10 +1998,10 @@ LineRenderer: m_SortingOrder: 0 m_MaskInteraction: 0 m_Positions: - - {x: -0.15602553, y: 4.074945, z: 0} - - {x: -0.11662118, y: 3.8796225, z: 0} - - {x: -0.07721684, y: 3.7057447, z: 0} - - {x: -0.03781248, y: 3.5533109, z: 0} + - {x: -0.15602553, y: 4.0749445, z: 0} + - {x: -0.11662118, y: 3.879622, z: 0} + - {x: -0.07721684, y: 3.7057445, z: 0} + - {x: -0.03781248, y: 3.5533106, z: 0} - {x: 0.0015918687, y: 3.4223216, z: 0} - {x: 0.040996216, y: 3.3127766, z: 0} - {x: 0.08040057, y: 3.2246761, z: 0} @@ -2704,14 +2719,14 @@ LineRenderer: m_SortingOrder: 0 m_MaskInteraction: 0 m_Positions: - - {x: -0.15602553, y: 4.074945, z: 0} - - {x: -0.18956745, y: 3.8764977, z: 0} - - {x: -0.22310936, y: 3.7000234, z: 0} - - {x: -0.25665125, y: 3.5455208, z: 0} + - {x: -0.15602553, y: 4.0749445, z: 0} + - {x: -0.18956745, y: 3.8764973, z: 0} + - {x: -0.22310936, y: 3.7000232, z: 0} + - {x: -0.25665125, y: 3.5455203, z: 0} - {x: -0.29019317, y: 3.412991, z: 0} - {x: -0.32373506, y: 3.3024335, z: 0} - - {x: -0.35727698, y: 3.2138486, z: 0} - - {x: -0.39081886, y: 3.147236, z: 0} + - {x: -0.35727698, y: 3.2138484, z: 0} + - {x: -0.39081886, y: 3.1472359, z: 0} - {x: -0.4243608, y: 3.1025958, z: 0} - {x: -0.45790267, y: 3.0799282, z: 0} - {x: -0.4914446, y: 3.079233, z: 0} diff --git a/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs b/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs index 18d00f20..50e1d443 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/DivingGameManager.cs @@ -1,4 +1,4 @@ -using AppleHills.Core.Interfaces; +using AppleHills.Core.Interfaces; using Cinematics; using Core; using Core.Lifecycle; @@ -9,6 +9,7 @@ using System.Collections; using System.Collections.Generic; using Core.Settings; using Minigames.DivingForPictures.Bubbles; +using Minigames.DivingForPictures.Screenshot; using UI.Core; using UnityEngine; using UnityEngine.Playables; @@ -55,7 +56,9 @@ namespace Minigames.DivingForPictures // Public properties public int PlayerScore => _playerScore; public float CurrentVelocityFactor => _currentVelocityFactor; - public int picturesTaken; + + // Delegate to DivingScreenshotManager for backward compatibility + public int picturesTaken => DivingScreenshotManager.Instance != null ? DivingScreenshotManager.Instance.ScreenshotCount : 0; // Events public event Action OnScoreChanged; @@ -284,23 +287,7 @@ namespace Minigames.DivingForPictures } } - private void DoPictureTaken(Monster.Monster monster) - { - // Calculate points based on depth - int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * _settings.DepthMultiplier); - int pointsAwarded = _settings.BasePoints + depthBonus; - - // Add score - _playerScore += pointsAwarded; - - // Add number of pictures taken - picturesTaken += 1; - - // Fire events - OnScoreChanged?.Invoke(picturesTaken); - OnPictureTaken?.Invoke(monster, picturesTaken); - - } + // Photo logic moved to DivingScreenshotManager /// /// Called when the player takes damage from any collision @@ -667,8 +654,13 @@ namespace Minigames.DivingForPictures _activeMonsters.Clear(); // Calculate booster pack reward based on pictures taken - int boosterPackCount = CalculateBoosterPackReward(); - Logging.Debug($"[DivingGameManager] Pictures taken: {picturesTaken}, awarding {boosterPackCount} booster pack(s)"); + int boosterPackCount = DivingScreenshotManager.Instance != null + ? DivingScreenshotManager.Instance.CalculateBoosterPackReward() + : 1; + int screenshotCount = DivingScreenshotManager.Instance != null + ? DivingScreenshotManager.Instance.ScreenshotCount + : 0; + Logging.Debug($"[DivingGameManager] Pictures taken: {screenshotCount}, awarding {boosterPackCount} booster pack(s)"); // Show UI and grant booster packs using new async method UIPageController.Instance.ShowAllUI(); @@ -700,29 +692,7 @@ namespace Minigames.DivingForPictures Logging.Debug($"Final Score: {_playerScore}"); } - /// - /// Calculates how many booster packs to award based on the number of pictures taken. - /// - /// Number of booster packs to award - private int CalculateBoosterPackReward() - { - if (picturesTaken <= 3) - { - return 1; - } - else if (picturesTaken <= 5) - { - return 2; - } - else if (picturesTaken <= 10) - { - return 3; - } - else - { - return 4; - } - } + // Booster reward calculation moved to DivingScreenshotManager /// /// Starts a smooth transition to the new velocity factor @@ -949,66 +919,49 @@ namespace Minigames.DivingForPictures { if (!_isPhotoSequenceActive || _currentPhotoTarget == null) return; - - // Stop the viewfinder animation if it's still running - if (viewfinderManager != null) + + // Start coroutine to handle screenshot and cleanup + StartCoroutine(TakePictureCoroutine()); + } + + /// + /// Coroutine that takes screenshot and waits for completion before cleanup + /// + private IEnumerator TakePictureCoroutine() + { + // Take screenshot and WAIT for it to complete + if (DivingScreenshotManager.Instance != null) { - viewfinderManager.StopViewfinderAnimation(); + yield return DivingScreenshotManager.Instance.TakeScreenshotAsync(_currentPhotoTarget, _capturedProximity); + } + else + { + Logging.Warning("[DivingGameManager] DivingScreenshotManager not found!"); + } + + // Play shutter sound + if (cameraViewfinderManager != null) + { + cameraViewfinderManager.PlayShutterSound(); } // Notify the monster that its picture was taken - _currentPhotoTarget.NotifyPictureTaken(); - - // Calculate score based on proximity and depth - CalculateScore(_currentPhotoTarget, _capturedProximity); - - //Trigger the Flash Effect - if (flashRef != null) + if (_currentPhotoTarget != null) { - - var flash = flashRef.GetComponent(); - if (flash != null) - { - - flash.TriggerFlash(); - cameraViewfinderManager.PlayShutterSound(); - } + _currentPhotoTarget.NotifyPictureTaken(); + } + + // NOW destroy the viewfinder (screenshot is complete) + if (viewfinderManager != null) + { + viewfinderManager.StopViewfinderAnimation(); } // Complete the sequence CompletePhotoSequence(); } - /// - /// Calculates the score for a picture based on proximity to target and monster depth - /// - private void CalculateScore(Monster.Monster monster, float proximity) - { - if (monster == null) return; - - // Calculate base points from depth - int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * _settings.DepthMultiplier); - - // Apply proximity multiplier (0-100%) - float proximityMultiplier = Mathf.Clamp01(proximity); // Ensure it's in 0-1 range - int proximityBonus = Mathf.RoundToInt(_settings.BasePoints * proximityMultiplier); - - // Calculate total score - int pointsAwarded = _settings.BasePoints + proximityBonus + depthBonus; - - Logging.Debug($"[DivingGameManager] Picture score calculation: base={proximityBonus} (proximity={proximity:F2}), " + - $"depth bonus={depthBonus}, total={pointsAwarded}"); - - // Add score - _playerScore += pointsAwarded; - - // Add pictures taken - picturesTaken += 1; - - // Fire events - OnScoreChanged?.Invoke(picturesTaken); - OnPictureTaken?.Invoke(monster, picturesTaken); - } + // Score calculation moved to DivingScreenshotManager /// /// Handles completion of the viewfinder animation diff --git a/Assets/Scripts/Minigames/DivingForPictures/DivingScoreUI.cs b/Assets/Scripts/Minigames/DivingForPictures/DivingScoreUI.cs index 232038f1..30d750bf 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/DivingScoreUI.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/DivingScoreUI.cs @@ -1,23 +1,59 @@ using UnityEngine; using TMPro; +using Minigames.DivingForPictures.Screenshot; namespace Minigames.DivingForPictures { public class DivingScoreUI : MonoBehaviour { + private static DivingScoreUI _instance; + + public static DivingScoreUI Instance + { + get + { + if (_instance == null && Application.isPlaying) + { + _instance = FindAnyObjectByType(); + } + return _instance; + } + } + [SerializeField] private TextMeshProUGUI scoreText; [SerializeField] private GameObject scorePopupPrefab; [SerializeField] private Transform popupParent; + + [Header("Animation Target")] + [SerializeField] private Transform photoIconTarget; + + /// + /// The photo icon transform that flyaway animations should target + /// + public Transform PhotoIconTarget => photoIconTarget; + + private void Awake() + { + if (_instance == null) + { + _instance = this; + } + else if (_instance != this) + { + Debug.LogWarning("[DivingScoreUI] Multiple instances detected. Keeping first instance."); + } + } private void Start() { - // Subscribe to events - DivingGameManager.Instance.OnScoreChanged += UpdateScoreDisplay; - DivingGameManager.Instance.OnPictureTaken += ShowScorePopup; + // Subscribe to screenshot manager events + if (DivingScreenshotManager.Instance != null) + { + DivingScreenshotManager.Instance.OnScreenshotCountChanged += UpdateScoreDisplay; + } // Initialize display - UpdateScoreDisplay(DivingGameManager.Instance.picturesTaken); - + UpdateScoreDisplay(0); // Create popup parent if needed if (popupParent == null) @@ -29,10 +65,9 @@ namespace Minigames.DivingForPictures private void OnDestroy() { // Unsubscribe from events - if (DivingGameManager.Instance) + if (DivingScreenshotManager.Instance != null) { - DivingGameManager.Instance.OnScoreChanged -= UpdateScoreDisplay; - DivingGameManager.Instance.OnPictureTaken -= ShowScorePopup; + DivingScreenshotManager.Instance.OnScreenshotCountChanged -= UpdateScoreDisplay; } } @@ -43,23 +78,5 @@ namespace Minigames.DivingForPictures scoreText.text = $"x {score}"; } } - - private void ShowScorePopup(Monster.Monster monster, int points) - { - if (scorePopupPrefab == null) return; - - // Create popup at monster position - GameObject popup = Instantiate(scorePopupPrefab, monster.transform.position, Quaternion.identity, popupParent); - - // Find text component and set value - TextMeshProUGUI popupText = popup.GetComponentInChildren(); - if (popupText != null) - { - popupText.text = $"+{points}"; - } - - // Auto-destroy after delay - Destroy(popup, 2f); - } } } diff --git a/Assets/Scripts/Minigames/DivingForPictures/PictureCamera/CameraViewfinderManager.cs b/Assets/Scripts/Minigames/DivingForPictures/PictureCamera/CameraViewfinderManager.cs index f73a529d..cd54d5f9 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/PictureCamera/CameraViewfinderManager.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/PictureCamera/CameraViewfinderManager.cs @@ -42,6 +42,12 @@ namespace Minigames.DivingForPictures.PictureCamera private Viewfinder viewfinderComponent; private UnityEngine.Camera mainCamera; private AudioSource _audioSource; + + /// + /// The currently active Viewfinder component. + /// Exposed for screenshot system to access capture area and flyaway animation. + /// + public Viewfinder CurrentViewfinder => viewfinderComponent; // Animation state private float animationProgress = 0f; diff --git a/Assets/Scripts/Minigames/DivingForPictures/PictureCamera/Viewfinder.cs b/Assets/Scripts/Minigames/DivingForPictures/PictureCamera/Viewfinder.cs index cf0e9d22..9b8b6873 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/PictureCamera/Viewfinder.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/PictureCamera/Viewfinder.cs @@ -3,17 +3,30 @@ using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using Input; +using UnityEngine.Serialization; +using Utils.UI; namespace Minigames.DivingForPictures.PictureCamera { /// /// Attached to the viewfinder UI prefab. Handles tap detection and other viewfinder-specific operations. + /// Also exposes screenshot-related references for the diving minigame. /// public class Viewfinder : MonoBehaviour, ITouchInputConsumer { [SerializeField] private Image[] viewfinderImages; // Array of Image components to tint based on proximity + [Header("Screenshot Components")] + [FormerlySerializedAs("_captureArea")] + [SerializeField] private RectTransform captureArea; + [FormerlySerializedAs("_flyawayAnimation")] + [SerializeField] private ScreenshotFlyawayAnimation flyawayAnimation; + + [Header("UI Elements to Hide During Screenshot")] + [Tooltip("UI elements (like frame, crosshairs) that should be hidden during screenshot capture")] + [SerializeField] private GameObject[] uiElementsToHideDuringCapture; + // Events public event System.Action OnViewfinderTapped; public event System.Action OnViewfinderHoldStarted; @@ -24,9 +37,41 @@ namespace Minigames.DivingForPictures.PictureCamera private RectTransform _rectTransform; private CameraViewfinderManager _viewfinderManager; + // Public properties for screenshot system + public RectTransform CaptureArea + { + get + { + if (captureArea == null) + { + captureArea = GetComponent(); + } + return captureArea; + } + } + + public ScreenshotFlyawayAnimation FlyawayAnimation => flyawayAnimation; + + /// + /// UI elements to hide during screenshot capture (frame, crosshairs, etc.) + /// + public GameObject[] UIElementsToHideDuringCapture => uiElementsToHideDuringCapture; + private void Awake() { _rectTransform = GetComponent(); + + // Auto-assign capture area to self if not set + if (captureArea == null) + { + captureArea = GetComponent(); + } + + // Auto-find flyaway animation in children + if (flyawayAnimation == null) + { + flyawayAnimation = GetComponentInChildren(includeInactive: true); + } } /// diff --git a/Assets/Scripts/Minigames/DivingForPictures/Screenshot.meta b/Assets/Scripts/Minigames/DivingForPictures/Screenshot.meta new file mode 100644 index 00000000..555e6c02 --- /dev/null +++ b/Assets/Scripts/Minigames/DivingForPictures/Screenshot.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fa94031c3f274ab2afd0d0b2d4cef32f +timeCreated: 1766012726 \ No newline at end of file diff --git a/Assets/Scripts/Minigames/DivingForPictures/Screenshot/DivingScreenshotManager.cs b/Assets/Scripts/Minigames/DivingForPictures/Screenshot/DivingScreenshotManager.cs new file mode 100644 index 00000000..911473a8 --- /dev/null +++ b/Assets/Scripts/Minigames/DivingForPictures/Screenshot/DivingScreenshotManager.cs @@ -0,0 +1,286 @@ +using System; +using System.Collections; +using Core; +using Core.Settings; +using UnityEngine; +using Utils; +using Utils.UI; + +namespace Minigames.DivingForPictures.Screenshot +{ + /// + /// Singleton manager for diving minigame screenshot functionality. + /// Provides easy-to-use TakeScreenshot() and TakeScreenshotAsync() methods. + /// Integrates with PhotoManager for disk storage and ScreenshotFlyawayAnimation for visual feedback. + /// + public class DivingScreenshotManager : MonoBehaviour + { + private static DivingScreenshotManager _instance; + + public static DivingScreenshotManager Instance + { + get + { + if (_instance == null && Application.isPlaying) + { + _instance = FindAnyObjectByType(); + + if (_instance == null) + { + GameObject go = new GameObject("DivingScreenshotManager"); + _instance = go.AddComponent(); + } + } + + return _instance; + } + } + + [Header("Screenshot Settings")] + [SerializeField] private GameObject[] _uiElementsToHide; + + [Header("Flash Effect")] + [SerializeField] private GameObject _flashEffect; + + // State tracking + private int _screenshotCount; + private int _playerScore; + private bool _isCapturing; + + // Settings reference + private IDivingMinigameSettings _settings; + + // Public properties + public int ScreenshotCount => _screenshotCount; + public int PlayerScore => _playerScore; + public bool IsCapturing => _isCapturing; + + // Events + public event Action OnScreenshotCountChanged; + public event Action OnScoreChanged; + public event Action OnScreenshotCaptured; // photoId, texture + + private void Awake() + { + if (_instance == null) + { + _instance = this; + } + else if (_instance != this) + { + Destroy(gameObject); + return; + } + } + + private void Start() + { + _settings = GameManager.GetSettingsObject(); + } + + /// + /// Take a screenshot using coroutine. Simple synchronous call. + /// + /// Optional monster reference for score calculation + /// Optional proximity score (0-1) + public void TakeScreenshot(Monster.Monster monster = null, float proximity = 0f) + { + if (_isCapturing) + { + Logging.Warning("[DivingScreenshotManager] Already capturing a screenshot!"); + return; + } + + StartCoroutine(TakeScreenshotCoroutine(monster, proximity)); + } + + /// + /// Take a screenshot asynchronously. Returns when capture is complete. + /// + /// Optional monster reference for score calculation + /// Optional proximity score (0-1) + public Coroutine TakeScreenshotAsync(Monster.Monster monster = null, float proximity = 0f) + { + if (_isCapturing) + { + Logging.Warning("[DivingScreenshotManager] Already capturing a screenshot!"); + return null; + } + + return StartCoroutine(TakeScreenshotCoroutine(monster, proximity)); + } + + /// + /// Internal coroutine that handles the screenshot capture process + /// + private IEnumerator TakeScreenshotCoroutine(Monster.Monster monster, float proximity) + { + _isCapturing = true; + + // Get viewfinder and validate references + var viewfinderManager = PictureCamera.CameraViewfinderManager.Instance; + if (viewfinderManager == null || viewfinderManager.CurrentViewfinder == null) + { + Logging.Error("[DivingScreenshotManager] No active viewfinder found!"); + _isCapturing = false; + yield break; + } + + var viewfinder = viewfinderManager.CurrentViewfinder; + RectTransform captureArea = viewfinder?.CaptureArea; + + if (captureArea == null) + { + Logging.Error($"[DivingScreenshotManager] Capture area not configured! Viewfinder: {viewfinder?.gameObject.name}"); + _isCapturing = false; + yield break; + } + + // Show flash effect + if (_flashEffect != null) + { + _flashEffect.SetActive(true); + yield return new WaitForSeconds(0.1f); + _flashEffect.SetActive(false); + } + + // Combine global UI elements with viewfinder-specific ones + GameObject[] combinedUIToHide = CombineUIElementsToHide(_uiElementsToHide, viewfinder.UIElementsToHideDuringCapture); + + // Capture and save using PhotoManager + bool captureSuccess = false; + string savedPhotoId = null; + Texture2D capturedTexture = null; + + yield return PhotoManager.CaptureAndSaveCoroutine( + CaptureType.DivingMinigame, + captureArea, + combinedUIToHide, + onSuccess: (photoId) => + { + savedPhotoId = photoId; + captureSuccess = true; + + // Load the texture back for animation + capturedTexture = PhotoManager.LoadPhoto(CaptureType.DivingMinigame, photoId); + + Logging.Debug($"[DivingScreenshotManager] Screenshot saved: {photoId}"); + }, + onFailure: (error) => + { + Logging.Error($"[DivingScreenshotManager] Screenshot failed: {error}"); + captureSuccess = false; + } + ); + + if (!captureSuccess) + { + _isCapturing = false; + yield break; + } + + // Calculate score + int earnedScore = CalculateScore(monster, proximity); + _playerScore += earnedScore; + _screenshotCount++; + + // Fire events + OnScreenshotCountChanged?.Invoke(_screenshotCount); + OnScoreChanged?.Invoke(_screenshotCount); // Pass screenshot count for UI compatibility + OnScreenshotCaptured?.Invoke(savedPhotoId, capturedTexture); + + Logging.Debug($"[DivingScreenshotManager] Score: +{earnedScore} (Total: {_playerScore}, Count: {_screenshotCount})"); + + // Trigger flyaway animation with target from DivingScoreUI + if (capturedTexture != null && viewfinder.FlyawayAnimation != null) + { + Transform photoIconTarget = DivingScoreUI.Instance?.PhotoIconTarget; + viewfinder.FlyawayAnimation.PlayAnimation(capturedTexture, photoIconTarget); + } + + _isCapturing = false; + } + + /// + /// Calculate score based on monster depth and proximity + /// + private int CalculateScore(Monster.Monster monster, float proximity) + { + if (_settings == null) + { + return 100; // Default fallback + } + + int baseScore = _settings.BasePoints; + + // Add depth bonus if monster reference provided + if (monster != null) + { + int depthBonus = Mathf.FloorToInt(Mathf.Abs(monster.transform.position.y) * _settings.DepthMultiplier); + baseScore += depthBonus; + } + + // Add proximity bonus (0-1 scale, multiply by some factor) + int proximityBonus = Mathf.RoundToInt(proximity * 50f); + baseScore += proximityBonus; + + return baseScore; + } + + /// + /// Get booster pack count based on screenshot count (for end game reward) + /// + public int CalculateBoosterPackReward() + { + if (_screenshotCount <= 3) + { + return 1; + } + else if (_screenshotCount <= 5) + { + return 2; + } + else if (_screenshotCount <= 10) + { + return 3; + } + else + { + return 4; + } + } + + /// + /// Reset state for new game + /// + public void ResetState() + { + _screenshotCount = 0; + _playerScore = 0; + _isCapturing = false; + } + + /// + /// Combines global UI elements with viewfinder-specific UI elements + /// + private GameObject[] CombineUIElementsToHide(GameObject[] globalElements, GameObject[] viewfinderElements) + { + if (globalElements == null && viewfinderElements == null) + return null; + + if (globalElements == null) + return viewfinderElements; + + if (viewfinderElements == null) + return globalElements; + + // Combine both arrays + GameObject[] combined = new GameObject[globalElements.Length + viewfinderElements.Length]; + globalElements.CopyTo(combined, 0); + viewfinderElements.CopyTo(combined, globalElements.Length); + + return combined; + } + } +} + diff --git a/Assets/Scripts/Minigames/DivingForPictures/Screenshot/DivingScreenshotManager.cs.meta b/Assets/Scripts/Minigames/DivingForPictures/Screenshot/DivingScreenshotManager.cs.meta new file mode 100644 index 00000000..10fa907f --- /dev/null +++ b/Assets/Scripts/Minigames/DivingForPictures/Screenshot/DivingScreenshotManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 78476907cb4b488da7a1526a8453b577 +timeCreated: 1766012726 \ No newline at end of file diff --git a/Assets/Scripts/UI/DivingGameOverScreen.cs b/Assets/Scripts/UI/DivingGameOverScreen.cs index 283328ad..6c78c9a2 100644 --- a/Assets/Scripts/UI/DivingGameOverScreen.cs +++ b/Assets/Scripts/UI/DivingGameOverScreen.cs @@ -37,11 +37,18 @@ namespace UI protected override void DoTransitionIn(Action onComplete) { // Update score when showing the screen - if (DivingGameManager.Instance != null) + int finalScore = 0; + if (Minigames.DivingForPictures.Screenshot.DivingScreenshotManager.Instance != null) { - int finalScore = DivingGameManager.Instance.picturesTaken; - finalScoreText.text = $"x {finalScore}"; + finalScore = Minigames.DivingForPictures.Screenshot.DivingScreenshotManager.Instance.ScreenshotCount; } + else if (DivingGameManager.Instance != null) + { + // Fallback for backward compatibility + finalScore = DivingGameManager.Instance.picturesTaken; + } + + finalScoreText.text = $"x {finalScore}"; if (canvasGroup != null) { diff --git a/Assets/Scripts/Utils/PhotoManager.cs b/Assets/Scripts/Utils/PhotoManager.cs index 62eac472..5651be81 100644 --- a/Assets/Scripts/Utils/PhotoManager.cs +++ b/Assets/Scripts/Utils/PhotoManager.cs @@ -57,8 +57,11 @@ namespace Utils } } - // Wait for UI to hide + // Wait for UI to hide and render to complete yield return new WaitForEndOfFrame(); + yield return null; // Wait one more frame for good measure + + Logging.Debug($"[PhotoManager] About to capture. CaptureArea: {captureArea.name}"); // Capture photo bool captureComplete = false; @@ -68,6 +71,7 @@ namespace Utils { capturedPhoto = texture; captureComplete = true; + Logging.Debug($"[PhotoManager] Capture callback received. Texture: {(texture != null ? $"{texture.width}x{texture.height}" : "NULL")}"); }, mainCamera, clampToScreenBounds); // Wait for capture to complete @@ -129,6 +133,12 @@ namespace Utils if (mainCamera == null) mainCamera = Camera.main; + // Debug: Log RectTransform details + Logging.Debug($"[PhotoManager] CaptureArea RectTransform: {captureArea.name}"); + Logging.Debug($"[PhotoManager] CaptureArea anchoredPosition: {captureArea.anchoredPosition}"); + Logging.Debug($"[PhotoManager] CaptureArea sizeDelta: {captureArea.sizeDelta}"); + Logging.Debug($"[PhotoManager] CaptureArea rect: {captureArea.rect}"); + // Use ScreenSpaceUtility to convert RectTransform to screen rect Rect screenRect = ScreenSpaceUtility.RectTransformToScreenRect( captureArea, @@ -138,6 +148,15 @@ namespace Utils ); Logging.Debug($"[PhotoManager] Capturing area: pos={screenRect.position}, size={screenRect.size}"); + Logging.Debug($"[PhotoManager] Screen dimensions: {Screen.width}x{Screen.height}"); + + // Validate screenRect + if (screenRect.width <= 0 || screenRect.height <= 0) + { + Logging.Error($"[PhotoManager] Invalid screen rect calculated! width={screenRect.width}, height={screenRect.height}"); + onComplete?.Invoke(null); + return; + } // Use Screenshot Helper's Capture method ScreenshotHelper.Instance.Capture( diff --git a/Assets/Scripts/Utils/UI.meta b/Assets/Scripts/Utils/UI.meta new file mode 100644 index 00000000..9b2622a7 --- /dev/null +++ b/Assets/Scripts/Utils/UI.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 6b23cacf87f94639aad3b8e25b596ac3 +timeCreated: 1766012758 \ No newline at end of file diff --git a/Assets/Scripts/Utils/UI/ScreenshotFlyawayAnimation.cs b/Assets/Scripts/Utils/UI/ScreenshotFlyawayAnimation.cs new file mode 100644 index 00000000..920acfb0 --- /dev/null +++ b/Assets/Scripts/Utils/UI/ScreenshotFlyawayAnimation.cs @@ -0,0 +1,217 @@ +using UnityEngine; +using UnityEngine.UI; +using Pixelplacement; + +namespace Utils.UI +{ + /// + /// UI component that animates a screenshot flying away and disappearing. + /// Uses Pixelplacement Tween library for smooth animations with curves. + /// Attach to a UI prefab with frame (Image) and picture (Image) components. + /// + public class ScreenshotFlyawayAnimation : MonoBehaviour + { + [Header("UI Components")] + [SerializeField] private Image _frame; + [SerializeField] private Image _picture; + + [Header("Animation Settings")] + [Tooltip("Target offset from starting position (in UI space)")] + [SerializeField] private Vector2 _targetOffset = new Vector2(0, 300f); + + [Tooltip("Number of full rotations during animation")] + [SerializeField] private float _spinRotations = 2f; + + [Tooltip("Duration of the entire animation in seconds")] + [SerializeField] private float _duration = 1.5f; + + [Tooltip("Movement curve for position animation")] + [SerializeField] private AnimationCurve _moveCurve = AnimationCurve.EaseInOut(0, 0, 1, 1); + + [Tooltip("Scale curve for shrinking animation")] + [SerializeField] private AnimationCurve _scaleCurve = AnimationCurve.EaseInOut(0, 1, 1, 0); + + [Tooltip("Rotation curve for spinning animation")] + [SerializeField] private AnimationCurve _rotationCurve = AnimationCurve.Linear(0, 0, 1, 1); + + private RectTransform _rectTransform; + private bool _isAnimating; + private Transform _targetTransform; // Target to fly toward (optional) + + private void Awake() + { + _rectTransform = GetComponent(); + + // Hide initially - will be shown when animation plays + gameObject.SetActive(false); + + // Validate components + if (_frame == null) + { + Debug.LogWarning("[ScreenshotFlyawayAnimation] Frame image not assigned!"); + } + + if (_picture == null) + { + Debug.LogWarning("[ScreenshotFlyawayAnimation] Picture image not assigned!"); + } + } + + /// + /// Start the flyaway animation with the captured screenshot texture. + /// Unparents to root canvas to survive viewfinder destruction. + /// + /// The screenshot texture to display + /// Optional target transform to fly toward (if null, uses _targetOffset) + public void PlayAnimation(Texture2D photo, Transform target = null) + { + if (_isAnimating) + { + Debug.LogWarning("[ScreenshotFlyawayAnimation] Animation already playing!"); + return; + } + + if (photo == null) + { + Debug.LogError("[ScreenshotFlyawayAnimation] Photo texture is null!"); + Destroy(gameObject); + return; + } + + // Store target for StartAnimation + _targetTransform = target; + + // Show the GameObject before playing animation + gameObject.SetActive(true); + + // Unparent to root canvas to survive viewfinder destruction + Canvas rootCanvas = GetComponentInParent(); + if (rootCanvas != null) + { + rootCanvas = rootCanvas.rootCanvas; + transform.SetParent(rootCanvas.transform, worldPositionStays: true); + } + + // Assign texture to picture image + if (_picture != null) + { + Sprite photoSprite = Sprite.Create( + photo, + new Rect(0, 0, photo.width, photo.height), + new Vector2(0.5f, 0.5f) + ); + _picture.sprite = photoSprite; + } + + _isAnimating = true; + StartAnimation(); + } + + /// + /// Execute the animation using Pixelplacement Tween + /// + private void StartAnimation() + { + if (_rectTransform == null) return; + + // Get starting position + Vector2 startPosition = _rectTransform.anchoredPosition; + Vector2 endPosition; + + // Calculate end position based on target or offset + if (_targetTransform != null) + { + // Convert target world position to local anchored position + RectTransform targetRect = _targetTransform as RectTransform; + if (targetRect != null && _rectTransform.parent is RectTransform parentRect) + { + // Convert target's position to parent's local space + Vector2 targetLocalPos; + RectTransformUtility.ScreenPointToLocalPointInRectangle( + parentRect, + RectTransformUtility.WorldToScreenPoint(null, targetRect.position), + null, + out targetLocalPos + ); + endPosition = targetLocalPos; + } + else + { + // Fallback: use offset if conversion fails + endPosition = startPosition + _targetOffset; + } + } + else + { + // Use offset if no target provided + endPosition = startPosition + _targetOffset; + } + + // Start rotation at 0 + Vector3 startRotation = Vector3.zero; + Vector3 endRotation = new Vector3(0, 0, 360f * _spinRotations); + + // Start scale at 1 + Vector3 startScale = Vector3.one; + Vector3 endScale = Vector3.zero; + + // Animate position using AnchoredPosition for UI + Tween.AnchoredPosition( + _rectTransform, + startPosition, + endPosition, + _duration, + 0f, // no delay + _moveCurve, + Tween.LoopType.None, + null, // no start callback + OnAnimationComplete // complete callback + ); + + // Animate scale + Tween.LocalScale( + transform, + startScale, + endScale, + _duration, + 0f, + _scaleCurve + ); + + // Animate rotation (Z-axis spin) + Tween.Rotation( + transform, + Quaternion.Euler(startRotation), + Quaternion.Euler(endRotation), + _duration, + 0f, + _rotationCurve, + Tween.LoopType.None, + null, + null, + true // obey timescale + ); + } + + /// + /// Called when animation completes - destroy the GameObject + /// + private void OnAnimationComplete() + { + _isAnimating = false; + + // Clean up sprite to avoid memory leak + if (_picture != null && _picture.sprite != null) + { + Sprite sprite = _picture.sprite; + _picture.sprite = null; + Destroy(sprite.texture); + Destroy(sprite); + } + + // Destroy the animation GameObject + Destroy(gameObject); + } + } +} + diff --git a/Assets/Scripts/Utils/UI/ScreenshotFlyawayAnimation.cs.meta b/Assets/Scripts/Utils/UI/ScreenshotFlyawayAnimation.cs.meta new file mode 100644 index 00000000..5dae7eca --- /dev/null +++ b/Assets/Scripts/Utils/UI/ScreenshotFlyawayAnimation.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5600bf58913e468e883989b2cca4b0a8 +timeCreated: 1766012758 \ No newline at end of file diff --git a/Assets/Settings/DivingMinigameSettings.asset b/Assets/Settings/DivingMinigameSettings.asset index a393100a..4ddef8ec 100644 --- a/Assets/Settings/DivingMinigameSettings.asset +++ b/Assets/Settings/DivingMinigameSettings.asset @@ -77,7 +77,7 @@ MonoBehaviour: photoInputMode: 0 photoTakingMode: 1 autoPhotoDelay: 0.5 - paddingFactor: 1 + paddingFactor: 1.2 minSizePercent: 0.15 maxSizePercent: 1 viewfinderStartScale: 1