Added new settings in settings system
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
- Добавил больше настроек в систему настроек - Пока у большинства настроек нет функционала - Немного изменил внешний вид настроек
This commit is contained in:
parent
4d05d1adbb
commit
24aaf18d4b
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -138,7 +138,7 @@ MonoBehaviour:
|
||||
m_MinWidth: -1
|
||||
m_MinHeight: -1
|
||||
m_PreferredWidth: 600
|
||||
m_PreferredHeight: 50
|
||||
m_PreferredHeight: 90
|
||||
m_FlexibleWidth: -1
|
||||
m_FlexibleHeight: -1
|
||||
m_LayoutPriority: 1
|
||||
@ -177,7 +177,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 300, y: -50}
|
||||
m_AnchoredPosition: {x: 300, y: -90}
|
||||
m_SizeDelta: {x: 600, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &8196548391682863322
|
||||
@ -277,7 +277,7 @@ RectTransform:
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 600, y: 50}
|
||||
m_SizeDelta: {x: 600, y: 90}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &7434999243356666657
|
||||
MonoBehaviour:
|
||||
@ -389,8 +389,8 @@ MonoBehaviour:
|
||||
m_Calls: []
|
||||
m_text: "\u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A"
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_fontAsset: {fileID: 11400000, guid: 5302535af1044152a457ed104f1f4b91, type: 2}
|
||||
m_sharedMaterial: {fileID: 2164040, guid: 5302535af1044152a457ed104f1f4b91, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
@ -414,12 +414,12 @@ MonoBehaviour:
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 24
|
||||
m_fontSize: 48
|
||||
m_fontSizeBase: 24
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_enableAutoSizing: 1
|
||||
m_fontSizeMin: 24
|
||||
m_fontSizeMax: 48
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
|
||||
@ -37,7 +37,7 @@ RectTransform:
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 200, y: 50}
|
||||
m_SizeDelta: {x: 400, y: 70}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &6418208233271057322
|
||||
CanvasRenderer:
|
||||
@ -62,7 +62,7 @@ MonoBehaviour:
|
||||
m_IgnoreLayout: 0
|
||||
m_MinWidth: -1
|
||||
m_MinHeight: -1
|
||||
m_PreferredWidth: 200
|
||||
m_PreferredWidth: 400
|
||||
m_PreferredHeight: 70
|
||||
m_FlexibleWidth: -1
|
||||
m_FlexibleHeight: -1
|
||||
@ -182,12 +182,12 @@ MonoBehaviour:
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 36.35
|
||||
m_fontSize: 48
|
||||
m_fontSizeBase: 48
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 1
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontSizeMax: 48
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 2
|
||||
m_VerticalAlignment: 512
|
||||
|
||||
@ -7346,7 +7346,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.132, y: 0.5}
|
||||
m_AnchorMax: {x: 0.846, y: 0.77500004}
|
||||
m_AnchoredPosition: {x: -54.500015, y: 5}
|
||||
m_AnchoredPosition: {x: -54.5, y: 5}
|
||||
m_SizeDelta: {x: -107, y: -10}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &1474919456
|
||||
@ -7717,18 +7717,6 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 98f414c07d2f47e794d25468e8519ba7, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::RR.Common.UI.SettingsUIList
|
||||
settingsList: []
|
||||
musicVolumeSlider: {fileID: 0}
|
||||
sfxVolumeSlider: {fileID: 0}
|
||||
freeGameToggle: {fileID: 0}
|
||||
givingPrizesToggle: {fileID: 0}
|
||||
startLivesSlider: {fileID: 0}
|
||||
increasedLivesSlider: {fileID: 0}
|
||||
statsButton: {fileID: 0}
|
||||
volumePercentageText: {fileID: 0}
|
||||
sfxVolumePercentageText: {fileID: 0}
|
||||
startLivesCountText: {fileID: 0}
|
||||
increasedLivesCountText: {fileID: 0}
|
||||
--- !u!114 &1537614491
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -9291,7 +9279,8 @@ MonoBehaviour:
|
||||
groupPanelPrefab: {fileID: 2186865876444500735, guid: 1983dbab136fb73419f146d56772a8c8, type: 3}
|
||||
defaultGroupsExpanded: 1
|
||||
rememberGroupFoldout: 1
|
||||
groupOrder: []
|
||||
groupOrder:
|
||||
- "\u041C\u0443\u0437\u044B\u043A\u0430 \u0438 \u0437\u0432\u0443\u043A\u0438"
|
||||
sortByNameInsideGroup: 1
|
||||
toggleRowPrefab: {fileID: -3497382869404314779, guid: 3f18baed1f4d89f4ab9b4caf0c789a38, type: 3}
|
||||
sliderRowPrefab: {fileID: 5445087308684328405, guid: a85153c0090994b438ad050a1dbcc306, type: 3}
|
||||
@ -9443,7 +9432,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0.00077443453}
|
||||
m_AnchoredPosition: {x: 0, y: -0.000034523957}
|
||||
m_SizeDelta: {x: 0, y: 300}
|
||||
m_Pivot: {x: 0, y: 1}
|
||||
--- !u!114 &1792218764
|
||||
@ -10209,7 +10198,7 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.132, y: 0.21750003}
|
||||
m_AnchorMax: {x: 0.846, y: 0.5}
|
||||
m_AnchoredPosition: {x: -54.500015, y: -79.00003}
|
||||
m_AnchoredPosition: {x: -54.5, y: -79.00003}
|
||||
m_SizeDelta: {x: -107, y: -63}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &1959311160
|
||||
|
||||
@ -5,6 +5,9 @@ using RR.Common.Settings;
|
||||
|
||||
namespace RR.Common.InspectorOverrides
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom property drawer for SettingEntry - v1.2
|
||||
/// </summary>
|
||||
[CustomPropertyDrawer(typeof(SettingEntry))]
|
||||
public class SettingEntryDrawer : PropertyDrawer
|
||||
{
|
||||
@ -24,6 +27,8 @@ namespace RR.Common.InspectorOverrides
|
||||
var nameProp = property.FindPropertyRelative("displayName");
|
||||
var descProp = property.FindPropertyRelative("description");
|
||||
var groupProp = property.FindPropertyRelative("group");
|
||||
var shownInSettingsProp = property.FindPropertyRelative("shownInSettings");
|
||||
var exposedProp = property.FindPropertyRelative("exposed");
|
||||
var typeProp = property.FindPropertyRelative("valueType");
|
||||
|
||||
var defBoolProp = property.FindPropertyRelative("defaultBool");
|
||||
@ -33,14 +38,14 @@ namespace RR.Common.InspectorOverrides
|
||||
|
||||
var minIntProp = property.FindPropertyRelative("minInt");
|
||||
var maxIntProp = property.FindPropertyRelative("maxInt");
|
||||
var intDisplayFormatProp = property.FindPropertyRelative("intDisplayFormat");
|
||||
var intStepProp = property.FindPropertyRelative("intStep");
|
||||
var minFloatProp = property.FindPropertyRelative("minFloat");
|
||||
var maxFloatProp = property.FindPropertyRelative("maxFloat");
|
||||
var displayAsPercentageProp = property.FindPropertyRelative("displayAsPercentage");
|
||||
|
||||
var applyProp = property.FindPropertyRelative("applyTarget");
|
||||
var mixerProp = property.FindPropertyRelative("mixer");
|
||||
var mixerParamProp = property.FindPropertyRelative("mixerParameter");
|
||||
var minDbProp = property.FindPropertyRelative("minDb");
|
||||
var maxDbProp = property.FindPropertyRelative("maxDb");
|
||||
var audioTargetProp = property.FindPropertyRelative("audioTargetType");
|
||||
|
||||
float line = EditorGUIUtility.singleLineHeight;
|
||||
float space = EditorGUIUtility.standardVerticalSpacing;
|
||||
@ -69,6 +74,9 @@ namespace RR.Common.InspectorOverrides
|
||||
DrawProp(ref r, keyProp, "Key");
|
||||
DrawProp(ref r, groupProp, "Group");
|
||||
DrawProp(ref r, descProp, "Description", includeChildren: true);
|
||||
|
||||
DrawSectionTitle(ref r, "Visibility & Access");
|
||||
DrawFlagsRow(ref r, shownInSettingsProp, exposedProp, "Shown in UI", "Exposed");
|
||||
|
||||
DrawSectionTitle(ref r, "Value");
|
||||
DrawProp(ref r, typeProp, "Value Type");
|
||||
@ -84,11 +92,20 @@ namespace RR.Common.InspectorOverrides
|
||||
case SettingValueType.Int:
|
||||
DrawProp(ref r, defIntProp, "Default");
|
||||
DrawMinMaxRow(ref r, minIntProp, maxIntProp, "Min", "Max");
|
||||
DrawProp(ref r, intDisplayFormatProp, "Display Format");
|
||||
|
||||
// Показываем intStep только если выбран ValueSelector
|
||||
var displayFormat = (IntDisplayFormat)intDisplayFormatProp.enumValueIndex;
|
||||
if (displayFormat == IntDisplayFormat.ValueSelector)
|
||||
{
|
||||
DrawProp(ref r, intStepProp, "Step");
|
||||
}
|
||||
break;
|
||||
|
||||
case SettingValueType.Float:
|
||||
DrawProp(ref r, defFloatProp, "Default");
|
||||
DrawMinMaxRow(ref r, minFloatProp, maxFloatProp, "Min", "Max");
|
||||
DrawProp(ref r, displayAsPercentageProp, "Display as %");
|
||||
break;
|
||||
|
||||
case SettingValueType.String:
|
||||
@ -122,11 +139,9 @@ namespace RR.Common.InspectorOverrides
|
||||
DrawProp(ref r, applyProp, "Apply Target");
|
||||
|
||||
var apply = (ApplyTarget)applyProp.enumValueIndex;
|
||||
if (apply == ApplyTarget.AudioMixerFloat01ToDb)
|
||||
if (apply == ApplyTarget.Audio)
|
||||
{
|
||||
DrawProp(ref r, mixerProp, "Audio Mixer");
|
||||
DrawProp(ref r, mixerParamProp, "Exposed Param");
|
||||
DrawMinMaxRow(ref r, minDbProp, maxDbProp, "Min dB", "Max dB");
|
||||
DrawProp(ref r, audioTargetProp, "Audio Type");
|
||||
}
|
||||
|
||||
// Warning
|
||||
@ -172,6 +187,10 @@ namespace RR.Common.InspectorOverrides
|
||||
h += HeightOf(keyProp) + space;
|
||||
h += HeightOf(groupProp) + space;
|
||||
h += HeightOf(descProp, true) + space;
|
||||
|
||||
// Visibility & Access section title
|
||||
h += line + space;
|
||||
h += line + space; // flags row (shownInSettings + exposed)
|
||||
|
||||
// Value section title
|
||||
h += line + space;
|
||||
@ -188,9 +207,26 @@ namespace RR.Common.InspectorOverrides
|
||||
break;
|
||||
|
||||
case SettingValueType.Int:
|
||||
h += line + space; // Default
|
||||
h += line + space; // range row
|
||||
h += line + space; // intDisplayFormat
|
||||
|
||||
// Добавляем высоту для intStep если выбран ValueSelector
|
||||
var intDisplayFormatProp = property.FindPropertyRelative("intDisplayFormat");
|
||||
if (intDisplayFormatProp != null)
|
||||
{
|
||||
var displayFormat = (IntDisplayFormat)intDisplayFormatProp.enumValueIndex;
|
||||
if (displayFormat == IntDisplayFormat.ValueSelector)
|
||||
{
|
||||
h += line + space; // intStep
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SettingValueType.Float:
|
||||
h += line + space; // Default
|
||||
h += line + space; // range row
|
||||
h += line + space; // displayAsPercentage checkbox
|
||||
break;
|
||||
|
||||
case SettingValueType.Button:
|
||||
@ -214,11 +250,9 @@ namespace RR.Common.InspectorOverrides
|
||||
h += HeightOf(applyProp) + space;
|
||||
|
||||
ApplyTarget apply = (ApplyTarget)applyProp.enumValueIndex;
|
||||
if (apply == ApplyTarget.AudioMixerFloat01ToDb)
|
||||
if (apply == ApplyTarget.Audio)
|
||||
{
|
||||
h += line + space; // mixer
|
||||
h += line + space; // param
|
||||
h += line + space; // db row
|
||||
h += line + space; // audioTargetType
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(keyProp.stringValue))
|
||||
@ -267,6 +301,28 @@ namespace RR.Common.InspectorOverrides
|
||||
|
||||
r.y += line + space;
|
||||
}
|
||||
|
||||
private static void DrawFlagsRow(ref Rect r, SerializedProperty leftProp, SerializedProperty rightProp, string leftLabel, string rightLabel)
|
||||
{
|
||||
float line = EditorGUIUtility.singleLineHeight;
|
||||
float space = EditorGUIUtility.standardVerticalSpacing;
|
||||
|
||||
float gap = 10f;
|
||||
float half = (r.width - gap) * 0.5f;
|
||||
|
||||
Rect left = new(r.x, r.y, half, line);
|
||||
Rect right = new(r.x + half + gap, r.y, half, line);
|
||||
|
||||
// Shown in Settings
|
||||
GUIContent leftContent = new GUIContent(leftLabel, "Показывать настройку в UI меню настроек");
|
||||
EditorGUI.PropertyField(left, leftProp, leftContent);
|
||||
|
||||
// Exposed
|
||||
GUIContent rightContent = new GUIContent(rightLabel, "Доступна для изменения извне (через API/файл)");
|
||||
EditorGUI.PropertyField(right, rightProp, rightContent);
|
||||
|
||||
r.y += line + space;
|
||||
}
|
||||
|
||||
private static string BuildHeader(string displayName, string key)
|
||||
{
|
||||
|
||||
@ -12,99 +12,30 @@ namespace RR.Common.Settings
|
||||
case ApplyTarget.None:
|
||||
return;
|
||||
|
||||
case ApplyTarget.AudioMixerFloat01ToDb:
|
||||
ApplyAudioMixer(def, v);
|
||||
return;
|
||||
|
||||
case ApplyTarget.QualityLevel:
|
||||
ApplyQuality(v.i);
|
||||
return;
|
||||
|
||||
case ApplyTarget.VSync:
|
||||
ApplyVSync(v.b);
|
||||
return;
|
||||
|
||||
case ApplyTarget.TargetFps:
|
||||
ApplyTargetFps(v.i);
|
||||
return;
|
||||
|
||||
case ApplyTarget.Fullscreen:
|
||||
ApplyFullscreen(v.b);
|
||||
return;
|
||||
|
||||
case ApplyTarget.FullscreenMode:
|
||||
ApplyFullscreenMode(v.i);
|
||||
return;
|
||||
|
||||
case ApplyTarget.ResolutionIndex:
|
||||
ApplyResolutionIndex(v.i);
|
||||
case ApplyTarget.Audio:
|
||||
ApplyAudio(def, v);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyAudioMixer(SettingEntry def, SettingValue v)
|
||||
private static void ApplyAudio(SettingEntry def, SettingValue v)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(def.mixerParameter)) return;
|
||||
|
||||
float volume = Mathf.Clamp01(v.f);
|
||||
|
||||
// Применяем через AudioManager
|
||||
if (GameManager.Instance?.Audio != null)
|
||||
{
|
||||
// Определяем тип звука по имени параметра
|
||||
string param = def.mixerParameter.ToLower();
|
||||
if (param.Contains("music"))
|
||||
switch (def.audioTargetType)
|
||||
{
|
||||
GameManager.Instance.Audio.SetMusicVolume(volume);
|
||||
}
|
||||
else if (param.Contains("sfx") || param.Contains("sound") || param.Contains("effect"))
|
||||
{
|
||||
GameManager.Instance.Audio.SetSfxVolume(volume);
|
||||
case AudioTargetType.Music:
|
||||
GameManager.Instance.Audio.SetMusicVolume(volume);
|
||||
break;
|
||||
|
||||
case AudioTargetType.Sfx:
|
||||
GameManager.Instance.Audio.SetSfxVolume(volume);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ApplyQuality(int level)
|
||||
{
|
||||
var names = QualitySettings.names;
|
||||
if (names == null || names.Length == 0) return;
|
||||
|
||||
level = Mathf.Clamp(level, 0, names.Length - 1);
|
||||
QualitySettings.SetQualityLevel(level, true);
|
||||
}
|
||||
|
||||
private static void ApplyVSync(bool enabled)
|
||||
{
|
||||
QualitySettings.vSyncCount = enabled ? 1 : 0;
|
||||
}
|
||||
|
||||
private static void ApplyTargetFps(int fps)
|
||||
{
|
||||
Application.targetFrameRate = fps > 0 ? fps : -1;
|
||||
}
|
||||
|
||||
private static void ApplyFullscreen(bool fullscreen)
|
||||
{
|
||||
Screen.fullScreen = fullscreen;
|
||||
}
|
||||
|
||||
private static void ApplyFullscreenMode(int idx)
|
||||
{
|
||||
// FullScreenMode: 0..3 (ExclusiveFullScreen, FullScreenWindow, MaximizedWindow, Windowed)
|
||||
idx = Mathf.Clamp(idx, 0, 3);
|
||||
Screen.fullScreenMode = (FullScreenMode)idx;
|
||||
}
|
||||
|
||||
private static void ApplyResolutionIndex(int index)
|
||||
{
|
||||
var rs = Screen.resolutions;
|
||||
if (rs == null || rs.Length == 0) return;
|
||||
|
||||
index = Mathf.Clamp(index, 0, rs.Length - 1);
|
||||
var r = rs[index];
|
||||
|
||||
// без герцовки — самый совместимый вариант
|
||||
Screen.SetResolution(r.width, r.height, Screen.fullScreenMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Audio;
|
||||
|
||||
namespace RR.Common.Settings
|
||||
{
|
||||
@ -15,21 +14,22 @@ namespace RR.Common.Settings
|
||||
OptionPicker // Выбор из списка опций (enum-like)
|
||||
}
|
||||
|
||||
// "Куда применять" — расширяется редко (не под каждую настройку)
|
||||
public enum ApplyTarget
|
||||
{
|
||||
None,
|
||||
|
||||
// Audio
|
||||
AudioMixerFloat01ToDb, // float 0..1 -> dB и в AudioMixer parameter
|
||||
|
||||
// Graphics / Performance
|
||||
QualityLevel, // int -> QualitySettings.SetQualityLevel
|
||||
VSync, // bool -> QualitySettings.vSyncCount
|
||||
TargetFps, // int -> Application.targetFrameRate
|
||||
Fullscreen, // bool -> Screen.fullScreen
|
||||
FullscreenMode, // int 0..3 -> Screen.fullScreenMode
|
||||
ResolutionIndex // int -> индекс в Screen.resolutions
|
||||
Audio // Применить к звуку через AudioManager (музыка или эффекты)
|
||||
}
|
||||
|
||||
public enum AudioTargetType
|
||||
{
|
||||
Music, // Музыка
|
||||
Sfx // Звуковые эффекты
|
||||
}
|
||||
|
||||
public enum IntDisplayFormat
|
||||
{
|
||||
Slider, // Обычный слайдер
|
||||
ValueSelector // Выбор значения (со стрелками или дропдауном)
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@ -55,6 +55,12 @@ namespace RR.Common.Settings
|
||||
[TextArea] public string description;
|
||||
public string group = "General";
|
||||
|
||||
[Tooltip("Показывать ли настройку в UI меню настроек")]
|
||||
public bool shownInSettings = true;
|
||||
|
||||
[Tooltip("Доступна ли настройка для изменения извне (через API/файл)")]
|
||||
public bool exposed = false;
|
||||
|
||||
public SettingValueType valueType;
|
||||
|
||||
// Defaults
|
||||
@ -66,19 +72,26 @@ namespace RR.Common.Settings
|
||||
// Ranges (used for Int/Float)
|
||||
public int minInt = 0;
|
||||
public int maxInt = 10;
|
||||
|
||||
[Tooltip("Формат отображения для Int (слайдер или выбор значения)")]
|
||||
public IntDisplayFormat intDisplayFormat = IntDisplayFormat.Slider;
|
||||
|
||||
[Tooltip("Шаг для выбора значения Int (используется только для ValueSelector)")]
|
||||
public int intStep = 1;
|
||||
|
||||
public float minFloat = 0f;
|
||||
public float maxFloat = 1f;
|
||||
|
||||
[Tooltip("Отображать float значение как проценты (0-100%)")]
|
||||
public bool displayAsPercentage = false;
|
||||
|
||||
public ApplyTarget applyTarget = ApplyTarget.None;
|
||||
|
||||
// AudioMixer params (used only for AudioMixerFloat01ToDb)
|
||||
public AudioMixer mixer;
|
||||
public string mixerParameter = "MasterVolumeDb";
|
||||
public float minDb = -80f;
|
||||
public float maxDb = 0f;
|
||||
// Audio params (используется только для ApplyTarget.Audio)
|
||||
[Tooltip("Тип звука: музыка или звуковые эффекты")]
|
||||
public AudioTargetType audioTargetType = AudioTargetType.Music;
|
||||
|
||||
// Button params (для типа Button)
|
||||
[Header("Button Settings")]
|
||||
[Tooltip("Текст на кнопке (если не задан displayName)")]
|
||||
public string buttonText;
|
||||
|
||||
@ -92,7 +105,6 @@ namespace RR.Common.Settings
|
||||
public Sprite buttonSprite;
|
||||
|
||||
// OptionPicker params (для типа OptionPicker)
|
||||
[Header("Option Picker Settings")]
|
||||
[Tooltip("Список вариантов выбора")]
|
||||
public List<string> options;
|
||||
|
||||
|
||||
@ -166,6 +166,36 @@ namespace RR.Common.Settings
|
||||
public void SetFloat(string key, float value) => Set(key, SettingValue.Float(value));
|
||||
public void SetString(string key, string value) => Set(key, SettingValue.String(value));
|
||||
|
||||
/// <summary>
|
||||
/// Изменяет настройку извне (с проверкой флага exposed)
|
||||
/// </summary>
|
||||
public bool SetExternal(string key, SettingValue value)
|
||||
{
|
||||
if (this == null) return false;
|
||||
|
||||
SettingEntry def = Define(key);
|
||||
if (def == null)
|
||||
{
|
||||
Debug.LogWarning($"[SettingsManager] No definition found for key '{key}'.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!def.exposed)
|
||||
{
|
||||
Debug.LogWarning($"[SettingsManager] Setting '{key}' is not exposed for external changes. Set 'exposed' flag to true in SettingsDatabase.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Set(key, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Удобные типизированные сеттеры для внешних изменений
|
||||
public bool SetExternalBool(string key, bool value) => SetExternal(key, SettingValue.Bool(value));
|
||||
public bool SetExternalInt(string key, int value) => SetExternal(key, SettingValue.Int(value));
|
||||
public bool SetExternalFloat(string key, float value) => SetExternal(key, SettingValue.Float(value));
|
||||
public bool SetExternalString(string key, string value) => SetExternal(key, SettingValue.String(value));
|
||||
|
||||
/// <summary>
|
||||
/// Немедленное сохранение настроек
|
||||
/// </summary>
|
||||
@ -173,6 +203,58 @@ namespace RR.Common.Settings
|
||||
{
|
||||
SaveNow();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Перезагружает настройки из файла (только exposed настройки)
|
||||
/// Полезно для hot-reload при изменении файла извне
|
||||
/// </summary>
|
||||
public void ReloadFromFile()
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
Debug.LogWarning($"[SettingsManager] Settings file not found: {path}");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(path);
|
||||
SettingsSaveData data = JsonUtility.FromJson<SettingsSaveData>(json);
|
||||
if (data != null)
|
||||
{
|
||||
foreach (SettingsSaveData.Entry e in data.entries)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(e.key)) continue;
|
||||
|
||||
SettingEntry def = Define(e.key);
|
||||
if (def == null)
|
||||
{
|
||||
Debug.LogWarning($"[SettingsManager] Unknown setting key '{e.key}' in file.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Проверяем флаг exposed
|
||||
if (!def.exposed)
|
||||
{
|
||||
Debug.LogWarning($"[SettingsManager] Skipping '{e.key}' - not exposed for external changes.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Применяем настройку
|
||||
SettingValue clean = def.Sanitize(e.value);
|
||||
map[e.key] = clean;
|
||||
SettingsApplier.Apply(def, clean);
|
||||
OnSettingChanged?.Invoke(e.key, clean);
|
||||
}
|
||||
|
||||
Debug.Log($"[SettingsManager] Reloaded settings from {path}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[SettingsManager] Failed to reload settings: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyAll()
|
||||
{
|
||||
@ -219,6 +301,11 @@ namespace RR.Common.Settings
|
||||
}
|
||||
|
||||
private void LoadOrDefaults()
|
||||
{
|
||||
LoadOrDefaults(checkExposed: false);
|
||||
}
|
||||
|
||||
private void LoadOrDefaults(bool checkExposed)
|
||||
{
|
||||
map.Clear();
|
||||
|
||||
@ -231,8 +318,22 @@ namespace RR.Common.Settings
|
||||
if (data != null)
|
||||
{
|
||||
foreach (SettingsSaveData.Entry e in data.entries)
|
||||
if (!string.IsNullOrWhiteSpace(e.key))
|
||||
map[e.key] = e.value;
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(e.key)) continue;
|
||||
|
||||
// Если checkExposed = true, проверяем флаг exposed
|
||||
if (checkExposed)
|
||||
{
|
||||
SettingEntry def = Define(e.key);
|
||||
if (def != null && !def.exposed)
|
||||
{
|
||||
Debug.LogWarning($"[SettingsManager] Skipping '{e.key}' from file - not exposed.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
map[e.key] = e.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
|
||||
@ -17,6 +17,8 @@ MonoBehaviour:
|
||||
displayName: "\u0413\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u043C\u0443\u0437\u044B\u043A\u0438"
|
||||
description:
|
||||
group: "\u041C\u0443\u0437\u044B\u043A\u0430 \u0438 \u0437\u0432\u0443\u043A\u0438"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 2
|
||||
defaultBool: 0
|
||||
defaultInt: 0
|
||||
@ -24,13 +26,13 @@ MonoBehaviour:
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 0
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 1
|
||||
applyTarget: 1
|
||||
mixer: {fileID: 24100000, guid: 4f44de6a220ee7d4b8179285074ead2d, type: 2}
|
||||
mixerParameter: MusicVolume
|
||||
minDb: -80
|
||||
maxDb: 0
|
||||
audioTargetType: 0
|
||||
buttonText:
|
||||
buttonData:
|
||||
buttonColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
@ -41,6 +43,8 @@ MonoBehaviour:
|
||||
displayName: "\u0413\u0440\u043E\u043C\u043A\u043E\u0441\u0442\u044C \u0437\u0432\u0443\u043A\u043E\u0432"
|
||||
description:
|
||||
group: "\u041C\u0443\u0437\u044B\u043A\u0430 \u0438 \u0437\u0432\u0443\u043A\u0438"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 2
|
||||
defaultBool: 0
|
||||
defaultInt: 0
|
||||
@ -48,13 +52,13 @@ MonoBehaviour:
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 0
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 1
|
||||
applyTarget: 1
|
||||
mixer: {fileID: 24100000, guid: 4f44de6a220ee7d4b8179285074ead2d, type: 2}
|
||||
mixerParameter: SFXVolume
|
||||
minDb: -80
|
||||
maxDb: 0
|
||||
audioTargetType: 1
|
||||
buttonText:
|
||||
buttonData:
|
||||
buttonColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
@ -65,6 +69,8 @@ MonoBehaviour:
|
||||
displayName: "\u0411\u0435\u0441\u043F\u043B\u0430\u0442\u043D\u0430\u044F \u0438\u0433\u0440\u0430"
|
||||
description:
|
||||
group: "\u041E\u043F\u043B\u0430\u0442\u0430 \u0438 \u0441\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 0
|
||||
defaultBool: 0
|
||||
defaultInt: 0
|
||||
@ -72,24 +78,80 @@ MonoBehaviour:
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 0
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
mixer: {fileID: 24100000, guid: 4f44de6a220ee7d4b8179285074ead2d, type: 2}
|
||||
mixerParameter: SFXVolume
|
||||
minDb: -80
|
||||
maxDb: 0
|
||||
audioTargetType: 0
|
||||
buttonText:
|
||||
buttonData:
|
||||
buttonColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
buttonSprite: {fileID: 0}
|
||||
options: []
|
||||
defaultOptionIndex: 0
|
||||
- key: payment.smallPrize
|
||||
- key: payment.supportNumber
|
||||
displayName: "\u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C \u043D\u043E\u043C\u0435\u0440
|
||||
\u043F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0438"
|
||||
description:
|
||||
group: "\u041E\u043F\u043B\u0430\u0442\u0430 \u0438 \u0441\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 0
|
||||
defaultBool: 1
|
||||
defaultInt: 0
|
||||
defaultFloat: 0
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 0
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
audioTargetType: 0
|
||||
buttonText:
|
||||
buttonData:
|
||||
buttonColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
buttonSprite: {fileID: 0}
|
||||
options: []
|
||||
defaultOptionIndex: 0
|
||||
- key: payment.paymentImpulseCost
|
||||
displayName: "\u0421\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C \u043E\u0434\u043D\u043E\u0433\u043E
|
||||
\u0438\u043C\u043F\u0443\u043B\u044C\u0441\u0430"
|
||||
description:
|
||||
group: "\u041E\u043F\u043B\u0430\u0442\u0430 \u0438 \u0441\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 1
|
||||
defaultBool: 0
|
||||
defaultInt: 10
|
||||
defaultFloat: 0
|
||||
defaultString:
|
||||
minInt: 10
|
||||
maxInt: 1000
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
audioTargetType: 0
|
||||
buttonText:
|
||||
buttonData:
|
||||
buttonColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
buttonSprite: {fileID: 0}
|
||||
options: []
|
||||
defaultOptionIndex: 0
|
||||
- key: prizes.giveSmallPrize
|
||||
displayName: "\u0412\u044B\u0434\u0430\u0432\u0430\u0442\u044C \u043C\u0430\u043B\u0435\u043D\u044C\u043A\u0438\u0439
|
||||
\u043F\u0440\u0438\u0437"
|
||||
description:
|
||||
group: "\u041F\u0440\u0438\u0437\u044B \u0438 \u0432\u044B\u0434\u0430\u0447\u0430"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 0
|
||||
defaultBool: 0
|
||||
defaultInt: 0
|
||||
@ -97,23 +159,132 @@ MonoBehaviour:
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 0
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
mixer: {fileID: 24100000, guid: 4f44de6a220ee7d4b8179285074ead2d, type: 2}
|
||||
mixerParameter: SFXVolume
|
||||
minDb: -80
|
||||
maxDb: 0
|
||||
audioTargetType: 0
|
||||
buttonText:
|
||||
buttonData:
|
||||
buttonColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
buttonSprite: {fileID: 0}
|
||||
options: []
|
||||
defaultOptionIndex: 0
|
||||
- key: prizes.giveBigPrize
|
||||
displayName: "\u041F\u043E\u043A\u0430\u0437\u044B\u0432\u0430\u0442\u044C QR-\u043A\u043E\u0434\u044B
|
||||
\u0434\u043B\u044F \u0441\u0432\u044F\u0437\u0438"
|
||||
description:
|
||||
group: "\u041F\u0440\u0438\u0437\u044B \u0438 \u0432\u044B\u0434\u0430\u0447\u0430"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 0
|
||||
defaultBool: 1
|
||||
defaultInt: 1
|
||||
defaultFloat: 0
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 20
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
audioTargetType: 0
|
||||
buttonText: "\u0412\u0432\u0435\u0441\u0442\u0438 \u0441\u0443\u043F\u0435\u0440\u043F\u0440\u0438\u0437"
|
||||
buttonData:
|
||||
buttonColor: {r: 0.563809, g: 0.8509804, b: 0.13333333, a: 1}
|
||||
buttonSprite: {fileID: 0}
|
||||
options: []
|
||||
defaultOptionIndex: 0
|
||||
- key: prizes.errorGivePrize
|
||||
displayName: "\u0412\u044B\u0434\u0430\u0432\u0430\u0442\u044C \u043F\u0440\u0438\u0437
|
||||
\u043F\u0440\u0438 \u043E\u0448\u0438\u0431\u043A\u0435"
|
||||
description:
|
||||
group: "\u041F\u0440\u0438\u0437\u044B \u0438 \u0432\u044B\u0434\u0430\u0447\u0430"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 0
|
||||
defaultBool: 0
|
||||
defaultInt: 1
|
||||
defaultFloat: 0
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 20
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
audioTargetType: 0
|
||||
buttonText: "\u0412\u0432\u0435\u0441\u0442\u0438 \u0441\u0443\u043F\u0435\u0440\u043F\u0440\u0438\u0437"
|
||||
buttonData:
|
||||
buttonColor: {r: 0.563809, g: 0.8509804, b: 0.13333333, a: 1}
|
||||
buttonSprite: {fileID: 0}
|
||||
options: []
|
||||
defaultOptionIndex: 0
|
||||
- key: prizes.showPrizeError
|
||||
displayName: "\u0412\u044B\u0432\u043E\u0434 \u043E\u0448\u0438\u0431\u043A\u0438
|
||||
\u0432\u044B\u0434\u0430\u0447\u0438 \u0432 \u043C\u0435\u043D\u044E"
|
||||
description:
|
||||
group: "\u041F\u0440\u0438\u0437\u044B \u0438 \u0432\u044B\u0434\u0430\u0447\u0430"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 0
|
||||
defaultBool: 0
|
||||
defaultInt: 1
|
||||
defaultFloat: 0
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 20
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
audioTargetType: 0
|
||||
buttonText: "\u0412\u0432\u0435\u0441\u0442\u0438 \u0441\u0443\u043F\u0435\u0440\u043F\u0440\u0438\u0437"
|
||||
buttonData:
|
||||
buttonColor: {r: 0.563809, g: 0.8509804, b: 0.13333333, a: 1}
|
||||
buttonSprite: {fileID: 0}
|
||||
options: []
|
||||
defaultOptionIndex: 0
|
||||
- key: prizes.phoneNumber
|
||||
displayName: "\u041D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430"
|
||||
description:
|
||||
group: "\u041F\u0440\u0438\u0437\u044B \u0438 \u0432\u044B\u0434\u0430\u0447\u0430"
|
||||
shownInSettings: 0
|
||||
exposed: 0
|
||||
valueType: 3
|
||||
defaultBool: 0
|
||||
defaultInt: 1
|
||||
defaultFloat: 0
|
||||
defaultString: +79123456789
|
||||
minInt: 0
|
||||
maxInt: 20
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
audioTargetType: 0
|
||||
buttonText: "\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0430"
|
||||
buttonData:
|
||||
buttonColor: {r: 0.8490566, g: 0.40749258, b: 0.13216448, a: 1}
|
||||
buttonSprite: {fileID: 0}
|
||||
options: []
|
||||
defaultOptionIndex: 0
|
||||
- key: gameplay.startLives
|
||||
displayName: "\u041D\u0430\u0447\u0430\u043B\u044C\u043D\u044B\u0435 \u0436\u0438\u0437\u043D\u0438"
|
||||
description:
|
||||
group: "\u0418\u0433\u0440\u043E\u0432\u043E\u0439 \u043F\u0440\u043E\u0446\u0435\u0441\u0441"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 1
|
||||
defaultBool: 0
|
||||
defaultInt: 3
|
||||
@ -121,13 +292,13 @@ MonoBehaviour:
|
||||
defaultString:
|
||||
minInt: 1
|
||||
maxInt: 20
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
mixer: {fileID: 24100000, guid: 4f44de6a220ee7d4b8179285074ead2d, type: 2}
|
||||
mixerParameter: SFXVolume
|
||||
minDb: -80
|
||||
maxDb: 0
|
||||
audioTargetType: 0
|
||||
buttonText:
|
||||
buttonData:
|
||||
buttonColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
@ -139,6 +310,8 @@ MonoBehaviour:
|
||||
\u043C\u043E\u043D\u0435\u0442\u044B"
|
||||
description:
|
||||
group: "\u0418\u0433\u0440\u043E\u0432\u043E\u0439 \u043F\u0440\u043E\u0446\u0435\u0441\u0441"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 1
|
||||
defaultBool: 0
|
||||
defaultInt: 1
|
||||
@ -146,13 +319,13 @@ MonoBehaviour:
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 20
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
mixer: {fileID: 24100000, guid: 4f44de6a220ee7d4b8179285074ead2d, type: 2}
|
||||
mixerParameter: SFXVolume
|
||||
minDb: -80
|
||||
maxDb: 0
|
||||
audioTargetType: 0
|
||||
buttonText:
|
||||
buttonData:
|
||||
buttonColor: {r: 0, g: 0, b: 0, a: 0}
|
||||
@ -162,7 +335,9 @@ MonoBehaviour:
|
||||
- key: btn.statistics
|
||||
displayName: "\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0430"
|
||||
description:
|
||||
group: "\u041E\u043F\u043B\u0430\u0442\u0430 \u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0430"
|
||||
group: "\u041E\u043F\u043B\u0430\u0442\u0430 \u0438 \u0441\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 4
|
||||
defaultBool: 0
|
||||
defaultInt: 1
|
||||
@ -170,16 +345,98 @@ MonoBehaviour:
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 20
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
mixer: {fileID: 24100000, guid: 4f44de6a220ee7d4b8179285074ead2d, type: 2}
|
||||
mixerParameter: SFXVolume
|
||||
minDb: -80
|
||||
maxDb: 0
|
||||
audioTargetType: 0
|
||||
buttonText: "\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043A\u0430"
|
||||
buttonData:
|
||||
buttonColor: {r: 0.8490566, g: 0.40749258, b: 0.13216448, a: 1}
|
||||
buttonSprite: {fileID: 0}
|
||||
options: []
|
||||
defaultOptionIndex: 0
|
||||
- key: btn.phoneNumber
|
||||
displayName: "\u0412\u0432\u0435\u0441\u0442\u0438 \u043D\u043E\u043C\u0435\u0440
|
||||
\u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430"
|
||||
description:
|
||||
group: "\u041F\u0440\u0438\u0437\u044B \u0438 \u0432\u044B\u0434\u0430\u0447\u0430"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 4
|
||||
defaultBool: 0
|
||||
defaultInt: 1
|
||||
defaultFloat: 0
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 20
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
audioTargetType: 0
|
||||
buttonText: "\u0412\u0432\u0435\u0441\u0442\u0438 \u043D\u043E\u043C\u0435\u0440
|
||||
\u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430"
|
||||
buttonData:
|
||||
buttonColor: {r: 0.8490566, g: 0.40749258, b: 0.13216448, a: 1}
|
||||
buttonSprite: {fileID: 0}
|
||||
options: []
|
||||
defaultOptionIndex: 0
|
||||
- key: btn.bigPrize
|
||||
displayName: "\u0412\u0432\u0435\u0441\u0442\u0438 \u0441\u0443\u043F\u0435\u0440\u043F\u0440\u0438\u0437"
|
||||
description:
|
||||
group: "\u041F\u0440\u0438\u0437\u044B \u0438 \u0432\u044B\u0434\u0430\u0447\u0430"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 4
|
||||
defaultBool: 0
|
||||
defaultInt: 1
|
||||
defaultFloat: 0
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 20
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
audioTargetType: 0
|
||||
buttonText: "\u0412\u0432\u0435\u0441\u0442\u0438 \u0441\u0443\u043F\u0435\u0440\u043F\u0440\u0438\u0437"
|
||||
buttonData:
|
||||
buttonColor: {r: 0.563809, g: 0.8509804, b: 0.13333333, a: 1}
|
||||
buttonSprite: {fileID: 0}
|
||||
options: []
|
||||
defaultOptionIndex: 0
|
||||
- key: btn.supportNumber
|
||||
displayName: "\u0412\u0432\u0435\u0441\u0442\u0438 \u043D\u043E\u043C\u0435\u0440
|
||||
\u043F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0438"
|
||||
description:
|
||||
group: "\u041E\u043F\u043B\u0430\u0442\u0430 \u0438 \u0441\u0442\u043E\u0438\u043C\u043E\u0441\u0442\u044C"
|
||||
shownInSettings: 1
|
||||
exposed: 0
|
||||
valueType: 4
|
||||
defaultBool: 1
|
||||
defaultInt: 0
|
||||
defaultFloat: 0
|
||||
defaultString:
|
||||
minInt: 0
|
||||
maxInt: 0
|
||||
intDisplayFormat: 0
|
||||
intStep: 1
|
||||
minFloat: 0
|
||||
maxFloat: 1
|
||||
displayAsPercentage: 0
|
||||
applyTarget: 0
|
||||
audioTargetType: 0
|
||||
buttonText: "\u0412\u0432\u0435\u0441\u0442\u0438 \u043D\u043E\u043C\u0435\u0440
|
||||
\u043F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0438"
|
||||
buttonData:
|
||||
buttonColor: {r: 0.16300285, g: 0.64997125, b: 0.9339623, a: 1}
|
||||
buttonSprite: {fileID: 0}
|
||||
options: []
|
||||
defaultOptionIndex: 0
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RR.Common.Settings;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
@ -107,40 +106,7 @@ namespace RR.Common.UI
|
||||
{
|
||||
if (entry == null) return;
|
||||
|
||||
// Спец-случаи с Dropdown
|
||||
if (entry.applyTarget == ApplyTarget.QualityLevel)
|
||||
{
|
||||
UseDropdown(QualitySettings.names.ToList(), onChanged: idx =>
|
||||
SetSafe(entry.key, SettingValue.Int(idx)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry.applyTarget == ApplyTarget.ResolutionIndex)
|
||||
{
|
||||
Resolution[] rs = Screen.resolutions;
|
||||
List<string> options = rs.Select(t => $"{t.width} x {t.height}").ToList();
|
||||
|
||||
UseDropdown(options, onChanged: idx =>
|
||||
SetSafe(entry.key, SettingValue.Int(idx)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry.applyTarget == ApplyTarget.FullscreenMode)
|
||||
{
|
||||
// индексы 0..3 как в твоём SettingsApplier
|
||||
List<string> options = new()
|
||||
{
|
||||
"Exclusive Fullscreen",
|
||||
"Fullscreen Window",
|
||||
"Maximized Window",
|
||||
"Windowed"
|
||||
};
|
||||
UseDropdown(options, onChanged: idx =>
|
||||
SetSafe(entry.key, SettingValue.Int(idx)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Обычные по типу
|
||||
// Настройки по valueType
|
||||
switch (entry.valueType)
|
||||
{
|
||||
case SettingValueType.Bool:
|
||||
@ -343,9 +309,24 @@ namespace RR.Common.UI
|
||||
{
|
||||
if (!sliderValueText || !slider || !slider.gameObject.activeSelf) return;
|
||||
|
||||
sliderValueText.text = slider.wholeNumbers
|
||||
? Mathf.RoundToInt(slider.value).ToString()
|
||||
: slider.value.ToString("0.##");
|
||||
if (slider.wholeNumbers)
|
||||
{
|
||||
sliderValueText.text = Mathf.RoundToInt(slider.value).ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Проверяем флаг displayAsPercentage
|
||||
if (entry != null && entry.displayAsPercentage)
|
||||
{
|
||||
// Отображаем как проценты (0-100%)
|
||||
float percentage = slider.value * 100f;
|
||||
sliderValueText.text = percentage.ToString("0") + "%";
|
||||
}
|
||||
else
|
||||
{
|
||||
sliderValueText.text = slider.value.ToString("0.##");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -142,7 +142,7 @@ namespace RR.Common.UI
|
||||
spawnedItems.Clear();
|
||||
|
||||
List<SettingEntry> entries = database.entries
|
||||
.Where(e => e != null && !string.IsNullOrWhiteSpace(e.key))
|
||||
.Where(e => e != null && !string.IsNullOrWhiteSpace(e.key) && e.shownInSettings)
|
||||
.ToList();
|
||||
|
||||
if (!groupByGroup)
|
||||
@ -239,24 +239,17 @@ namespace RR.Common.UI
|
||||
|
||||
private SettingUIItem PickPrefab(SettingEntry e)
|
||||
{
|
||||
return e.applyTarget switch
|
||||
|
||||
return e.valueType switch
|
||||
{
|
||||
// Спец-UI по ApplyTarget
|
||||
ApplyTarget.QualityLevel => dropdownRowPrefab,
|
||||
ApplyTarget.ResolutionIndex => dropdownRowPrefab,
|
||||
ApplyTarget.FullscreenMode => dropdownRowPrefab,
|
||||
|
||||
_ => e.valueType switch
|
||||
{
|
||||
// По типу
|
||||
SettingValueType.Bool => toggleRowPrefab,
|
||||
SettingValueType.Float => sliderRowPrefab,
|
||||
SettingValueType.Int => sliderRowPrefab ? sliderRowPrefab : dropdownRowPrefab,
|
||||
SettingValueType.String => inputRowPrefab,
|
||||
SettingValueType.Button => buttonRowPrefab,
|
||||
SettingValueType.OptionPicker => optionPickerRowPrefab ? optionPickerRowPrefab : dropdownRowPrefab,
|
||||
_ => null
|
||||
}
|
||||
// По типу
|
||||
SettingValueType.Bool => toggleRowPrefab,
|
||||
SettingValueType.Float => sliderRowPrefab,
|
||||
SettingValueType.Int => sliderRowPrefab ? sliderRowPrefab : dropdownRowPrefab,
|
||||
SettingValueType.String => inputRowPrefab,
|
||||
SettingValueType.Button => buttonRowPrefab,
|
||||
SettingValueType.OptionPicker => optionPickerRowPrefab ? optionPickerRowPrefab : dropdownRowPrefab,
|
||||
_ => null
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -154,32 +154,30 @@ namespace RR.Common.UI
|
||||
|
||||
private Vector2 GetTargetPosition(RectTransform target)
|
||||
{
|
||||
// Получаем позицию целевого элемента относительно content
|
||||
Vector2 targetAnchoredPos = target.anchoredPosition;
|
||||
|
||||
// Если элементы не прямые дети content, нужно пересчитать позицию
|
||||
if (target.parent == content)
|
||||
return new Vector2(
|
||||
pointerRect.anchoredPosition.x + offset.x, // X оставляем как есть (или применяем offset)
|
||||
targetAnchoredPos.y + offset.y // Y берем от целевого элемента
|
||||
);
|
||||
// Конвертируем мировую позицию в локальную позицию content
|
||||
// Получаем мировые координаты центра целевого элемента
|
||||
Vector3[] corners = new Vector3[4];
|
||||
target.GetWorldCorners(corners);
|
||||
Vector3 center = (corners[0] + corners[2]) * 0.5f;
|
||||
Vector3 worldCenter = (corners[0] + corners[2]) * 0.5f;
|
||||
|
||||
// Конвертируем мировую позицию в локальную позицию родителя указателя
|
||||
RectTransform pointerParent = pointerRect.parent as RectTransform;
|
||||
if (pointerParent == null)
|
||||
{
|
||||
Debug.LogWarning("UIPointer: pointer не имеет RectTransform родителя!");
|
||||
return pointerRect.anchoredPosition;
|
||||
}
|
||||
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
content,
|
||||
RectTransformUtility.WorldToScreenPoint(null, center),
|
||||
pointerParent,
|
||||
RectTransformUtility.WorldToScreenPoint(null, worldCenter),
|
||||
null,
|
||||
out Vector2 localPos
|
||||
);
|
||||
targetAnchoredPos = localPos;
|
||||
|
||||
// Применяем смещение
|
||||
// X фиксирована, меняется только Y
|
||||
return new Vector2(
|
||||
pointerRect.anchoredPosition.x + offset.x, // X оставляем как есть (или применяем offset)
|
||||
targetAnchoredPos.y + offset.y // Y берем от целевого элемента
|
||||
pointerRect.anchoredPosition.x, // X остается как есть
|
||||
localPos.y + offset.y // Y от целевого элемента + смещение
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user