diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 599e83dc..08fe7b39 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -33,7 +33,9 @@ "Bash(cmd /c \"mkdir \"\"d:\\\\works\\\\2025\\\\02.Studio\\\\dev\\\\base\\\\XRBase\\\\Assets\\\\Scripts\\\\UVC\\\\UIToolkit\\\\ToolBar\\\\Data\"\" && mkdir \"\"d:\\\\works\\\\2025\\\\02.Studio\\\\dev\\\\base\\\\XRBase\\\\Assets\\\\Scripts\\\\UVC\\\\UIToolkit\\\\ToolBar\\\\Items\"\" && mkdir \"\"d:\\\\works\\\\2025\\\\02.Studio\\\\dev\\\\base\\\\XRBase\\\\Assets\\\\Resources\\\\UIToolkit\\\\ToolBar\"\"\")", "Bash(/bin/ls:*)", "Bash(/bin/mkdir -p:*)", - "Bash(/bin/rm:*)" + "Bash(/bin/rm:*)", + "WebFetch(domain:docs.unity3d.com)", + "Bash(ls:*)" ], "deny": [], "ask": [] diff --git a/Assets/Resources/UIToolkit/List/UTKReordableListItem.uxml b/Assets/Resources/UIToolkit/List/UTKReordableListItem.uxml new file mode 100644 index 00000000..2dce22d9 --- /dev/null +++ b/Assets/Resources/UIToolkit/List/UTKReordableListItem.uxml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + diff --git a/Assets/Resources/UIToolkit/List/UTKReordableListItem.uxml.meta b/Assets/Resources/UIToolkit/List/UTKReordableListItem.uxml.meta new file mode 100644 index 00000000..aa1f13b2 --- /dev/null +++ b/Assets/Resources/UIToolkit/List/UTKReordableListItem.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 83ba2c4f240fbfb44a4ed4acd25aa5ce +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/Assets/Resources/UIToolkit/List/UTKReordableListItemUss.uss b/Assets/Resources/UIToolkit/List/UTKReordableListItemUss.uss new file mode 100644 index 00000000..a3052a3f --- /dev/null +++ b/Assets/Resources/UIToolkit/List/UTKReordableListItemUss.uss @@ -0,0 +1,56 @@ +/* + * =================================== + * UTKReordableListItemUss.uss + * 재정렬 가능 리스트 아이템 스타일 + * =================================== + */ + +/* =================================== + Item Container + =================================== */ + +.reordable-list-item { + flex-direction: row; + align-items: center; + padding: var(--space-s) var(--space-m); + min-height: 36px; +} + +/* =================================== + Drag Handle + =================================== */ + +.reordable-list-item__drag-handle { + width: 24px; + height: 24px; + -unity-font-definition: resource('Fonts/Icons/MaterialSymbolsOutlined'); + font-size: 18px; + color: var(--color-text-secondary); + -unity-text-align: middle-center; + flex-shrink: 0; + margin-right: var(--space-xs); + cursor: move; + padding: 0; +} + +.reordable-list-item__drag-handle:hover { + color: var(--color-text-primary); +} + +/* =================================== + Checkbox + =================================== */ + +.reordable-list-item__checkbox { + flex-shrink: 0; + margin-right: var(--space-s); +} + +/* =================================== + Input Field + =================================== */ + +.reordable-list-item__input { + flex-grow: 1; + min-width: 0; +} diff --git a/Assets/Resources/UIToolkit/List/UTKReordableListItemUss.uss.meta b/Assets/Resources/UIToolkit/List/UTKReordableListItemUss.uss.meta new file mode 100644 index 00000000..9858638b --- /dev/null +++ b/Assets/Resources/UIToolkit/List/UTKReordableListItemUss.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 18f971ae90e8e1c4bad0afcc31efe1d1 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Assets/Resources/UIToolkit/List/UTKReordableListUss.uss b/Assets/Resources/UIToolkit/List/UTKReordableListUss.uss new file mode 100644 index 00000000..95913bfd --- /dev/null +++ b/Assets/Resources/UIToolkit/List/UTKReordableListUss.uss @@ -0,0 +1,47 @@ +/* + * =================================== + * UTKReordableListUss.uss + * 재정렬 가능 리스트 컨테이너 스타일 + * =================================== + */ + +/* =================================== + Base Container + =================================== */ + +.reordable-list { + flex-grow: 1; + background-color: var(--color-bg-secondary); + border-radius: var(--radius-s); + border-width: var(--border-width); + border-color: var(--color-border); +} + +/* =================================== + ListView 내부 여백 조정 + =================================== */ + +.reordable-list .utk-listview { + flex-grow: 1; + border-width: 0; + border-radius: 0; + background-color: transparent; +} + +/* =================================== + 드래그 중 아이템 스타일 (Unity 내장 클래스) + =================================== */ + +.reordable-list .unity-list-view__reorderable-item__container { + flex-direction: row; + align-items: center; +} + +/* =================================== + 드래그 핸들 바 (Unity 내장 reorder handle) + 커스텀 드래그 핸들 사용하므로 기본 숨김 + =================================== */ + +.reordable-list .unity-list-view__reorderable-handle-bar { + display: none; +} diff --git a/Assets/Resources/UIToolkit/List/UTKReordableListUss.uss.meta b/Assets/Resources/UIToolkit/List/UTKReordableListUss.uss.meta new file mode 100644 index 00000000..ee0b66cc --- /dev/null +++ b/Assets/Resources/UIToolkit/List/UTKReordableListUss.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ebeda1896b5d02d489342ed0c4e45698 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Assets/Resources/UIToolkit/Modal/Setting.meta b/Assets/Resources/UIToolkit/Modal/Setting.meta new file mode 100644 index 00000000..113b6910 --- /dev/null +++ b/Assets/Resources/UIToolkit/Modal/Setting.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 62b1c6b38fe308748b808fb2b576e6e2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/UIToolkit/Modal/Setting/UTKSettingDisplayInfoTabViewUss.uss b/Assets/Resources/UIToolkit/Modal/Setting/UTKSettingDisplayInfoTabViewUss.uss new file mode 100644 index 00000000..02a100cb --- /dev/null +++ b/Assets/Resources/UIToolkit/Modal/Setting/UTKSettingDisplayInfoTabViewUss.uss @@ -0,0 +1,47 @@ +/* + * =================================== + * UTKSettingDisplayInfoTabViewUss.uss + * 설정 표시 정보 탭 뷰 컨테이너 스타일 + * =================================== + */ + +/* =================================== + Base Container + =================================== */ + +.setting-display-tab-view { + flex-grow: 1; + background-color: var(--color-bg-secondary); + border-radius: var(--radius-s); + border-width: var(--border-width); + border-color: var(--color-border); +} + +/* =================================== + ListView 내부 여백 조정 + =================================== */ + +.setting-display-tab-view .utk-listview { + flex-grow: 1; + border-width: 0; + border-radius: 0; + background-color: transparent; +} + +/* =================================== + 드래그 중 아이템 스타일 (Unity 내장 클래스) + =================================== */ + +.setting-display-tab-view .unity-list-view__reorderable-item__container { + flex-direction: row; + align-items: center; +} + +/* =================================== + 드래그 핸들 바 (Unity 내장 reorder handle) + 커스텀 드래그 핸들 사용하므로 기본 숨김 + =================================== */ + +.setting-display-tab-view .unity-list-view__reorderable-handle-bar { + display: none; +} diff --git a/Assets/Resources/UIToolkit/Modal/Setting/UTKSettingDisplayInfoTabViewUss.uss.meta b/Assets/Resources/UIToolkit/Modal/Setting/UTKSettingDisplayInfoTabViewUss.uss.meta new file mode 100644 index 00000000..6173d6c3 --- /dev/null +++ b/Assets/Resources/UIToolkit/Modal/Setting/UTKSettingDisplayInfoTabViewUss.uss.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 360ccda715f15bc479dec409d0ed87cf +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} + disableValidation: 0 diff --git a/Assets/Sample/UIToolkit/UTKSettingModal.unity b/Assets/Sample/UIToolkit/UTKSettingModal.unity new file mode 100644 index 00000000..e368c5a5 --- /dev/null +++ b/Assets/Sample/UIToolkit/UTKSettingModal.unity @@ -0,0 +1,497 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 10 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 1 + m_PVRFilteringGaussRadiusAO: 1 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &1097328750 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1097328752} + - component: {fileID: 1097328754} + - component: {fileID: 1097328755} + m_Layer: 0 + m_Name: Sample + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1097328752 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1097328750} + serializedVersion: 2 + 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: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1097328754 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1097328750} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 19102, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: UnityEngine.dll::UnityEngine.UIElements.UIDocument + m_PanelSettings: {fileID: 11400000, guid: 5ad7007b08a97b54d927c352279a18b6, type: 2} + m_ParentUI: {fileID: 0} + sourceAsset: {fileID: 9197481963319205126, guid: 54e4f33c8b08cb54f97dbdb5edd79e1e, type: 3} + m_SortingOrder: 1 + m_Position: 0 + m_WorldSpaceSizeMode: 1 + m_WorldSpaceWidth: 1920 + m_WorldSpaceHeight: 1080 + m_PivotReferenceSize: 0 + m_Pivot: 0 + m_WorldSpaceCollider: {fileID: 0} +--- !u!114 &1097328755 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1097328750} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 39265a781c40bdb4a90aa56b0fbf44a6, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::UVC.Sample.UIToolkit.UTKToolBarSample + _uiDocument: {fileID: 1097328754} + initialTheme: 0 +--- !u!1 &1331954412 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1331954415} + - component: {fileID: 1331954414} + - component: {fileID: 1331954413} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1331954413 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1331954412} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3} + m_Name: + m_EditorClassIdentifier: + m_SendPointerHoverToParent: 1 + m_MoveRepeatDelay: 0.5 + m_MoveRepeatRate: 0.1 + m_XRTrackingOrigin: {fileID: 0} + m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_PointAction: {fileID: -1654692200621890270, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_MoveAction: {fileID: -8784545083839296357, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_SubmitAction: {fileID: 392368643174621059, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_CancelAction: {fileID: 7727032971491509709, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_LeftClickAction: {fileID: 3001919216989983466, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_MiddleClickAction: {fileID: -2185481485913320682, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_RightClickAction: {fileID: -4090225696740746782, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_ScrollWheelAction: {fileID: 6240969308177333660, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_TrackedDevicePositionAction: {fileID: 6564999863303420839, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_TrackedDeviceOrientationAction: {fileID: 7970375526676320489, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3} + m_DeselectOnBackgroundClick: 0 + m_PointerBehavior: 0 + m_CursorLockBehavior: 0 + m_ScrollDeltaPerTick: 6 +--- !u!114 &1331954414 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1331954412} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 10 +--- !u!4 &1331954415 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1331954412} + serializedVersion: 2 + 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: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1414861612 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1414861614} + - component: {fileID: 1414861613} + - component: {fileID: 1414861615} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1414861613 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1414861612} + m_Enabled: 1 + serializedVersion: 11 + m_Type: 1 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 +--- !u!4 &1414861614 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1414861612} + serializedVersion: 2 + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!114 &1414861615 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1414861612} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UsePipelineSettings: 1 + m_AdditionalLightsShadowResolutionTier: 2 + m_CustomShadowLayers: 0 + m_LightCookieSize: {x: 1, y: 1} + m_LightCookieOffset: {x: 0, y: 0} + m_SoftShadowQuality: 0 + m_RenderingLayersMask: + serializedVersion: 0 + m_Bits: 1 + m_ShadowRenderingLayersMask: + serializedVersion: 0 + m_Bits: 1 + m_Version: 4 + m_LightLayerMask: 1 + m_ShadowLayerMask: 1 + m_RenderingLayers: 1 + m_ShadowRenderingLayers: 1 +--- !u!1 &2136621999 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2136622002} + - component: {fileID: 2136622001} + - component: {fileID: 2136622000} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &2136622000 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2136621999} + m_Enabled: 1 +--- !u!20 &2136622001 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2136621999} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &2136622002 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2136621999} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 2136622002} + - {fileID: 1414861614} + - {fileID: 1331954415} + - {fileID: 1097328752} diff --git a/Assets/Sample/UIToolkit/UTKSettingModal.unity.meta b/Assets/Sample/UIToolkit/UTKSettingModal.unity.meta new file mode 100644 index 00000000..b039aeaf --- /dev/null +++ b/Assets/Sample/UIToolkit/UTKSettingModal.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7cce97e0d24c7794da00973b5ead99be +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sample/UIToolkit/UTKSettingModalSample.cs b/Assets/Sample/UIToolkit/UTKSettingModalSample.cs new file mode 100644 index 00000000..6584227b --- /dev/null +++ b/Assets/Sample/UIToolkit/UTKSettingModalSample.cs @@ -0,0 +1,59 @@ +#nullable enable +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UIElements; +using UVC.UIToolkit; +using UVC.UI.Commands; +using UVC.Log; + +namespace UVC.Sample.UIToolkit +{ + /// + /// UTKSettingModalSample 독립 실행 샘플 코드입니다. + /// + public class UTKSettingModalSample : MonoBehaviour + { + [SerializeField] private UIDocument? _uiDocument; + + [SerializeField] + [Tooltip("시작 시 적용할 테마")] + private UTKTheme initialTheme = UTKTheme.Dark; + + private UTKToggle? _themeToggle; + private VisualElement? _root; + + private void Start() + { + // UIDocument 참조 확인 + var doc = GetComponent(); + if (doc == null) + { + Debug.LogError("UIDocument가 할당되지 않았습니다."); + return; + } + _uiDocument = doc; + _root = _uiDocument.rootVisualElement; + + UTKThemeManager.Instance.RegisterRoot(_root); + UTKThemeManager.Instance.SetTheme(initialTheme); + + // 테마 토글 + _themeToggle = _root.Q("toggle"); + if (_themeToggle != null) + { + _themeToggle.OnValueChanged += (isOn) => + { + UTKThemeManager.Instance.SetTheme(!isOn ? UTKTheme.Dark : UTKTheme.Light); + }; + } + + } + + private void OnDestroy() + { + + + ULog.Debug("UTKSettingModalSample 정리 완료"); + } + } +} diff --git a/Assets/Sample/UIToolkit/UTKSettingModalSample.cs.meta b/Assets/Sample/UIToolkit/UTKSettingModalSample.cs.meta new file mode 100644 index 00000000..2855e9fe --- /dev/null +++ b/Assets/Sample/UIToolkit/UTKSettingModalSample.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e88ad13f58976fb4a837242a7e1c8282 diff --git a/Assets/Sample/UIToolkit/UTKSettingModalUXML.uxml b/Assets/Sample/UIToolkit/UTKSettingModalUXML.uxml new file mode 100644 index 00000000..d4b81360 --- /dev/null +++ b/Assets/Sample/UIToolkit/UTKSettingModalUXML.uxml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Assets/Sample/UIToolkit/UTKSettingModalUXML.uxml.meta b/Assets/Sample/UIToolkit/UTKSettingModalUXML.uxml.meta new file mode 100644 index 00000000..c4b36402 --- /dev/null +++ b/Assets/Sample/UIToolkit/UTKSettingModalUXML.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 6c8eae7ee21b96245b325f08111b214b +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/Assets/Scripts/UVC/UIToolkit/List/UTKReordableList.cs b/Assets/Scripts/UVC/UIToolkit/List/UTKReordableList.cs new file mode 100644 index 00000000..40ce5593 --- /dev/null +++ b/Assets/Scripts/UVC/UIToolkit/List/UTKReordableList.cs @@ -0,0 +1,383 @@ +#nullable enable +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UIElements; + +namespace UVC.UIToolkit +{ + /// + /// 설정 표시 정보 아이템 데이터. + /// + public class ReordableListItemData + { + /// 표시 순서 (ListView 인덱스 기준) + public int Order { get; set; } + + /// 사용 유무 + public bool IsActive { get; set; } + + /// 표시 내용 + public string DisplayText { get; set; } = ""; + } + + /// + /// 설정 표시 정보 탭 뷰. + /// UTKListView를 활용하여 마우스 드래그로 항목 순서를 변경할 수 있는 설정 목록 뷰입니다. + /// 각 항목은 드래그 핸들, 체크박스(사용 유무), 입력 필드(내용 수정)로 구성됩니다. + /// + [UxmlElement] + public partial class UTKReordableList : VisualElement, IDisposable + { + #region Constants + private const string USS_PATH = "UIToolkit/List/UTKReordableListUss"; + private const string ITEM_UXML_PATH = "UIToolkit/List/UTKReordableListItem"; + private const string ITEM_USS_PATH = "UIToolkit/List/UTKReordableListItemUss"; + private const float ITEM_HEIGHT = 36f; + #endregion + + #region Fields + private bool _disposed; + private UTKListView? _listView; + private List _items = new(); + private VisualTreeAsset? _itemTemplate; + private StyleSheet? _itemStyleSheet; + #endregion + + #region Events + /// 순서 변경 시 발생 + public event Action? OnOrderChanged; + + /// 데이터(체크/텍스트) 변경 시 발생 + public event Action? OnDataChanged; + #endregion + + #region Constructor + public UTKReordableList() : base() + { + // 1. 테마 적용 + UTKThemeManager.Instance.ApplyThemeToElement(this); + + // 2. USS 로드 + var uss = Resources.Load(USS_PATH); + if (uss != null) + { + styleSheets.Add(uss); + } + + // 3. UI 생성 + CreateUI(); + + // 4. 테마 변경 구독 + SubscribeToThemeChanges(); + } + #endregion + + #region Setup + private void CreateUI() + { + AddToClassList("reordable-list"); + SetupListView(); + } + + private void SetupListView() + { + _listView = new UTKListView(); + _listView.makeItem = MakeItem; + _listView.bindItem = BindItem; + _listView.unbindItem = UnbindItem; + _listView.fixedItemHeight = ITEM_HEIGHT; + _listView.selectionType = SelectionType.Single; + _listView.reorderable = true; + _listView.reorderMode = ListViewReorderMode.Animated; + _listView.itemIndexChanged += OnItemIndexChanged; + + Add(_listView); + } + + private void SubscribeToThemeChanges() + { + UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged; + RegisterCallback(OnAttachToPanelForTheme); + RegisterCallback(OnDetachFromPanelForTheme); + } + + private void OnAttachToPanelForTheme(AttachToPanelEvent evt) + { + UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged; + UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged; + UTKThemeManager.Instance.ApplyThemeToElement(this); + } + + private void OnDetachFromPanelForTheme(DetachFromPanelEvent evt) + { + UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged; + } + + private void OnThemeChanged(UTKTheme theme) + { + UTKThemeManager.Instance.ApplyThemeToElement(this); + } + #endregion + + #region ListView Callbacks + private VisualElement MakeItem() + { + // UXML 캐싱 + _itemTemplate ??= Resources.Load(ITEM_UXML_PATH); + // USS 캐싱 (코드에서 로드 - UXML에서 지정하지 않음) + _itemStyleSheet ??= Resources.Load(ITEM_USS_PATH); + + if (_itemTemplate != null) + { + var root = _itemTemplate.Instantiate(); + + // USS 적용 (코드에서 적용) + if (_itemStyleSheet != null) + root.styleSheets.Add(_itemStyleSheet); + + // 드래그 핸들 아이콘 설정 + var handle = root.Q