diff --git a/.gitattributes b/.gitattributes index aab49955f..d8c37fec9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -75,7 +75,8 @@ *.psd filter=lfs diff=lfs merge=lfs -text *.psb filter=lfs diff=lfs merge=lfs -text *.bank filter=lfs diff=lfs merge=lfs -text +*.mp4 filter=lfs diff=lfs merge=lfs -text # DOTween editor images - exclude from LFS (stored as regular binaries, Unity re-import causes false changes) Assets/Plugins/Demigiant/DOTween/Editor/Imgs/*.png -filter -diff -merge -Assets/Plugins/Demigiant/DOTween/Editor/Imgs/*.jpg -filter -diff -merge \ No newline at end of file +Assets/Plugins/Demigiant/DOTween/Editor/Imgs/*.jpg -filter -diff -merge diff --git a/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.mat b/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.mat new file mode 100644 index 000000000..8c3972b3d --- /dev/null +++ b/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.mat @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: DreamSeaMemory + m_Shader: {fileID: 4800000, guid: a8d86af0aff94e1794fa50e65ac676d5, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _VideoTex: + m_Texture: {fileID: 8400000, guid: d873791053c443c1a79eedd22a687780, type: 2} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _Contrast: 1 + - _DitherStrength: 0.002 + - _Levels: 10 + - _UseVideo: 0 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _PixelGrid: {r: 360, g: 640, b: 0, a: 0} + m_BuildTextureStacks: [] diff --git a/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.mat.meta b/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.mat.meta new file mode 100644 index 000000000..7eb2ac177 --- /dev/null +++ b/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e04544198a7d4f88ba592bf1feebbca2 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.renderTexture b/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.renderTexture new file mode 100644 index 000000000..fbc220f35 --- /dev/null +++ b/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.renderTexture @@ -0,0 +1,40 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!84 &8400000 +RenderTexture: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: DreamSeaMemory + m_ImageContentsHash: + serializedVersion: 2 + Hash: 00000000000000000000000000000000 + m_ForcedFallbackFormat: 4 + m_DownscaleFallback: 0 + m_IsAlphaChannelOptional: 0 + serializedVersion: 5 + m_Width: 720 + m_Height: 1280 + m_AntiAliasing: 1 + m_MipCount: -1 + m_DepthStencilFormat: 0 + m_ColorFormat: 4 + m_MipMap: 0 + m_GenerateMips: 0 + m_SRGB: 1 + m_UseDynamicScale: 0 + m_BindMS: 0 + m_EnableCompatibleFormat: 1 + m_EnableRandomWrite: 0 + m_TextureSettings: + serializedVersion: 2 + m_FilterMode: 1 + m_Aniso: 0 + m_MipBias: 0 + m_WrapU: 1 + m_WrapV: 1 + m_WrapW: 1 + m_Dimension: 2 + m_VolumeDepth: 1 + m_ShadowSamplingMode: 2 diff --git a/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.renderTexture.meta b/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.renderTexture.meta new file mode 100644 index 000000000..7c3ec219d --- /dev/null +++ b/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.renderTexture.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d873791053c443c1a79eedd22a687780 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 8400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.shader b/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.shader new file mode 100644 index 000000000..3aee99195 --- /dev/null +++ b/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.shader @@ -0,0 +1,120 @@ +Shader "AibisDream/DreamSeaMemory" +{ + Properties + { + [PerRendererData] _MainTex ("Poster Texture", 2D) = "white" {} + _VideoTex ("Video Texture", 2D) = "black" {} + _UseVideo ("Use Prepared Video", Range(0, 1)) = 0 + _Color ("Tint", Color) = (1,1,1,1) + _PixelGrid ("Virtual Pixel Grid", Vector) = (240,426,0,0) + _Contrast ("Contrast", Range(0.5, 2)) = 1 + _Levels ("Luminance Levels", Range(2, 16)) = 10 + _DitherStrength ("Dither Strength", Range(0, 0.1)) = 0.002 + } + + SubShader + { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + "PreviewType"="Plane" + "CanUseSpriteAtlas"="True" + } + + Cull Off + Lighting Off + ZWrite Off + Blend SrcAlpha OneMinusSrcAlpha + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 3.0 + + #include "UnityCG.cginc" + + struct appdata + { + float4 vertex : POSITION; + float4 color : COLOR; + float2 uv : TEXCOORD0; + }; + + struct v2f + { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float2 uv : TEXCOORD0; + }; + + sampler2D _MainTex; + sampler2D _VideoTex; + fixed4 _Color; + float _UseVideo; + float4 _PixelGrid; + float _Contrast; + float _Levels; + float _DitherStrength; + + v2f vert(appdata v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = v.uv; + o.color = v.color * _Color; + return o; + } + + float Bayer4x4(float2 pixel) + { + int x = ((int)pixel.x) & 3; + int y = ((int)pixel.y) & 3; + int index = x + y * 4; + + if (index == 0) return 0.0 / 16.0; + if (index == 1) return 8.0 / 16.0; + if (index == 2) return 2.0 / 16.0; + if (index == 3) return 10.0 / 16.0; + if (index == 4) return 12.0 / 16.0; + if (index == 5) return 4.0 / 16.0; + if (index == 6) return 14.0 / 16.0; + if (index == 7) return 6.0 / 16.0; + if (index == 8) return 3.0 / 16.0; + if (index == 9) return 11.0 / 16.0; + if (index == 10) return 1.0 / 16.0; + if (index == 11) return 9.0 / 16.0; + if (index == 12) return 15.0 / 16.0; + if (index == 13) return 7.0 / 16.0; + if (index == 14) return 13.0 / 16.0; + return 5.0 / 16.0; + } + + fixed4 frag(v2f i) : SV_Target + { + float2 grid = max(_PixelGrid.xy, float2(1.0, 1.0)); + float2 pixel = floor(i.uv * grid); + float2 sampleUv = (pixel + 0.5) / grid; + + fixed4 poster = tex2D(_MainTex, sampleUv); + fixed4 video = tex2D(_VideoTex, sampleUv); + float3 source = lerp(poster.rgb, video.rgb, saturate(_UseVideo)); + + float luminance = dot(source, float3(0.299, 0.587, 0.114)); + luminance = saturate((luminance - 0.5) * _Contrast + 0.5); + luminance = saturate(luminance + (Bayer4x4(pixel) - 0.5) * _DitherStrength); + + float levels = max(2.0, floor(_Levels + 0.5)); + luminance = floor(luminance * (levels - 1.0) + 0.5) / (levels - 1.0); + + return fixed4(luminance.xxx * i.color.rgb, poster.a * i.color.a); + } + ENDCG + } + } + + Fallback "Sprites/Default" +} diff --git a/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.shader.meta b/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.shader.meta new file mode 100644 index 000000000..3751d3071 --- /dev/null +++ b/Assets/GameContent/Scene_Dream/Materials/DreamSeaMemory.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a8d86af0aff94e1794fa50e65ac676d5 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameContent/Scene_Dream/animation/D2S_SeaMemory_Duo.mp4 b/Assets/GameContent/Scene_Dream/animation/D2S_SeaMemory_Duo.mp4 new file mode 100644 index 000000000..bec1dae7d --- /dev/null +++ b/Assets/GameContent/Scene_Dream/animation/D2S_SeaMemory_Duo.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d33a3e1f2477f161f5ba770ccda3bab33c1dd4c404d0c689d873a04894f3bae +size 2799606 diff --git a/Assets/GameContent/Scene_Dream/animation/D2S_SeaMemory_Duo.mp4.meta b/Assets/GameContent/Scene_Dream/animation/D2S_SeaMemory_Duo.mp4.meta new file mode 100644 index 000000000..de2b8b706 --- /dev/null +++ b/Assets/GameContent/Scene_Dream/animation/D2S_SeaMemory_Duo.mp4.meta @@ -0,0 +1,27 @@ +fileFormatVersion: 2 +guid: 9ed84eb452114d46b39fa43322d186ec +VideoClipImporter: + externalObjects: {} + serializedVersion: 2 + frameRange: 0 + startFrame: -1 + endFrame: -1 + colorSpace: 0 + deinterlace: 0 + encodeAlpha: 0 + flipVertical: 0 + flipHorizontal: 0 + importAudio: 0 + targetSettings: + 0: + enableTranscoding: 0 + codec: 0 + resizeFormat: 0 + aspectRatio: 0 + customWidth: 1 + customHeight: 1 + bitrateMode: 2 + spatialQuality: 2 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameContent/Scene_Dream/animation/D2S_SeaMemory_Duo_Poster.png b/Assets/GameContent/Scene_Dream/animation/D2S_SeaMemory_Duo_Poster.png new file mode 100644 index 000000000..2e89428af --- /dev/null +++ b/Assets/GameContent/Scene_Dream/animation/D2S_SeaMemory_Duo_Poster.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:827a16ba66367829cf916d8547faa3e817cd3ff782cda2005001e91c4e6b6047 +size 170641 diff --git a/Assets/GameContent/Scene_Dream/animation/D2S_SeaMemory_Duo_Poster.png.meta b/Assets/GameContent/Scene_Dream/animation/D2S_SeaMemory_Duo_Poster.png.meta new file mode 100644 index 000000000..9e64c317c --- /dev/null +++ b/Assets/GameContent/Scene_Dream/animation/D2S_SeaMemory_Duo_Poster.png.meta @@ -0,0 +1,114 @@ +fileFormatVersion: 2 +guid: 0d38a05e2cc64f5bb1958d3bdf78925d +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 12 + 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: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 0 + 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: 3 + 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: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Render/KiteFocusSprite.shader b/Assets/Render/KiteFocusSprite.shader index 3f623f71b..fa0175d49 100644 --- a/Assets/Render/KiteFocusSprite.shader +++ b/Assets/Render/KiteFocusSprite.shader @@ -8,6 +8,7 @@ Shader "AIBIS/KiteFocusSprite" [Header(Focus Blur)] _BlurAmount ("Blur Amount", Range(0, 1)) = 0 _BlurSize ("Blur Size", Range(0, 0.05)) = 0.012 + [HideInInspector] _UseSoftFocus ("Use Soft Focus", Float) = 0 _DefocusBloom ("Defocus Highlight Bloom", Range(0, 1)) = 0.32 _HaloStrength ("Large Circle Halo", Range(0, 0.6)) = 0.22 _ChromaticFringe ("Lens Color Fringe", Range(0, 0.6)) = 0.14 @@ -75,6 +76,7 @@ Shader "AIBIS/KiteFocusSprite" fixed4 _Color; float _BlurAmount; float _BlurSize; + float _UseSoftFocus; float _DefocusBloom; float _HaloStrength; float _ChromaticFringe; @@ -150,6 +152,33 @@ Shader "AIBIS/KiteFocusSprite" return result * 0.125; } + half4 SoftFocusBlur(float2 uv, float radius) + { + float nearRadius = radius * 0.48; + half4 result = samplePremultiplied(uv) * 0.20; + + result += samplePremultiplied(uv + float2( nearRadius, 0)) * 0.08; + result += samplePremultiplied(uv + float2(-nearRadius, 0)) * 0.08; + result += samplePremultiplied(uv + float2(0, nearRadius)) * 0.08; + result += samplePremultiplied(uv + float2(0, -nearRadius)) * 0.08; + + result += samplePremultiplied(uv + float2( nearRadius, nearRadius)) * 0.055; + result += samplePremultiplied(uv + float2(-nearRadius, nearRadius)) * 0.055; + result += samplePremultiplied(uv + float2( nearRadius, -nearRadius)) * 0.055; + result += samplePremultiplied(uv + float2(-nearRadius, -nearRadius)) * 0.055; + + result += samplePremultiplied(uv + float2( radius, 0)) * 0.04; + result += samplePremultiplied(uv + float2(-radius, 0)) * 0.04; + result += samplePremultiplied(uv + float2(0, radius)) * 0.04; + result += samplePremultiplied(uv + float2(0, -radius)) * 0.04; + + result += samplePremultiplied(uv + float2( radius, radius)) * 0.025; + result += samplePremultiplied(uv + float2(-radius, radius)) * 0.025; + result += samplePremultiplied(uv + float2( radius, -radius)) * 0.025; + result += samplePremultiplied(uv + float2(-radius, -radius)) * 0.025; + return result; + } + fixed4 frag(v2f i) : SV_Target { float blurAmt = saturate(_BlurAmount); @@ -164,6 +193,18 @@ Shader "AIBIS/KiteFocusSprite" float2 texel = max(abs(_MainTex_TexelSize.xy), float2(1e-5, 1e-5)); float radius = (length(texel) * 0.5 + _BlurSize) * (0.28 + blurAmt * 1.72); + + if (_UseSoftFocus > 0.5) + { + half4 softBlurred = SoftFocusBlur(i.uv, radius); + half4 softSharp = sharp; + softSharp.rgb *= softSharp.a; + half4 softColor = lerp(softSharp, softBlurred, smoothstep(0.0, 1.0, blurAmt)); + softColor.rgb *= i.color.rgb * i.color.a; + softColor.a *= i.color.a; + return softColor; + } + half4 disc = ApertureDisc(i.uv, radius); half4 halo = WideHalo(i.uv, radius * 1.85); half4 blurred = lerp(disc, halo, saturate(_HaloStrength * blurAmt)); diff --git a/Assets/Scenes/梦境.unity b/Assets/Scenes/梦境.unity index 3261017bf..52020e336 100644 --- a/Assets/Scenes/梦境.unity +++ b/Assets/Scenes/梦境.unity @@ -421,20 +421,20 @@ MonoBehaviour: m_EditorClassIdentifier: director: {fileID: 132823524} starfieldRenderer: {fileID: 1420961919} - initialBlur: 0.78 - blurSize: 0.009 + initialBlur: 0.58 + blurSize: 0.0045 firstAttemptStart: 0.45 - firstFocusDuration: 0.48 - firstNearFocusBlur: 0.38 - firstHoldDuration: 0.14 - firstSlipDuration: 0.38 - firstSlipBlur: 0.72 - secondAttemptStart: 1.72 - secondFocusDuration: 0.55 - secondNearFocusBlur: 0.28 - secondHoldDuration: 0.18 - secondSlipDuration: 0.46 - unresolvedBlur: 0.62 + firstFocusDuration: 0.72 + firstNearFocusBlur: 0.16 + firstHoldDuration: 0.1 + firstSlipDuration: 0.42 + firstSlipBlur: 0.52 + secondAttemptStart: 1.85 + secondFocusDuration: 0.82 + secondNearFocusBlur: 0.08 + secondHoldDuration: 0.12 + secondSlipDuration: 0.5 + unresolvedBlur: 0.44 blurFadeStart: 4 blurFadeDuration: 3.2 --- !u!1 &218986882 @@ -663,6 +663,9 @@ MonoBehaviour: frameRenderers: - {fileID: 1847534534} sceneBlackOverlay: {fileID: 1373573734} + glassSeaVideoClip: {fileID: 32900000, guid: 9ed84eb452114d46b39fa43322d186ec, type: 3} + glassSeaTargetTexture: {fileID: 8400000, guid: d873791053c443c1a79eedd22a687780, type: 2} + glassSeaPrepareTimeout: 5 terminalUI: {fileID: 1195418928} doorShellTransform: {fileID: 0} terminalShapeReference: {fileID: 1847534534} @@ -1510,15 +1513,27 @@ MonoBehaviour: typewriterCharDelay: 0.025 bootSpeedMultiplier: 4 bootSequence: - - text: '>> SYSTEM: Reality_Engine.sys stopped.' + - text: 'root@sys:~$ dream.render --stop --session 0742' style: 3 - delayAfter: 0.2 - - text: '>> SYSTEM: Rendering underlying code...' + delayAfter: 0.15 + - text: '[ OK ] Dream renderer stopped.' + style: 0 + delayAfter: 0.25 + - text: '[ RAW ] Untitled_Greybox_0 exposed.' + style: 0 + delayAfter: 0.35 + - text: 'root@sys:~$ trace --tail /log/dream_0742.rec' style: 3 - delayAfter: 0.2 - - text: '>> LOADING: Ocean_Simulation.sh ... OK' + delayAfter: 0.15 + - text: '[0005] audio.play("sea_ambient", source=door.rear)' style: 3 - delayAfter: 0.8 + delayAfter: 0.1 + - text: '[0006] memory.project("glass_sea")' + style: 3 + delayAfter: 0.1 + - text: '[ WARN ] memory source unresolved; overflow detected.' + style: 1 + delayAfter: 0.4 - text: "root@sys:~$ print_string(\"\u6D77\u662F\u5B58\u5728\u7684\u5417?\")" style: 2 delayAfter: 0.5 @@ -1791,7 +1806,7 @@ SpriteRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2} + - {fileID: 2100000, guid: 78265ded39f017d45a2afc117effab89, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -2602,7 +2617,7 @@ SpriteRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 1583441590} + - {fileID: 2100000, guid: e04544198a7d4f88ba592bf1feebbca2, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -2623,7 +2638,7 @@ SpriteRenderer: m_SortingLayerID: 844151739 m_SortingLayer: 1 m_SortingOrder: 5 - m_Sprite: {fileID: 21300000, guid: 8e0b68f1e994fc24b80e5a480c61602b, type: 3} + m_Sprite: {fileID: 21300000, guid: 0d38a05e2cc64f5bb1958d3bdf78925d, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 0} m_FlipX: 0 m_FlipY: 0 @@ -2643,8 +2658,8 @@ Transform: m_GameObject: {fileID: 1961593256904873106} serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.07, y: -0.03, z: 0} - m_LocalScale: {x: 0.7074555, y: 0.62522215, z: 0.8706811} + m_LocalPosition: {x: 0.02, y: 0.03, z: 0} + m_LocalScale: {x: 0.636667, y: 0.615, z: 0.8706811} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 450371655} diff --git a/Assets/Scripts/SceneManagement/DreamDoorSystem.cs b/Assets/Scripts/SceneManagement/DreamDoorSystem.cs index 233cf778a..beda35eec 100644 --- a/Assets/Scripts/SceneManagement/DreamDoorSystem.cs +++ b/Assets/Scripts/SceneManagement/DreamDoorSystem.cs @@ -4,6 +4,7 @@ using AibisDream.UI; using AibisDream.Utility; using DG.Tweening; using UnityEngine; +using UnityEngine.Video; namespace AibisDream { @@ -22,6 +23,11 @@ namespace AibisDream [SerializeField] private Renderer[] frameRenderers; [SerializeField] private SpriteRenderer sceneBlackOverlay; + [Header("Door Sea Memory")] + [SerializeField] private VideoClip glassSeaVideoClip; + [SerializeField] private RenderTexture glassSeaTargetTexture; + [SerializeField, Min(0.5f)] private float glassSeaPrepareTimeout = 5f; + [Header("Terminal(挂在 Door 子节点上即可,无需 Canvas)")] [SerializeField] private DreamTerminalUI terminalUI; @@ -56,6 +62,14 @@ namespace AibisDream private Vector3 _terminalUiOriginalLocalPosition; private Transform _doorShellTransform; private Vector3 _doorShellOriginalScale; + private VideoPlayer _glassSeaVideoPlayer; + private Material _glassSeaMaterial; + private bool _glassSeaVideoPrepared; + private bool _glassSeaVideoFailed; + private bool _glassSeaFrameReady; + private DoorPresentationPhase _presentationPhase = DoorPresentationPhase.Hidden; + + private static readonly int UseVideoId = Shader.PropertyToID("_UseVideo"); private enum FrameHidePhase { @@ -64,6 +78,15 @@ namespace AibisDream OnTerminal } + private enum DoorPresentationPhase + { + Hidden, + Door, + GlassSea, + CodeSea, + Terminal + } + public override void OnSingletonInit() { if (doorRoot != null) @@ -75,10 +98,14 @@ namespace AibisDream if (glassSea != null) { + _glassSeaMaterial = glassSea.material; + SetGlassSeaVideoVisible(false); glassSea.SetAlpha(0); glassSea.gameObject.SetActive(false); } + InitializeGlassSeaVideo(); + if (codeSea != null) { codeSea.SetAlpha(0); @@ -108,19 +135,33 @@ namespace AibisDream _terminalUiOriginalScale = _terminalUiTransform.localScale; _terminalUiOriginalLocalPosition = _terminalUiTransform.localPosition; } + + _presentationPhase = DoorPresentationPhase.Hidden; + } + + public override void OnSingletonDestroy() + { + if (_glassSeaVideoPlayer != null) + { + _glassSeaVideoPlayer.prepareCompleted -= OnGlassSeaVideoPrepared; + _glassSeaVideoPlayer.frameReady -= OnGlassSeaVideoFrameReady; + _glassSeaVideoPlayer.errorReceived -= OnGlassSeaVideoError; + } + + base.OnSingletonDestroy(); } /// - /// 显示整个门(仅 background + Frame,GlassSea/CodeSea 保持隐藏直到各自命令调用) + /// 显示普通门。该命令是一个完整状态切换,会清掉之前残留的海景、代码海浪和终端。 /// public IEnumerator ShowDoor(float duration = 0f) { - if (doorRoot != null) - doorRoot.gameObject.SetActive(true); - - SetBackgroundVisible(true); - SetFrameVisible(true); - ResetDoorShellScale(); + StopAllEffects(); + EnsureDoorBaseVisible(); + ResetGlassSeaImmediate(stopVideo: true); + ResetCodeSeaImmediate(); + ResetTerminalImmediate(); + _presentationPhase = DoorPresentationPhase.Door; if (duration > 0f) yield return new WaitForSeconds(duration); @@ -139,18 +180,48 @@ namespace AibisDream public IEnumerator ShowGlassSea(float duration = 2f) { + if (glassSea == null) + yield break; + + StopAllEffects(); + EnsureDoorBaseVisible(); + ResetCodeSeaImmediate(); + ResetTerminalImmediate(); + + if (_presentationPhase != DoorPresentationPhase.GlassSea || !glassSea.gameObject.activeSelf) + glassSea.SetAlpha(0f); + glassSea.gameObject.SetActive(true); - yield return glassSea.DOFade(1f, duration) + _presentationPhase = DoorPresentationPhase.GlassSea; + yield return EnsureGlassSeaVideoPlaying(); + yield return glassSea.DOFade(1f, Mathf.Max(0f, duration)) .SetEase(Ease.InOutSine) .WaitForCompletion(); } public IEnumerator HideGlassSea(float duration = 1f) { - yield return glassSea.DOFade(0f, duration) - .SetEase(Ease.InOutSine) - .WaitForCompletion(); + if (glassSea == null) + { + PauseGlassSeaVideo(); + yield break; + } + + DOTween.Kill(glassSea); + + if (glassSea.gameObject.activeSelf) + { + yield return glassSea.DOFade(0f, Mathf.Max(0f, duration)) + .SetEase(Ease.InOutSine) + .WaitForCompletion(); + } + + glassSea.SetAlpha(0f); glassSea.gameObject.SetActive(false); + PauseGlassSeaVideo(); + + if (_presentationPhase == DoorPresentationPhase.GlassSea) + _presentationPhase = DoorPresentationPhase.Door; } #endregion @@ -159,21 +230,39 @@ namespace AibisDream public IEnumerator ShowCodeSea(float duration = 2f) { + if (codeSea == null) + yield break; + + StopAllEffects(); + EnsureDoorBaseVisible(); + ResetTerminalImmediate(); + + codeSea.color = _codeSeaOriginalColor; + if (_codeSeaTransform != null) + _codeSeaTransform.localScale = _codeSeaOriginalScale; + codeSea.SetAlpha(0f); codeSea.gameObject.SetActive(true); + _presentationPhase = DoorPresentationPhase.CodeSea; + if (frameHidePhase == FrameHidePhase.OnCodeSea) SetFrameVisible(false); var seq = DOTween.Sequence(); - seq.Append(codeSea.DOFade(1f, duration).SetEase(Ease.InOutSine)); + seq.Append(codeSea.DOFade(1f, Mathf.Max(0f, duration)).SetEase(Ease.InOutSine)); if (glassSea != null && glassSea.gameObject.activeSelf) { - seq.Join(glassSea.DOFade(0f, duration * 0.7f).SetEase(Ease.InSine)); + seq.Join(glassSea.DOFade(0f, Mathf.Max(0f, duration) * 0.7f).SetEase(Ease.InSine)); } yield return seq.WaitForCompletion(); if (glassSea != null) + { + glassSea.SetAlpha(0f); glassSea.gameObject.SetActive(false); + } + + StopGlassSeaVideo(); } #endregion @@ -182,6 +271,7 @@ namespace AibisDream public IEnumerator ShowTerminal() { + _presentationPhase = DoorPresentationPhase.Terminal; yield return AnimateDoorToTerminal(); if (terminalUI != null) { @@ -214,6 +304,8 @@ namespace AibisDream if (glassSea != null) glassSea.gameObject.SetActive(false); + StopGlassSeaVideo(); + if (codeSea != null) codeSea.gameObject.SetActive(false); @@ -288,6 +380,7 @@ namespace AibisDream public void StopAllEffects() { + DOTween.Kill(glassSea); DOTween.Kill(_codeSeaTransform); DOTween.Kill(codeSea); DOTween.Kill(_terminalUiTransform); @@ -314,6 +407,8 @@ namespace AibisDream glassSea.gameObject.SetActive(false); } + StopGlassSeaVideo(); + if (codeSea != null) { codeSea.color = _codeSeaOriginalColor; @@ -340,6 +435,193 @@ namespace AibisDream if (sceneBlackOverlay != null) sceneBlackOverlay.SetAlpha(0); + + _presentationPhase = DoorPresentationPhase.Hidden; + } + + #endregion + + #region Presentation State + + private void EnsureDoorBaseVisible() + { + if (doorRoot != null) + doorRoot.gameObject.SetActive(true); + + SetBackgroundVisible(true); + SetFrameVisible(true); + ResetDoorShellScale(); + } + + private void ResetGlassSeaImmediate(bool stopVideo) + { + DOTween.Kill(glassSea); + + if (glassSea != null) + { + glassSea.SetAlpha(0f); + glassSea.gameObject.SetActive(false); + } + + if (stopVideo) + StopGlassSeaVideo(); + else + PauseGlassSeaVideo(); + } + + private void ResetCodeSeaImmediate() + { + DOTween.Kill(_codeSeaTransform); + DOTween.Kill(codeSea); + + if (codeSea == null) + return; + + codeSea.color = _codeSeaOriginalColor; + codeSea.SetAlpha(0f); + codeSea.gameObject.SetActive(false); + + if (_codeSeaTransform != null) + _codeSeaTransform.localScale = _codeSeaOriginalScale; + } + + private void ResetTerminalImmediate() + { + DOTween.Kill(_terminalUiTransform); + + if (terminalUI != null) + { + terminalUI.Alpha = 0f; + terminalUI.ResetVisualState(); + } + + if (_terminalUiTransform != null) + { + _terminalUiTransform.localPosition = _terminalUiOriginalLocalPosition; + _terminalUiTransform.localScale = _terminalUiOriginalScale; + } + + if (flashOverlay != null) + flashOverlay.SetAlpha(0f); + + if (sceneBlackOverlay != null) + sceneBlackOverlay.SetAlpha(0f); + } + + #endregion + + #region GlassSea Video + + private void InitializeGlassSeaVideo() + { + if (glassSeaVideoClip == null || glassSeaTargetTexture == null) + { + SetGlassSeaVideoVisible(false); + return; + } + + _glassSeaVideoPlayer = GetComponent(); + if (_glassSeaVideoPlayer == null) + _glassSeaVideoPlayer = gameObject.AddComponent(); + + _glassSeaVideoPlayer.playOnAwake = false; + _glassSeaVideoPlayer.source = VideoSource.VideoClip; + _glassSeaVideoPlayer.clip = glassSeaVideoClip; + _glassSeaVideoPlayer.renderMode = VideoRenderMode.RenderTexture; + _glassSeaVideoPlayer.targetTexture = glassSeaTargetTexture; + _glassSeaVideoPlayer.audioOutputMode = VideoAudioOutputMode.None; + _glassSeaVideoPlayer.isLooping = true; + _glassSeaVideoPlayer.skipOnDrop = true; + _glassSeaVideoPlayer.waitForFirstFrame = true; + _glassSeaVideoPlayer.sendFrameReadyEvents = true; + + _glassSeaVideoPlayer.prepareCompleted += OnGlassSeaVideoPrepared; + _glassSeaVideoPlayer.frameReady += OnGlassSeaVideoFrameReady; + _glassSeaVideoPlayer.errorReceived += OnGlassSeaVideoError; + + _glassSeaVideoPrepared = false; + _glassSeaVideoFailed = false; + _glassSeaFrameReady = false; + SetGlassSeaVideoVisible(false); + _glassSeaVideoPlayer.Prepare(); + } + + private IEnumerator EnsureGlassSeaVideoPlaying() + { + if (_glassSeaVideoPlayer == null || _glassSeaVideoFailed) + { + SetGlassSeaVideoVisible(false); + yield break; + } + + if (!_glassSeaVideoPrepared && !_glassSeaVideoPlayer.isPrepared) + { + float deadline = Time.realtimeSinceStartup + glassSeaPrepareTimeout; + while (!_glassSeaVideoPrepared && !_glassSeaVideoFailed && Time.realtimeSinceStartup < deadline) + yield return null; + + if (!_glassSeaVideoPrepared && !_glassSeaVideoPlayer.isPrepared) + { + _glassSeaVideoFailed = true; + _glassSeaVideoPlayer.Stop(); + SetGlassSeaVideoVisible(false); + Debug.LogWarning("[DreamDoorSystem] 海景视频准备超时,回退到静态海报。", this); + yield break; + } + } + + _glassSeaVideoPrepared = true; + if (!_glassSeaVideoPlayer.isPlaying) + _glassSeaVideoPlayer.Play(); + + if (!_glassSeaFrameReady) + { + float firstFrameDeadline = Time.realtimeSinceStartup + 1f; + while (!_glassSeaFrameReady && !_glassSeaVideoFailed && Time.realtimeSinceStartup < firstFrameDeadline) + yield return null; + } + } + + private void PauseGlassSeaVideo() + { + if (_glassSeaVideoPlayer != null && _glassSeaVideoPlayer.isPlaying) + _glassSeaVideoPlayer.Pause(); + } + + private void StopGlassSeaVideo() + { + if (_glassSeaVideoPlayer != null) + _glassSeaVideoPlayer.Stop(); + + _glassSeaFrameReady = false; + SetGlassSeaVideoVisible(false); + } + + private void OnGlassSeaVideoPrepared(VideoPlayer source) + { + _glassSeaVideoPrepared = true; + _glassSeaVideoFailed = false; + } + + private void OnGlassSeaVideoFrameReady(VideoPlayer source, long frameIndex) + { + _glassSeaFrameReady = true; + SetGlassSeaVideoVisible(true); + } + + private void OnGlassSeaVideoError(VideoPlayer source, string message) + { + _glassSeaVideoFailed = true; + _glassSeaVideoPrepared = false; + _glassSeaFrameReady = false; + SetGlassSeaVideoVisible(false); + Debug.LogWarning($"[DreamDoorSystem] 海景视频播放失败,回退到静态海报:{message}", this); + } + + private void SetGlassSeaVideoVisible(bool visible) + { + if (_glassSeaMaterial != null && _glassSeaMaterial.HasProperty(UseVideoId)) + _glassSeaMaterial.SetFloat(UseVideoId, visible ? 1f : 0f); } #endregion diff --git a/Assets/Scripts/SceneManagement/TimelineKit/StarfieldDefocusController.cs b/Assets/Scripts/SceneManagement/TimelineKit/StarfieldDefocusController.cs index e11595444..747efc7e9 100644 --- a/Assets/Scripts/SceneManagement/TimelineKit/StarfieldDefocusController.cs +++ b/Assets/Scripts/SceneManagement/TimelineKit/StarfieldDefocusController.cs @@ -1,5 +1,7 @@ +using System.Collections; using UnityEngine; using UnityEngine.Playables; +using Yarn.Unity; namespace AibisDream { @@ -12,6 +14,7 @@ namespace AibisDream { private static readonly int BlurAmountId = Shader.PropertyToID("_BlurAmount"); private static readonly int BlurSizeId = Shader.PropertyToID("_BlurSize"); + private static readonly int UseSoftFocusId = Shader.PropertyToID("_UseSoftFocus"); [Header("References")] [SerializeField] private PlayableDirector director; @@ -60,6 +63,114 @@ namespace AibisDream private MaterialPropertyBlock propertyBlock; + [YarnCommand("starfield_prepare")] + public static void PrepareStarfieldCommand() + { + var controller = FindFirstObjectByType(); + if (controller == null) + { + Debug.LogWarning("[StarfieldDefocusController] No active controller found for starfield_prepare."); + return; + } + + controller.PrepareStarfield(); + } + + [YarnCommand("starfield_focus")] + public static IEnumerator PlayFocusAttemptCommand(int attempt) + { + var controller = FindFirstObjectByType(); + if (controller == null) + { + Debug.LogWarning("[StarfieldDefocusController] No active controller found for starfield_focus."); + yield break; + } + + yield return controller.PlayFocusAttempt(attempt); + } + + [YarnCommand("starfield_descend")] + public static IEnumerator DescendToSeaCommand() + { + var controller = FindFirstObjectByType(); + if (controller == null) + { + Debug.LogWarning("[StarfieldDefocusController] No active controller found for starfield_descend."); + yield break; + } + + yield return controller.DescendToSea(); + } + + private void PrepareStarfield() + { + if (!TryValidateReferences()) + { + return; + } + + director.Stop(); + SetTimelineTime(0f); + } + + private IEnumerator PlayFocusAttempt(int attempt) + { + if (!TryValidateReferences()) + { + yield break; + } + + float startTime; + float endTime; + switch (attempt) + { + case 1: + startTime = firstAttemptStart; + endTime = firstAttemptStart + firstFocusDuration + firstHoldDuration + firstSlipDuration; + break; + case 2: + startTime = secondAttemptStart; + endTime = secondAttemptStart + secondFocusDuration + secondHoldDuration + secondSlipDuration; + break; + default: + Debug.LogWarning($"[StarfieldDefocusController] Unsupported focus attempt '{attempt}'. Expected 1 or 2.", this); + yield break; + } + + director.Pause(); + SetTimelineTime(startTime); + + float duration = Mathf.Max(0.01f, endTime - startTime); + float elapsed = 0f; + while (elapsed < duration) + { + elapsed += Time.deltaTime; + SetTimelineTime(Mathf.Lerp(startTime, endTime, Mathf.Clamp01(elapsed / duration))); + yield return null; + } + + SetTimelineTime(endTime); + } + + private IEnumerator DescendToSea() + { + if (!TryValidateReferences()) + { + yield break; + } + + director.Pause(); + SetTimelineTime(blurFadeStart); + director.Play(); + + while (director.state == PlayState.Playing) + { + yield return null; + } + + ApplyAtTime((float)director.time); + } + private void Reset() { director = GetComponent(); @@ -87,6 +198,45 @@ namespace AibisDream ApplyAtTime((float)director.time); } + private bool TryValidateReferences() + { + if (director == null) + { + Debug.LogWarning("[StarfieldDefocusController] PlayableDirector is not assigned.", this); + return false; + } + + if (director.playableAsset == null) + { + Debug.LogWarning("[StarfieldDefocusController] PlayableDirector has no Timeline asset.", this); + return false; + } + + if (starfieldRenderer == null) + { + Debug.LogWarning("[StarfieldDefocusController] Starfield SpriteRenderer is not assigned.", this); + return false; + } + + var material = starfieldRenderer.sharedMaterial; + if (material == null || !material.HasProperty(BlurAmountId) || !material.HasProperty(BlurSizeId)) + { + Debug.LogWarning( + "[StarfieldDefocusController] Starfield material must support _BlurAmount and _BlurSize.", + starfieldRenderer); + return false; + } + + return true; + } + + private void SetTimelineTime(float time) + { + director.time = Mathf.Clamp(time, 0f, (float)director.duration); + director.Evaluate(); + ApplyAtTime((float)director.time); + } + private void ApplyAtTime(float time) { if (starfieldRenderer == null) @@ -98,6 +248,7 @@ namespace AibisDream starfieldRenderer.GetPropertyBlock(propertyBlock); propertyBlock.SetFloat(BlurAmountId, EvaluateBlur(time)); propertyBlock.SetFloat(BlurSizeId, blurSize); + propertyBlock.SetFloat(UseSoftFocusId, 1f); starfieldRenderer.SetPropertyBlock(propertyBlock); } @@ -118,7 +269,10 @@ namespace AibisDream if (time < firstFocusEnd) { - return SmoothLerp(initialBlur, firstNearFocusBlur, InverseLerp(firstAttemptStart, firstFocusEnd, time)); + return EvaluateFocusTurn( + initialBlur, + firstNearFocusBlur, + InverseLerp(firstAttemptStart, firstFocusEnd, time)); } if (time < firstHoldEnd) @@ -138,7 +292,10 @@ namespace AibisDream if (time < secondFocusEnd) { - return SmoothLerp(firstSlipBlur, secondNearFocusBlur, InverseLerp(secondAttemptStart, secondFocusEnd, time)); + return EvaluateFocusTurn( + firstSlipBlur, + secondNearFocusBlur, + InverseLerp(secondAttemptStart, secondFocusEnd, time)); } if (time < secondHoldEnd) @@ -159,6 +316,29 @@ namespace AibisDream return SmoothLerp(unresolvedBlur, 0f, InverseLerp(blurFadeStart, blurFadeStart + blurFadeDuration, time)); } + /// + /// Simulates turning a focus ring toward focus, passing the focal plane, + /// then reversing back. The following slip phase still lets the image + /// drift out of focus, keeping both attempts deliberately unsuccessful. + /// + private static float EvaluateFocusTurn(float fromBlur, float nearFocusBlur, float t) + { + t = Mathf.Clamp01(t); + float overshootBlur = Mathf.Lerp(nearFocusBlur, fromBlur, 0.68f); + + if (t < 0.44f) + { + return SmoothLerp(fromBlur, nearFocusBlur, t / 0.44f); + } + + if (t < 0.72f) + { + return SmoothLerp(nearFocusBlur, overshootBlur, (t - 0.44f) / 0.28f); + } + + return SmoothLerp(overshootBlur, nearFocusBlur, (t - 0.72f) / 0.28f); + } + private static float InverseLerp(float from, float to, float value) { return Mathf.Clamp01((value - from) / Mathf.Max(0.0001f, to - from)); diff --git a/Assets/Scripts/UI/Components/DreamTerminalUI.cs b/Assets/Scripts/UI/Components/DreamTerminalUI.cs index c5bacd596..e2f7ba2eb 100644 --- a/Assets/Scripts/UI/Components/DreamTerminalUI.cs +++ b/Assets/Scripts/UI/Components/DreamTerminalUI.cs @@ -98,14 +98,14 @@ namespace AibisDream.UI [Header("启动日志")] [SerializeField] private List bootSequence = new() { - new BootLogEntry { text = "root@sys:~$ ./boot --test", style = LogStyle.Dim, delayAfter = 0.2f }, - new BootLogEntry { text = "[ OK ] Test passed.", style = LogStyle.Normal, delayAfter = 0.2f }, - new BootLogEntry { text = "root@sys:~$ render --target ocean && aplay sea.wav", style = LogStyle.Dim, delayAfter = 0.2f }, - new BootLogEntry { text = "[ OK ] Ocean rendered. Audio stream started.", style = LogStyle.Normal, delayAfter = 0.2f }, - new BootLogEntry { text = "root@sys:~$ render --stop", style = LogStyle.Dim, delayAfter = 0.2f }, - new BootLogEntry { text = "[ OK ] Render pipeline closed.", style = LogStyle.Normal, delayAfter = 0.2f }, - new BootLogEntry { text = "root@sys:~$ showcode", style = LogStyle.Alert, delayAfter = 0.2f }, - new BootLogEntry { text = "root@sys:~$ print_string(\"海是存在的吗?\")", style = LogStyle.Highlight, delayAfter = 0.2f }, + new BootLogEntry { text = "root@sys:~$ dream.render --stop --session 0742", style = LogStyle.Dim, delayAfter = 0.15f }, + new BootLogEntry { text = "[ OK ] Dream renderer stopped.", style = LogStyle.Normal, delayAfter = 0.25f }, + new BootLogEntry { text = "[ RAW ] Untitled_Greybox_0 exposed.", style = LogStyle.Normal, delayAfter = 0.35f }, + new BootLogEntry { text = "root@sys:~$ trace --tail /log/dream_0742.rec", style = LogStyle.Dim, delayAfter = 0.15f }, + new BootLogEntry { text = "[0005] audio.play(\"sea_ambient\", source=door.rear)", style = LogStyle.Dim, delayAfter = 0.1f }, + new BootLogEntry { text = "[0006] memory.project(\"glass_sea\")", style = LogStyle.Dim, delayAfter = 0.1f }, + new BootLogEntry { text = "[ WARN ] memory source unresolved; overflow detected.", style = LogStyle.Alert, delayAfter = 0.4f }, + new BootLogEntry { text = "root@sys:~$ print_string(\"海是存在的吗?\")", style = LogStyle.Highlight, delayAfter = 0.5f }, }; #endregion diff --git a/Assets/Yarn/FP/FP_Day1_sleep/FP_Day1_sleep.yarn b/Assets/Yarn/FP/FP_Day1_sleep/FP_Day1_sleep.yarn index bb12b1d38..e42fbf6ea 100644 --- a/Assets/Yarn/FP/FP_Day1_sleep/FP_Day1_sleep.yarn +++ b/Assets/Yarn/FP/FP_Day1_sleep/FP_Day1_sleep.yarn @@ -345,7 +345,7 @@ title: 女孩_已完成 position: 743,-1403 tags: detour --- -//girl: 女孩一边哼歌一边继续涂画着,
没有听到你的声音。
#line:01ef1ed +girl: 女孩一边哼歌一边继续涂画着,
没有听到你的声音。
#line:01ef1ed === title: 天台 @@ -606,17 +606,17 @@ tags: linear <> <> -【星空是模糊的,很难看清】 +<> girl: 怎么还是看不清? -【调试镜头】 +<> jj: 这都漏雨了。它太旧了,应该很难修好了。 girl: 不好!肯定是还有什么地方没弄好… -【调试镜头】 +<> jj: 走吧,我们在这里也玩够了。 @@ -634,10 +634,9 @@ girl: 你刚才还不是这么说的。 me: 姐姐…… -【镜头变得模糊,下摇】 +<> <> -<> <> <> diff --git a/Assets/Yarn/FP/FP_Day2_sleep/FP_Day2_sleep.yarn b/Assets/Yarn/FP/FP_Day2_sleep/FP_Day2_sleep.yarn index 668324c73..24dfd4dd4 100644 --- a/Assets/Yarn/FP/FP_Day2_sleep/FP_Day2_sleep.yarn +++ b/Assets/Yarn/FP/FP_Day2_sleep/FP_Day2_sleep.yarn @@ -822,6 +822,7 @@ position: -4,927 <> <> <> + <> <> <> 一扇紧闭的手术室门。让人感觉很熟悉。 #line:0ba4b43 @@ -886,6 +887,8 @@ position: -4,927 <> <> 一种莫名的亲切感。 #line:0dfe59e + <> + <> ->靠近黑暗<> #line:02cb5f1 // 黑暗中闪烁着无数微弱的绿色光点。那是无数段代码。 #line:0dc92eb // 其中一段正静静地漂浮在你的面前。 #line:07400da @@ -981,6 +984,7 @@ me: 海… #line:00a7bf5 <> <> <> +<> <> <> <>