diff --git a/Cyan-Stars/Assets/BundleRes/Scenes/ChartEditor.unity b/Cyan-Stars/Assets/BundleRes/Scenes/ChartEditor.unity index 7f2a5a7b7..8e4057d68 100644 --- a/Cyan-Stars/Assets/BundleRes/Scenes/ChartEditor.unity +++ b/Cyan-Stars/Assets/BundleRes/Scenes/ChartEditor.unity @@ -3834,6 +3834,164 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 208578990} m_CullTransparentMesh: 1 +--- !u!1 &234885784 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 234885785} + - component: {fileID: 234885788} + - component: {fileID: 234885787} + - component: {fileID: 234885786} + m_Layer: 5 + m_Name: Text (TMP) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &234885785 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 234885784} + 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: 542396988} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &234885786 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 234885784} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: 598.233 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &234885787 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 234885784} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + 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_text: "\u663E\u793A\u97F3\u9891\u66F2\u7EBF" + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 5d14d235b5318bc49a0e892f337a7e87, type: 2} + m_sharedMaterial: {fileID: 5463881750006113116, guid: 5d14d235b5318bc49a0e892f337a7e87, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 36 + m_fontSizeBase: 36 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_characterHorizontalScale: 1 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!222 &234885788 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 234885784} + m_CullTransparentMesh: 1 --- !u!1 &239559643 GameObject: m_ObjectHideFlags: 0 @@ -8050,10 +8208,10 @@ RectTransform: - {fileID: 978114220} m_Father: {fileID: 1514540015} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0, y: 0} - m_SizeDelta: {x: 0, y: 602.50006} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 100, y: -717.50006} + m_SizeDelta: {x: 1205.0001, y: 0} m_Pivot: {x: 0, y: 0} --- !u!114 &442738496 MonoBehaviour: @@ -9683,6 +9841,70 @@ RectTransform: m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 0, y: 75} m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &542396987 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 542396988} + - component: {fileID: 542396989} + m_Layer: 5 + m_Name: "\u663E\u793A\u97F3\u9891\u66F2\u7EBFFrame" + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &542396988 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 542396987} + 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: 234885785} + - {fileID: 798982892} + m_Father: {fileID: 1297060270} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 75} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &542396989 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 542396987} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 40 + m_Right: 40 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 0 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 --- !u!1 &543012495 GameObject: m_ObjectHideFlags: 0 @@ -9881,6 +10103,7 @@ MonoBehaviour: notesFrameRect: {fileID: 200356153} scrollRect: {fileID: 1746494796} judgeLineRect: {fileID: 2134614510} + audioWaveRawImage: {fileID: 702279848} --- !u!1 &549145901 GameObject: m_ObjectHideFlags: 0 @@ -13539,6 +13762,78 @@ MonoBehaviour: m_EditorClassIdentifier: m_Padding: {x: 0, y: 0, z: 0, w: 0} m_Softness: {x: 0, y: 0} +--- !u!1 &702279846 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 702279847} + - component: {fileID: 702279849} + - component: {fileID: 702279848} + m_Layer: 5 + m_Name: AudioWave + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &702279847 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 702279846} + 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: 1023559425} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.25, y: 0} + m_AnchorMax: {x: 0.75, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0} +--- !u!114 &702279848 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 702279846} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.RawImage + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 0 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Texture: {fileID: 0} + m_UVRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 +--- !u!222 &702279849 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 702279846} + m_CullTransparentMesh: 1 --- !u!1001 &717315022 PrefabInstance: m_ObjectHideFlags: 0 @@ -15146,6 +15441,172 @@ RectTransform: m_CorrespondingSourceObject: {fileID: 8632055456003868757, guid: f11dfa8f2cee203408b50a343df0badb, type: 3} m_PrefabInstance: {fileID: 793223616} m_PrefabAsset: {fileID: 0} +--- !u!1001 &798982891 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 542396988} + m_Modifications: + - target: {fileID: 1267847065536664933, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_SizeDelta.x + value: 48 + objectReference: {fileID: 0} + - target: {fileID: 1267847065536664933, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_SizeDelta.y + value: 48 + objectReference: {fileID: 0} + - target: {fileID: 2267842852582037851, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_fontSize + value: 41.05 + objectReference: {fileID: 0} + - target: {fileID: 2870093097978841429, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_Sprite + value: + objectReference: {fileID: 21300000, guid: 5aaa57c84d13ebd498cd8001c99c0e11, type: 3} + - target: {fileID: 4573623285734476500, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: rectTransformToChangeScale.Array.size + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 4573623285734476500, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: 'rectTransformToChangeScale.Array.data[3]' + value: + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_SizeDelta.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7757076495624774869, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + propertyPath: m_Name + value: RadioButton + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: + - {fileID: 6806352148778909055, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + m_AddedGameObjects: [] + m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 7757076495624774869, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + insertIndex: -1 + addedObject: {fileID: 798982894} + m_SourcePrefab: {fileID: 100100000, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} +--- !u!224 &798982892 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 7757076495624774868, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + m_PrefabInstance: {fileID: 798982891} + m_PrefabAsset: {fileID: 0} +--- !u!1 &798982893 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 7757076495624774869, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + m_PrefabInstance: {fileID: 798982891} + m_PrefabAsset: {fileID: 0} +--- !u!114 &798982894 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 798982893} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreLayout: 0 + m_MinWidth: -1 + m_MinHeight: -1 + m_PreferredWidth: 726.7668 + m_PreferredHeight: -1 + m_FlexibleWidth: -1 + m_FlexibleHeight: -1 + m_LayoutPriority: 1 +--- !u!114 &798982895 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 1811875860408279174, guid: 90efbfb46b5e7f94aae8607cfb874781, type: 3} + m_PrefabInstance: {fileID: 798982891} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 798982893} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d6424005847f4a129610fd8e1965bb41, type: 3} + m_Name: + m_EditorClassIdentifier: CyanStars::CyanStars.Utils.RadioButton.RadioButtonItem --- !u!1 &801457131 GameObject: m_ObjectHideFlags: 0 @@ -19254,6 +19715,7 @@ RectTransform: m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: + - {fileID: 702279847} - {fileID: 1974464501} - {fileID: 200356153} m_Father: {fileID: 487915726} @@ -23621,6 +24083,10 @@ PrefabInstance: propertyPath: m_Name value: "\u5236\u8C31\u5668\u8BBE\u7F6E\u5F39\u7A97Canvas" objectReference: {fileID: 0} + - target: {fileID: 994941279456320301, guid: 21018f88cf8fd3d468929538bb4e0c4a, type: 3} + propertyPath: m_Enabled + value: 0 + objectReference: {fileID: 0} - target: {fileID: 994941279456320303, guid: 21018f88cf8fd3d468929538bb4e0c4a, type: 3} propertyPath: m_Pivot.x value: 0.5 @@ -23756,9 +24222,10 @@ MonoBehaviour: audioMixer: {fileID: 24100000, guid: c5a148793f573b34885fa0eb984dfa73, type: 2} musicVolumeField: {fileID: 590199864} noteVolumeField: {fileID: 2039431223} - isCompactNoteButtonAreaButton: {fileID: 1413580225} isMultiBpmItemButton: {fileID: 1320703400} isMultiMusicItemButton: {fileID: 434106518} + isCompactNoteButtonAreaButton: {fileID: 1413580225} + isShowingAudioWave: {fileID: 798982895} --- !u!1001 &1286130100 PrefabInstance: m_ObjectHideFlags: 0 @@ -23935,9 +24402,10 @@ RectTransform: m_Children: - {fileID: 1230908547} - {fileID: 1122245071} - - {fileID: 899722264} - {fileID: 1150858797} - {fileID: 784130505} + - {fileID: 899722264} + - {fileID: 542396988} m_Father: {fileID: 1300828993} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} @@ -33800,7 +34268,7 @@ MonoBehaviour: m_HandleRect: {fileID: 964606382} m_Direction: 2 m_Value: 1 - m_Size: 0.9704348 + m_Size: 0.8086957 m_NumberOfSteps: 0 m_OnValueChanged: m_PersistentCalls: diff --git a/Cyan-Stars/Assets/Scripts/CyanStars.asmdef b/Cyan-Stars/Assets/Scripts/CyanStars.asmdef index 0ef18680a..1e59ebb63 100644 --- a/Cyan-Stars/Assets/Scripts/CyanStars.asmdef +++ b/Cyan-Stars/Assets/Scripts/CyanStars.asmdef @@ -3,6 +3,7 @@ "rootNamespace": "CyanStars", "references": [ "GUID:a6b40c9ae77eca3438197e7d0aafc4d6", + "GUID:2665a8d13d1b3f18800f46e256720795", "GUID:d8b63aba1907145bea998dd612889d6b", "GUID:df380645f10b7bc4b97d4f5eb6303d95", "GUID:15fc0a57446b3144c949da3e2b9737a9", diff --git a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/AudioWaveformGenerator.cs b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/AudioWaveformGenerator.cs new file mode 100644 index 000000000..3c9065908 --- /dev/null +++ b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/AudioWaveformGenerator.cs @@ -0,0 +1,250 @@ +#nullable enable + +using System; +using System.Threading; +using System.Threading.Tasks; +using Unity.Burst; +using Unity.Collections; +using Unity.Jobs; +using Unity.Mathematics; +using UnityEngine; + +namespace CyanStars.Gameplay.ChartEditor.View +{ + public class AudioWaveformGenerator : IDisposable + { + private const int AudioWaveTextureWidthPixel = 32; + private const float AudioWaveSamplesPerSecond = 10f; + private readonly Color32 AudioWaveColor = new Color32(255, 255, 255, 13); + private readonly Color32 ClearColor = new Color32(0, 0, 0, 0); + + // 缓存的预计算数据 + private NativeArray precomputedSamples; + private int cachedMusicOffset; + private AudioClip? cachedClip; + private Texture2D? currentTexture; + + public void Dispose() + { + if (precomputedSamples.IsCreated) + { + precomputedSamples.Dispose(); + } + if (currentTexture != null) + { + UnityEngine.Object.Destroy(currentTexture); + } + } + + /// + /// 预计算音频数据 + /// + public async Task PrecomputeAsync(AudioClip? clip, int musicOffset, CancellationToken token) + { + if (clip == cachedClip && musicOffset == cachedMusicOffset) + return; // 数据未变,无需重新预计算 + + cachedClip = clip; + cachedMusicOffset = musicOffset; + + if (precomputedSamples.IsCreated) + precomputedSamples.Dispose(); + + if (clip == null) + return; + + int clipSamples = clip.samples; + int clipChannels = clip.channels; + int clipFrequency = clip.frequency; + float clipLength = clip.length; + + float[] fullSamples = new float[clipSamples * clipChannels]; + clip.GetData(fullSamples, 0); + + // 异步执行降采样计算 + await Task.Run(() => + { + float musicOffsetS = musicOffset / 1000f; + float timelineTotalTimeS = math.max(0, clipLength + musicOffsetS); + int samplesCount = (int)math.ceil(timelineTotalTimeS * AudioWaveSamplesPerSecond); + + NativeArray rawSamples = new NativeArray(fullSamples, Allocator.Persistent); + NativeArray downsampled = new NativeArray(samplesCount, Allocator.Persistent); + + try + { + var downsampleJob = new DownsampleAudioJob + { + FullSamples = rawSamples, + Channels = clipChannels, + Frequency = clipFrequency, + ClipSamples = clipSamples, + MusicOffsetS = musicOffsetS, + TimelineTotalTimeS = timelineTotalTimeS, + SamplesCount = samplesCount, + Result = downsampled + }; + + downsampleJob.Schedule(samplesCount, 64).Complete(); + + // 找出最大值 + float maxAmp = 0.0001f; + for (int i = 0; i < samplesCount; i++) + { + if (downsampled[i] > maxAmp) maxAmp = downsampled[i]; + } + + // 归一化并缓存 + precomputedSamples = new NativeArray(samplesCount, Allocator.Persistent); + for (int i = 0; i < samplesCount; i++) + { + precomputedSamples[i] = downsampled[i] / maxAmp; + } + } + finally + { + rawSamples.Dispose(); + downsampled.Dispose(); + } + }, token); + } + + /// + /// 异步生成纹理 + /// + public async Task GenerateTextureAsync(int uiHeight, CancellationToken token) + { + if (!precomputedSamples.IsCreated || precomputedSamples.Length == 0 || uiHeight <= 0) + return null; + + int maxTexSize = math.min(SystemInfo.maxTextureSize, 8192); + int texHeight = math.clamp(uiHeight, 1, maxTexSize); + int totalPixels = AudioWaveTextureWidthPixel * texHeight; + + // 创建接收像素数据的 NativeArray + NativeArray pixels = new NativeArray(totalPixels, Allocator.Persistent); + + try + { + var drawJob = new DrawWaveformTextureJob + { + Samples = precomputedSamples, + TexWidth = AudioWaveTextureWidthPixel, + TexHeight = texHeight, + WaveColor = AudioWaveColor, + BgColor = ClearColor, + Pixels = pixels + }; + + await Task.Run(() => + { + drawJob.Schedule(totalPixels, 64).Complete(); + }, token); + + if (token.IsCancellationRequested) return null; + + if (currentTexture != null && (currentTexture.width != AudioWaveTextureWidthPixel || currentTexture.height != texHeight)) + { + UnityEngine.Object.Destroy(currentTexture); + currentTexture = null; + } + + if (currentTexture == null) + { + currentTexture = new Texture2D(AudioWaveTextureWidthPixel, texHeight, TextureFormat.RGBA32, false); + } + + currentTexture.SetPixelData(pixels, 0); + currentTexture.Apply(); + + return currentTexture; + } + finally + { + pixels.Dispose(); + } + } + + #region Burst Jobs + + [BurstCompile] + private struct DownsampleAudioJob : IJobParallelFor + { + [ReadOnly] public NativeArray FullSamples; + public int Channels; + public int Frequency; + public int ClipSamples; + public float MusicOffsetS; + public float TimelineTotalTimeS; + public int SamplesCount; + + [WriteOnly] public NativeArray Result; + + public void Execute(int i) + { + float t0 = (float)i / SamplesCount * TimelineTotalTimeS; + float t1 = (float)(i + 1) / SamplesCount * TimelineTotalTimeS; + + float localT0 = t0 - MusicOffsetS; + float localT1 = t1 - MusicOffsetS; + + int frameStart = math.clamp((int)(localT0 * Frequency), 0, ClipSamples); + int frameEnd = math.clamp((int)(localT1 * Frequency), 0, ClipSamples); + + float maxAmplitude = 0f; + if (frameStart < frameEnd) + { + for (int f = frameStart; f < frameEnd; f++) + { + int baseIndex = f * Channels; + for (int ch = 0; ch < Channels; ch++) + { + float amplitude = math.abs(FullSamples[baseIndex + ch]); + if (amplitude > maxAmplitude) + { + maxAmplitude = amplitude; + } + } + } + } + Result[i] = maxAmplitude; + } + } + + [BurstCompile] + private struct DrawWaveformTextureJob : IJobParallelFor + { + [ReadOnly] public NativeArray Samples; + public int TexWidth; + public int TexHeight; + public Color32 WaveColor; + public Color32 BgColor; + + [WriteOnly] public NativeArray Pixels; + + // index 代表当前的像素索引 (0 到 totalPixels-1) + public void Execute(int index) + { + // 将一维索引转为 2D 的 y(行) 和 x(列) + int y = index / TexWidth; + int x = index % TexWidth; + + // 按照当前所在的行 (y) 计算采样的振幅 + float t = TexHeight > 1 ? (float)y / (TexHeight - 1) : 0f; + int sampleIndex = math.clamp((int)math.round(t * (Samples.Length - 1)), 0, Samples.Length - 1); + float amplitude = Samples[sampleIndex]; + + // 判断当前像素 (x) 是否在振幅宽度范围内 + float centerX = (TexWidth - 1) / 2f; + float maxHalfWidth = TexWidth / 2f; + float halfWidth = amplitude * maxHalfWidth; + float dist = math.abs(x - centerX); + + Pixels[index] = (dist <= halfWidth) ? WaveColor : BgColor; + } + } + + #endregion + + } +} diff --git a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/AudioWaveformGenerator.cs.meta b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/AudioWaveformGenerator.cs.meta new file mode 100644 index 000000000..3e7694199 --- /dev/null +++ b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/AudioWaveformGenerator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 9d92b1bd62854003947cc69733250492 +timeCreated: 1783944383 \ No newline at end of file diff --git a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/Management/ChartEditorPlayerPrefsManager.cs b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/Management/ChartEditorPlayerPrefsManager.cs index df9e7d39c..38f767ea4 100644 --- a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/Management/ChartEditorPlayerPrefsManager.cs +++ b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/Management/ChartEditorPlayerPrefsManager.cs @@ -19,9 +19,10 @@ public class ChartEditorPlayerPrefsManager : MonoBehaviour private const string MusicVolumePrefName = "ChartEditor_MusicVolume"; private const string NoteVolumePrefName = "ChartEditor_NoteVolume"; - private const string IsCompactNoteButtonAreaPrefName = "ChartEditor_IsCompactNoteButtonArea"; private const string IsMultiBpmItemPrefName = "ChartEditor_IsMultiBpmItem"; private const string IsMultiMusicItemPrefName = "ChartEditor_IsMultiMusicItem"; + private const string IsCompactNoteButtonAreaPrefName = "ChartEditor_IsCompactNoteButtonArea"; + private const string IsShowingAudioWavePrefName = "ChartEditor_IsShowingAudioWave"; private readonly CompositeDisposable Disposables = new CompositeDisposable(); @@ -89,12 +90,14 @@ private void InitChartEditorSettingPlayerPrefs(ChartEditorModel model) model.MusicVolume.Value = PlayerPrefs.GetInt(MusicVolumePrefName); if (PlayerPrefs.HasKey(BeatAccuracyPrefName)) model.BeatAccuracy.Value = PlayerPrefs.GetInt(BeatAccuracyPrefName); - if (PlayerPrefs.HasKey(IsCompactNoteButtonAreaPrefName)) - model.IsCompactNoteButtonArea.Value = PlayerPrefs.GetInt(IsCompactNoteButtonAreaPrefName) == 1; if (PlayerPrefs.HasKey(IsMultiBpmItemPrefName)) model.IsMultiBpmItemMode.Value = PlayerPrefs.GetInt(IsMultiBpmItemPrefName) == 1; if (PlayerPrefs.HasKey(IsMultiMusicItemPrefName)) model.IsMultiMusicItemMode.Value = PlayerPrefs.GetInt(IsMultiMusicItemPrefName) == 1; + if (PlayerPrefs.HasKey(IsCompactNoteButtonAreaPrefName)) + model.IsCompactNoteButtonArea.Value = PlayerPrefs.GetInt(IsCompactNoteButtonAreaPrefName) == 1; + if (PlayerPrefs.HasKey(IsShowingAudioWavePrefName)) + model.IsShowingAudioWave.Value = PlayerPrefs.GetInt(IsShowingAudioWavePrefName) == 1; model.MusicVolume .Skip(1) @@ -112,27 +115,35 @@ private void InitChartEditorSettingPlayerPrefs(ChartEditorModel model) PlayerPrefs.Save(); }) .AddTo(Disposables); - model.IsCompactNoteButtonArea + model.IsMultiBpmItemMode .Skip(1) .Subscribe(val => { - PlayerPrefs.SetInt(IsCompactNoteButtonAreaPrefName, val ? 1 : 0); + PlayerPrefs.SetInt(IsMultiBpmItemPrefName, val ? 1 : 0); PlayerPrefs.Save(); }) .AddTo(Disposables); - model.IsMultiBpmItemMode + model.IsMultiMusicItemMode .Skip(1) .Subscribe(val => { - PlayerPrefs.SetInt(IsMultiBpmItemPrefName, val ? 1 : 0); + PlayerPrefs.SetInt(IsMultiMusicItemPrefName, val ? 1 : 0); PlayerPrefs.Save(); }) .AddTo(Disposables); - model.IsMultiMusicItemMode + model.IsCompactNoteButtonArea .Skip(1) .Subscribe(val => { - PlayerPrefs.SetInt(IsMultiMusicItemPrefName, val ? 1 : 0); + PlayerPrefs.SetInt(IsCompactNoteButtonAreaPrefName, val ? 1 : 0); + PlayerPrefs.Save(); + }) + .AddTo(Disposables); + model.IsShowingAudioWave + .Skip(1) + .Subscribe(val => + { + PlayerPrefs.SetInt(IsShowingAudioWavePrefName, val ? 1 : 0); PlayerPrefs.Save(); }) .AddTo(Disposables); diff --git a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/Model/ChartEditorModel.cs b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/Model/ChartEditorModel.cs index 4c9f4d466..bb6f74ac7 100644 --- a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/Model/ChartEditorModel.cs +++ b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/Model/ChartEditorModel.cs @@ -81,9 +81,10 @@ public class ChartEditorModel // 制谱器设置 public readonly ReactiveProperty MusicVolume = new ReactiveProperty(100); public readonly ReactiveProperty NoteVolume = new ReactiveProperty(100); - public readonly ReactiveProperty IsCompactNoteButtonArea = new ReactiveProperty(false); public readonly ReactiveProperty IsMultiBpmItemMode = new ReactiveProperty(false); public readonly ReactiveProperty IsMultiMusicItemMode = new ReactiveProperty(false); + public readonly ReactiveProperty IsCompactNoteButtonArea = new ReactiveProperty(false); + public readonly ReactiveProperty IsShowingAudioWave = new ReactiveProperty(false); /// diff --git a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/View/ChartEditorSettingView.cs b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/View/ChartEditorSettingView.cs index d2e05bdc1..492e4ee3d 100644 --- a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/View/ChartEditorSettingView.cs +++ b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/View/ChartEditorSettingView.cs @@ -21,15 +21,18 @@ public class ChartEditorSettingView : BasePopupView [SerializeField] private TMP_InputField noteVolumeField = null!; - [SerializeField] - private RadioButtonItem isCompactNoteButtonAreaButton = null!; - [SerializeField] private RadioButtonItem isMultiBpmItemButton = null!; [SerializeField] private RadioButtonItem isMultiMusicItemButton = null!; + [SerializeField] + private RadioButtonItem isCompactNoteButtonAreaButton = null!; + + [SerializeField] + private RadioButtonItem isShowingAudioWave = null!; + // AudioMixer 中的变量名 private const string MusicVolumeName = "MusicVolume"; @@ -80,19 +83,23 @@ public override void Bind(ChartEditorSettingViewModel targetViewModel) }) .AddTo(this); - isCompactNoteButtonAreaButton.IsChecked = ViewModel.IsCompactNoteButtonArea.CurrentValue; isMultiBpmItemButton.IsChecked = ViewModel.IsMultiBpmItemMode.CurrentValue; isMultiMusicItemButton.IsChecked = ViewModel.IsMultiMusicItemMode.CurrentValue; - isCompactNoteButtonAreaButton.OnValueChanged.AddListener(ViewModel.SetCompactNoteButtonArea); + isCompactNoteButtonAreaButton.IsChecked = ViewModel.IsCompactNoteButtonArea.CurrentValue; + isShowingAudioWave.IsChecked = ViewModel.IsShowingAudioWave.CurrentValue; + isMultiBpmItemButton.OnValueChanged.AddListener(ViewModel.SetMultiBpmItemMode); isMultiMusicItemButton.OnValueChanged.AddListener(ViewModel.SetMultiMusicItemMode); + isCompactNoteButtonAreaButton.OnValueChanged.AddListener(ViewModel.SetCompactNoteButtonArea); + isShowingAudioWave.OnValueChanged.AddListener(ViewModel.SetShowingAudioWave); } protected override void OnDestroy() { - isCompactNoteButtonAreaButton.OnValueChanged.RemoveListener(ViewModel.SetCompactNoteButtonArea); isMultiBpmItemButton.OnValueChanged.RemoveListener(ViewModel.SetMultiBpmItemMode); isMultiMusicItemButton.OnValueChanged.RemoveListener(ViewModel.SetMultiMusicItemMode); + isCompactNoteButtonAreaButton.OnValueChanged.RemoveListener(ViewModel.SetCompactNoteButtonArea); + isShowingAudioWave.OnValueChanged.RemoveListener(ViewModel.SetShowingAudioWave); base.OnDestroy(); } diff --git a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/View/EditAreaView.cs b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/View/EditAreaView.cs index 36ed3c9c6..1b3c61821 100644 --- a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/View/EditAreaView.cs +++ b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/View/EditAreaView.cs @@ -52,10 +52,18 @@ public class EditAreaView : BaseView, IPointerDownHandler [SerializeField] private RectTransform judgeLineRect = null!; + [SerializeField] + private RawImage audioWaveRawImage = null!; + + + private readonly AudioWaveformGenerator WaveformGenerator = new AudioWaveformGenerator(); + + private CancellationTokenSource? waveCts; private readonly CancellationTokenSource Cts = new CancellationTokenSource(); private static GameObjectPoolManager PoolManager => GameRoot.GameObjectPool; + // 管理当前激活的节拍线:Key=节拍索引(含细分拍),Value=节拍线物体实例 // 开始加载时会将 item 对应的 Value 设为 null 占位,加载完成后覆写为 gameObject private readonly Dictionary ActiveBeatLines = new Dictionary(); @@ -72,6 +80,10 @@ public override void Bind(EditAreaViewModel targetViewModel) { base.Bind(targetViewModel); + ViewModel.IsShowingAudioWave + .Subscribe(isShowing => audioWaveRawImage.enabled = isShowing) + .AddTo(this); + ViewModel.IsTimelinePlaying .Subscribe(isPlaying => scrollRect.vertical = !isPlaying) // 正在播放时完全禁止拖动/滚动 scrollRect .AddTo(this); @@ -125,6 +137,25 @@ public override void Bind(EditAreaViewModel targetViewModel) }) .AddTo(this); + Observable.CombineLatest( + ViewModel.AudioClipHandler, + ViewModel.FirstMusicVersionItemOffset, + ViewModel.TotalBeats, + (handler, offset, _) => (handler, offset: offset ?? 0) + ) + .ThrottleLastFrame(1) + .Subscribe(async t => + { + if (t.handler != null && t.handler.IsDoing) + await t.handler; + + await RequestDrawAudioWaveAsync(t.handler?.Asset, t.offset); + }) + .AddTo(this); + + ViewModel.BeatZoom + .Subscribe(_ => RefreshFramesAnchor()) + .AddTo(this); // 1. 位置线逻辑 ViewModel.PosLineCount.Subscribe(UpdatePosLines).AddTo(this); @@ -137,9 +168,9 @@ public override void Bind(EditAreaViewModel targetViewModel) (_, _, _) => true ) .ThrottleLastFrame(1) // 避免同一帧多次刷新 - .Subscribe(_ => ForceRebuildBeatLines()).AddTo(this); + .Subscribe(_ => RebuildBeatLines()).AddTo(this); - // 3. 滚动时刷新节拍线和音符,如果没在播放音乐则一并更新时间轴时间 + // 3. 滚动时刷新节拍线和音符可见性,如果没在播放音乐则一并更新时间轴时间 scrollRect.onValueChanged.AsObservable() .Subscribe(_ => { @@ -197,7 +228,7 @@ private async Task CreatePosLine() #region BeatLines - private void ForceRebuildBeatLines() + private void RebuildBeatLines() { foreach (var kvp in ActiveBeatLines) if (kvp.Value != null) @@ -213,7 +244,6 @@ private async void UpdateBeatLinesVisibility() // 计算 Content 底部为 0,向上增加 // Viewport 可视区域在 Content 中的 Y 轴范围: float viewportHeight = viewportRect.rect.height; - float contentHeight = contentRect.rect.height; // 当 verticalNormalizedPosition = 0 时,显示底部 (0 ~ viewportHeight) float scrollY = Mathf.Max(0, -contentRect.anchoredPosition.y); @@ -299,7 +329,6 @@ private async void UpdateNotesVisibility() return; float viewportHeight = viewportRect.rect.height; - float contentHeight = contentRect.rect.height; float scrollY = Mathf.Max(0, -contentRect.anchoredPosition.y); @@ -458,6 +487,51 @@ private async Task CreateNoteObject(BaseChartNoteData note) #endregion + #region AudioWave + + private async Task RequestDrawAudioWaveAsync(AudioClip? clip, int musicOffset) + { + RefreshFramesAnchor(); + + var rectTransform = (RectTransform)audioWaveRawImage.transform; + int uiHeight = Mathf.CeilToInt(rectTransform.rect.height); + + if (uiHeight <= 0) return; + + // 取消上一次未完成的绘制任务 + waveCts?.Cancel(); + waveCts?.Dispose(); + waveCts = new CancellationTokenSource(); + var token = waveCts.Token; + + try + { + // 预计算 + await WaveformGenerator.PrecomputeAsync(clip, musicOffset, token); + + if (token.IsCancellationRequested) + return; + + // 生成纹理 + Texture2D? waveTex = await WaveformGenerator.GenerateTextureAsync(uiHeight, token); + + if (token.IsCancellationRequested) + return; + + audioWaveRawImage.texture = waveTex != null ? waveTex : null; // 无音频处理 + } + catch (OperationCanceledException) + { + // 忽略取消异常 + } + catch (Exception ex) + { + Debug.LogError($"[AudioWaveform] 生成波形图报错: {ex}"); + } + } + + #endregion + #region Input public void OnPointerDown(PointerEventData eventData) @@ -501,6 +575,15 @@ out Beat beat #endregion + private void RefreshFramesAnchor() + { + // TODO: 目前仅供 AudioWave 使用,后续可考虑重构接入 BeatLinesFrame 和 NoteLinesFrame 以优化缩放时卡顿 + var rectTransform = (RectTransform)audioWaveRawImage.transform; + double judgeLineY = judgeLineRect.anchoredPosition.y; + rectTransform.anchorMin = new Vector2(0.25f, (float)(judgeLineY / contentRect.rect.height)); + rectTransform.anchorMax = new Vector2(0.75f, (contentRect.rect.height - viewportRect.rect.height + (float)judgeLineY) / contentRect.rect.height); + } + private void Update() { if (!Input.GetKeyDown(KeyCode.Space)) @@ -520,6 +603,8 @@ protected void OnDestroy() { Cts.Cancel(); Cts.Dispose(); + waveCts?.Cancel(); + waveCts?.Dispose(); // 清理节拍线 foreach (var kvp in ActiveBeatLines) @@ -538,7 +623,10 @@ protected void OnDestroy() } } + WaveformGenerator.Dispose(); + ActiveNotes.Clear(); } } + } diff --git a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/ViewModel/ChartEditorSettingViewModel.cs b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/ViewModel/ChartEditorSettingViewModel.cs index 48900e5d8..322f0dca3 100644 --- a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/ViewModel/ChartEditorSettingViewModel.cs +++ b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/ViewModel/ChartEditorSettingViewModel.cs @@ -9,9 +9,10 @@ public class ChartEditorSettingViewModel : BaseViewModel { public ReadOnlyReactiveProperty MusicVolume => Model.MusicVolume; public ReadOnlyReactiveProperty NoteVolume => Model.NoteVolume; - public ReadOnlyReactiveProperty IsCompactNoteButtonArea => Model.IsCompactNoteButtonArea; public ReadOnlyReactiveProperty IsMultiBpmItemMode => Model.IsMultiBpmItemMode; public ReadOnlyReactiveProperty IsMultiMusicItemMode => Model.IsMultiMusicItemMode; + public ReadOnlyReactiveProperty IsCompactNoteButtonArea => Model.IsCompactNoteButtonArea; + public ReadOnlyReactiveProperty IsShowingAudioWave => Model.IsShowingAudioWave; public ChartEditorSettingViewModel(ChartEditorModel model) : base(model) { @@ -19,8 +20,9 @@ public ChartEditorSettingViewModel(ChartEditorModel model) : base(model) public void SetMusicVolume(int value) => Model.MusicVolume.Value = value; public void SetNoteVolume(int value) => Model.NoteVolume.Value = value; - public void SetCompactNoteButtonArea(bool value) => Model.IsCompactNoteButtonArea.Value = value; public void SetMultiBpmItemMode(bool value) => Model.IsMultiBpmItemMode.Value = value; public void SetMultiMusicItemMode(bool value) => Model.IsMultiMusicItemMode.Value = value; + public void SetCompactNoteButtonArea(bool value) => Model.IsCompactNoteButtonArea.Value = value; + public void SetShowingAudioWave(bool value) => Model.IsShowingAudioWave.Value = value; } } diff --git a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/ViewModel/EditAreaViewModel.cs b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/ViewModel/EditAreaViewModel.cs index ce26e08a1..1d1c19080 100644 --- a/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/ViewModel/EditAreaViewModel.cs +++ b/Cyan-Stars/Assets/Scripts/Gameplay/ChartEditor/ViewModel/EditAreaViewModel.cs @@ -5,11 +5,13 @@ using System; using System.Collections.Generic; using System.Diagnostics.Contracts; +using CatAsset.Runtime; using CyanStars.Chart; using CyanStars.Gameplay.ChartEditor.Command; using CyanStars.Gameplay.ChartEditor.Model; using ObservableCollections; using R3; +using UnityEngine; namespace CyanStars.Gameplay.ChartEditor.ViewModel { @@ -37,10 +39,14 @@ public class EditAreaViewModel : BaseViewModel public ReadOnlyReactiveProperty PosMagnetState => Model.PosMagnet; public ReadOnlyReactiveProperty PosAccuracy => Model.PosAccuracy; public ReadOnlyReactiveProperty IsCompactNoteButtonArea => Model.IsCompactNoteButtonArea; + public ReadOnlyReactiveProperty?> AudioClipHandler => Model.AudioClipHandler; + public ReadOnlyReactiveProperty IsShowingAudioWave => Model.IsShowingAudioWave; public readonly ReadOnlyReactiveProperty CanPutNote; + public readonly ReadOnlyReactiveProperty FirstMusicVersionItemOffset; + public EditAreaViewModel(ChartEditorModel model) : base(model) @@ -123,7 +129,7 @@ public EditAreaViewModel(ChartEditorModel model) .ToReadOnlyReactiveProperty() .AddTo(base.Disposables); - ReadOnlyReactiveProperty firstMusicVersionItemOffset = + FirstMusicVersionItemOffset = Model.ChartPackData.CurrentValue.MusicVersions .ObserveChanged() .Prepend((CollectionChangedEvent)default) @@ -150,7 +156,7 @@ public EditAreaViewModel(ChartEditorModel model) ) .Prepend(Unit.Default) .CombineLatest( - firstMusicVersionItemOffset, + FirstMusicVersionItemOffset, Model.AudioClipHandler, (_, offset, handler) => {