diff --git a/Assets/PerfectWorld/Asssets/Icon/icon_checked.png b/Assets/PerfectWorld/Asssets/Icon/icon_checked.png new file mode 100644 index 0000000000..2381ef5dd1 Binary files /dev/null and b/Assets/PerfectWorld/Asssets/Icon/icon_checked.png differ diff --git a/Assets/PerfectWorld/Asssets/Icon/icon_checked.png.meta b/Assets/PerfectWorld/Asssets/Icon/icon_checked.png.meta new file mode 100644 index 0000000000..24f56007b2 --- /dev/null +++ b/Assets/PerfectWorld/Asssets/Icon/icon_checked.png.meta @@ -0,0 +1,153 @@ +fileFormatVersion: 2 +guid: 7fe023a7136a94d4393d0a3a4901efdb +TextureImporter: + internalIDToNameTable: [] + 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: 0 + 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: 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: 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 + spriteSheet: + serializedVersion: 2 + sprites: + - serializedVersion: 2 + name: icon_checked_0 + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 22 + height: 16 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + customData: + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 022fbaeaf7465384ba66ec58aa317a41 + internalID: -1390858318 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 1f5988c15a6a16c488898c9526378f0a + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: + icon_checked_0: -1390858318 + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/PerfectWorld/Prefab/UI/DlgSetting.prefab b/Assets/PerfectWorld/Prefab/UI/DlgSetting.prefab index fc6c3230cc..c70f82f4fc 100644 Binary files a/Assets/PerfectWorld/Prefab/UI/DlgSetting.prefab and b/Assets/PerfectWorld/Prefab/UI/DlgSetting.prefab differ diff --git a/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting.meta b/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting.meta new file mode 100644 index 0000000000..c2da35be60 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4b6e00c0a650e9446b61783946078df6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting/DlgSetting.cs b/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting/DlgSetting.cs new file mode 100644 index 0000000000..055e0d062b --- /dev/null +++ b/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting/DlgSetting.cs @@ -0,0 +1,107 @@ +using BrewMonster.UI; +using System.Collections; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +namespace BrewMonster +{ + public class DlgSetting : AUIDialog + { + [Header("Box Button")] + [SerializeField] private Button btn_system; + [SerializeField] private Button btn_interface; + [SerializeField] private Button btn_setting; + [SerializeField] private Button btn_sound; + [SerializeField] private Button btn_default; + [SerializeField] private Button btn_confirm; + [SerializeField] private Button btn_close; + + [Header("Content")] + [SerializeField] private GameObject content_interface; + [SerializeField] private GameObject content_sound; + + [Header("Sprite")] + [SerializeField] private Sprite tab_active; + [SerializeField] private Sprite tab_unactive; + + [Header("Tab Text Color")] + [SerializeField] private Color activeTextColor = Color.white; + [SerializeField] private Color inactiveTextColor = Color.white; + + private Button[] tabButtons; + + public override void Awake() + { + tabButtons = new[] + { + btn_system, + btn_interface, + btn_setting, + btn_sound + }; + } + + public override void OnEnable() + { + btn_system.onClick.AddListener(OnBtnSystem); + btn_interface.onClick.AddListener(OnBtnInterface); + btn_setting.onClick.AddListener(OnBtnSetting); + btn_sound.onClick.AddListener(OnBtnSound); + + } + + public override void OnDisable() + { + btn_system.onClick.RemoveListener(OnBtnSystem); + btn_interface.onClick.RemoveListener(OnBtnInterface); + btn_setting.onClick.RemoveListener(OnBtnSetting); + btn_sound.onClick.RemoveListener(OnBtnSound); + } + + private void OnBtnSystem() + { + SetActiveTab(btn_system); + } + + private void OnBtnInterface() + { + SetActiveTab(btn_interface); + content_interface.SetActive(true); + content_sound.SetActive(false); + } + + private void OnBtnSetting() + { + SetActiveTab(btn_setting); + } + + private void OnBtnSound() + { + SetActiveTab(btn_sound); + content_interface.SetActive(false); + content_sound.SetActive(true); + } + + private void SetActiveTab(Button activeButton) + { + foreach(Button button in tabButtons) + { + if (button == null) + continue; + + Image image = button.GetComponent(); + if(image != null) + { + image.sprite = button == activeButton ? tab_active : tab_unactive; + } + + TMP_Text text = button.GetComponentInChildren(); + if(text != null) + { + text.color = button == activeButton ? activeTextColor : inactiveTextColor; + } + } + } + } +} diff --git a/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting/DlgSetting.cs.meta b/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting/DlgSetting.cs.meta new file mode 100644 index 0000000000..8d2f72126b --- /dev/null +++ b/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting/DlgSetting.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5595fd2d80a58034bb63e5c36da3bd4a \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting/SettingSound.cs b/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting/SettingSound.cs new file mode 100644 index 0000000000..5b44af94f9 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting/SettingSound.cs @@ -0,0 +1,173 @@ +using BrewMonster.Assets.PerfectWorld.Scripts.UI; +using BrewMonster.Common; +using BrewMonster.Managers; +using BrewMonster.Scripts; +using BrewMonster.Scripts.Managers; +using BrewMonster.UI; +using CSNetwork.GPDataType; +using Cysharp.Threading.Tasks.Triggers; +using PerfectWorld.Scripts.Managers; +using System; +using System.Collections; +using System.Collections.Generic; +using TMPro; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; + +namespace BrewMonster +{ + public class SettingSound : MonoBehaviour + { + [Header("Sound Settings")] + [SerializeField] private Toggle tog_bgm; + [SerializeField] private Toggle tog_sfx; + [SerializeField] private Toggle tog_master; + [SerializeField] private RectTransform handle_bmg; + [SerializeField] private RectTransform handle_sfx; + [SerializeField] private RectTransform handle_master; + [SerializeField] private TextMeshProUGUI txt_bgm; + [SerializeField] private TextMeshProUGUI txt_sfx; + [SerializeField] private TextMeshProUGUI txt_master; + + [Header("Sprite")] + [SerializeField] private Sprite switch_off; + [SerializeField] private Sprite switch_on; + + [Header("Switch Config")] + private float slideDuration = 0.15f; + private float handleOffPositionX = -88.3f; + private float handleOnPositionX = -27.8f; + private float textOnPositionX = -27.8f; + private float textOffPositionX = 30f; + private Color textOnColor = new Color(0.96f, 0.84f, 0.61f); + private Color textOffColor = new Color(0.6f, 0.6f, 0.6f); + + private Coroutine bgmCoroutine; + private Coroutine sfxCoroutine; + private Coroutine masterCoroutine; + + private void OnEnable() + { + UpdateSwitchInstant(tog_bgm, handle_bmg, txt_bgm); + UpdateSwitchInstant(tog_sfx, handle_sfx, txt_sfx); + UpdateSwitchInstant(tog_master, handle_master, txt_master); + + tog_bgm.onValueChanged.AddListener(OnBgmChanged); + tog_sfx.onValueChanged.AddListener(OnSfxChanged); + tog_master.onValueChanged.AddListener(OnMasterChanged); + } + + private void OnDisable() + { + tog_bgm.onValueChanged.RemoveListener(OnBgmChanged); + tog_sfx.onValueChanged.RemoveListener(OnSfxChanged); + tog_master.onValueChanged.RemoveListener(OnMasterChanged); + } + + private void OnBgmChanged(bool isOn) + { + if (bgmCoroutine != null) + { + StopCoroutine(bgmCoroutine); + } + bgmCoroutine = StartCoroutine(SlideSwitchCoroutine(tog_bgm, handle_bmg, txt_bgm)); + // TODO: Add logic to change BGM volume or mute state + } + + private void OnSfxChanged(bool isOn) + { + if (sfxCoroutine != null) + { + StopCoroutine(sfxCoroutine); + } + sfxCoroutine = StartCoroutine(SlideSwitchCoroutine(tog_sfx, handle_sfx, txt_sfx)); + // TODO: Add logic to change SFX volume or mute state + } + + private void OnMasterChanged(bool isOn) + { + if (masterCoroutine != null) + { + StopCoroutine(masterCoroutine); + } + masterCoroutine = StartCoroutine(SlideSwitchCoroutine(tog_master, handle_master, txt_master)); + // TODO: Add logic to change Master volume or mute state + } + + private void UpdateSwitchInstant(Toggle toggle, RectTransform handle, TextMeshProUGUI statusText) + { + bool isOn = toggle.isOn; + // Logic circle switch + float handleTargetX = isOn ? handleOnPositionX : handleOffPositionX; + handle.anchoredPosition = new Vector2(handleTargetX, handle.anchoredPosition.y); + + // Logic text switch + if (statusText != null) + { + float textTargetX = isOn ? textOnPositionX : textOffPositionX; + statusText.rectTransform.anchoredPosition = new Vector2(textTargetX, statusText.rectTransform.anchoredPosition.y); + statusText.text = isOn ? "Mở" : "Tắt"; + statusText.color = isOn ? textOnColor : textOffColor; + } + + // Logic background switch + if (handle.TryGetComponent(out var handleImage)) + { + handleImage.sprite = isOn ? switch_on : switch_off; + } + } + + private IEnumerator SlideSwitchCoroutine(Toggle toggle, RectTransform handle, TextMeshProUGUI statusText) + { + bool isOn = toggle.isOn; + + // Get info target + float handleTargetX = isOn ? handleOnPositionX : handleOffPositionX; + float handleStartX = handle.anchoredPosition.x; + + float textTargetX = isOn ? textOnPositionX : textOffPositionX; + float textStartX = statusText != null ? statusText.rectTransform.anchoredPosition.x : 0f; + + // Update text and background immediately + if (statusText != null) + { + statusText.text = isOn ? "Mở" : "Tắt"; + statusText.color = isOn ? textOnColor : textOffColor; + } + + if (handle.TryGetComponent(out var handleImage)) + { + handleImage.sprite = isOn ? switch_on : switch_off; + } + + float time = 0f; + while (time < slideDuration) + { + time += Time.deltaTime; + float t = Mathf.Clamp01(time / slideDuration); + float smoothT = Mathf.SmoothStep(0f, 1f, t); + + // Move handle + float currentHandleX = Mathf.Lerp(handleStartX, handleTargetX, smoothT); + handle.anchoredPosition = new Vector2(currentHandleX, handle.anchoredPosition.y); + + // Move text + if (statusText != null) + { + float currentTextX = Mathf.Lerp(textStartX, textTargetX, smoothT); + statusText.rectTransform.anchoredPosition = new Vector2(currentTextX, statusText.rectTransform.anchoredPosition.y); + } + + yield return null; + } + + // Position it correctly in the last frame to avoid errors. + handle.anchoredPosition = new Vector2(handleTargetX, handle.anchoredPosition.y); + if (statusText != null) + { + statusText.rectTransform.anchoredPosition = new Vector2(textTargetX, statusText.rectTransform.anchoredPosition.y); + } + } + } +} diff --git a/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting/SettingSound.cs.meta b/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting/SettingSound.cs.meta new file mode 100644 index 0000000000..8afda748d6 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/UI/Dialogs/Setting/SettingSound.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 405c79bf7a84c8d499a6733998a87b79 \ No newline at end of file