UTKToolBar 완료
This commit is contained in:
@@ -12,7 +12,6 @@
|
||||
.utk-checkbox {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
align-self: flex-start;
|
||||
cursor: resource('UIToolkit/Images/cursor_point_white_32') 14 5;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
-->
|
||||
<ui:VisualElement name="group-header" class="utk-property-group__header">
|
||||
<utk:UTKLabel name="expand-icon" class="utk-property-group__expand-icon" />
|
||||
<utk:UTKLabel name="group-title" class="utk-property-group__title" />
|
||||
<utk:UTKLabel name="group-title" class="utk-property-group__title" size="Label2" is-bold="true" />
|
||||
<!-- <utk:UTKLabel name="group-count" class="utk-property-group__count" /> -->
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<!-- USS는 테마 적용을 위해 C# 코드에서 로드합니다 (UXML에서 지정하지 않음) -->
|
||||
<ui:VisualElement name="item-container" class="reordable-list-item">
|
||||
<!-- 드래그 핸들 아이콘 (Material Icon: DragIndicator) -->
|
||||
<ui:Label name="drag-handle" class="reordable-list-item__drag-handle" />
|
||||
<utk:UTKLabel name="drag-handle" class="reordable-list-item__drag-handle" />
|
||||
|
||||
<!-- 사용 유무 체크박스 -->
|
||||
<utk:UTKCheckBox name="active-checkbox" class="reordable-list-item__checkbox" />
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
align-items: center;
|
||||
padding: var(--space-s) var(--space-m);
|
||||
min-height: 36px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
/* ===================================
|
||||
|
||||
@@ -10,11 +10,12 @@
|
||||
=================================== */
|
||||
|
||||
.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);
|
||||
padding-top: var(--space-s);
|
||||
padding-bottom: var(--space-s);
|
||||
}
|
||||
|
||||
/* ===================================
|
||||
@@ -32,9 +33,15 @@
|
||||
드래그 중 아이템 스타일 (Unity 내장 클래스)
|
||||
=================================== */
|
||||
|
||||
.reordable-list .unity-list-view__reorderable-item {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.reordable-list .unity-list-view__reorderable-item__container {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
/* ===================================
|
||||
@@ -42,6 +49,13 @@
|
||||
커스텀 드래그 핸들 사용하므로 기본 숨김
|
||||
=================================== */
|
||||
|
||||
.reordable-list .unity-list-view__reorderable-handle {
|
||||
display: none;
|
||||
width: 0;
|
||||
min-width: 0;
|
||||
max-width: 0;
|
||||
}
|
||||
|
||||
.reordable-list .unity-list-view__reorderable-handle-bar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -159,6 +159,7 @@ ListView/TreeView 항목 텍스트 스타일
|
||||
.unity-list-view__item .unity-text-element {
|
||||
color: var(--color-text-primary) ;
|
||||
font-size: var(--font-size-body2) ;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.unity-collection-view__item--selected,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements">
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:utk="UVC.UIToolkit" editor-extension-mode="False">
|
||||
<ui:VisualElement name="button-root" class="utk-toolbar-btn">
|
||||
<ui:Label name="icon" class="utk-toolbar-btn__icon" />
|
||||
<ui:Label name="label" class="utk-toolbar-btn__label" />
|
||||
<utk:UTKLabel name="icon" class="utk-toolbar-btn__icon" />
|
||||
<utk:UTKLabel name="label" class="utk-toolbar-btn__label" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
font-size: var(--font-size-label4);
|
||||
color: var(--color-text-secondary);
|
||||
-unity-text-align: upper-center;
|
||||
margin-top: 1px;
|
||||
display: none;
|
||||
cursor: resource('UIToolkit/Images/cursor_point_white_32') 14 5;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements">
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:utk="UVC.UIToolkit" editor-extension-mode="False">
|
||||
<ui:VisualElement name="button-root" class="utk-toolbar-btn utk-toolbar-expandable">
|
||||
<ui:Label name="icon" class="utk-toolbar-btn__icon" />
|
||||
<ui:Label name="label" class="utk-toolbar-btn__label" />
|
||||
<utk:UTKLabel name="icon" class="utk-toolbar-btn__icon" />
|
||||
<utk:UTKLabel name="label" class="utk-toolbar-btn__label" />
|
||||
<ui:VisualElement name="arrow" class="utk-toolbar-expandable__arrow" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
|
||||
@@ -10,25 +10,31 @@
|
||||
border-color: var(--color-border);
|
||||
border-radius: var(--radius-m);
|
||||
padding: var(--space-xs);
|
||||
min-width: 120px;
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
.utk-toolbar-submenu__container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.utk-toolbar-submenu TemplateContainer {
|
||||
flex-grow: 1;
|
||||
align-items: stretch;
|
||||
}
|
||||
/* 서브 메뉴 내 버튼은 가로로 펼침 */
|
||||
.utk-toolbar-submenu .utk-toolbar-btn {
|
||||
flex-direction: row;
|
||||
min-width: 100px;
|
||||
min-width: 28px;
|
||||
min-height: 28px;
|
||||
justify-content: flex-start;
|
||||
padding: var(--space-xs) var(--space-m);
|
||||
padding: var(--space-xs) 0;
|
||||
margin: 1px 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.utk-toolbar-submenu .utk-toolbar-btn__icon {
|
||||
margin-right: var(--space-s);
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.utk-toolbar-submenu .utk-toolbar-btn__label {
|
||||
@@ -36,4 +42,7 @@
|
||||
font-size: var(--font-size-body2);
|
||||
color: var(--color-text-primary);
|
||||
-unity-text-align: middle-left;
|
||||
margin-right: var(--space-m);
|
||||
flex-grow: 100;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements">
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:utk="UVC.UIToolkit" editor-extension-mode="False">
|
||||
<ui:VisualElement name="button-root" class="utk-toolbar-btn utk-toolbar-toggle">
|
||||
<ui:Label name="icon" class="utk-toolbar-btn__icon" />
|
||||
<ui:Label name="label" class="utk-toolbar-btn__label" />
|
||||
<utk:UTKLabel name="icon" class="utk-toolbar-btn__icon" />
|
||||
<utk:UTKLabel name="label" class="utk-toolbar-btn__label" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
|
||||
497
Assets/Sample/UIToolkit/UTKReordableList.unity
Normal file
497
Assets/Sample/UIToolkit/UTKReordableList.unity
Normal file
@@ -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: 4bb0d1734d5c1b647ae0ffdb7879a92a, type: 3}
|
||||
m_SortingOrder: 0
|
||||
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: 4274ed098fc4bf048bb92836e8982c8f, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::UTKReordableListSample
|
||||
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}
|
||||
7
Assets/Sample/UIToolkit/UTKReordableList.unity.meta
Normal file
7
Assets/Sample/UIToolkit/UTKReordableList.unity.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b1b2ce854a8a3d47ac1fc46dfaf615f
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
152
Assets/Sample/UIToolkit/UTKReordableListSample.cs
Normal file
152
Assets/Sample/UIToolkit/UTKReordableListSample.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UVC.UIToolkit;
|
||||
|
||||
/// <summary>
|
||||
/// UTKReordableList의 기능을 테스트하기 위한 샘플 MonoBehaviour입니다.
|
||||
/// Dictionary 기반 SetData/ToDictionary, 이벤트 핸들러, 데이터 CRUD를 확인합니다.
|
||||
/// </summary>
|
||||
public class UTKReordableListSample : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
public UIDocument uiDocument;
|
||||
|
||||
[SerializeField]
|
||||
[Tooltip("시작 시 적용할 테마")]
|
||||
private UTKTheme initialTheme = UTKTheme.Dark;
|
||||
|
||||
private UTKToggle _themeToggle;
|
||||
private UTKReordableList _reordableList;
|
||||
|
||||
void Start()
|
||||
{
|
||||
// UIDocument 참조 확인
|
||||
var doc = GetComponent<UIDocument>();
|
||||
if (doc == null)
|
||||
{
|
||||
Debug.LogError("UIDocument가 할당되지 않았습니다.");
|
||||
return;
|
||||
}
|
||||
uiDocument = doc;
|
||||
|
||||
var root = uiDocument.rootVisualElement;
|
||||
|
||||
// 테마 토글
|
||||
_themeToggle = root.Q<UTKToggle>("toggle");
|
||||
if (_themeToggle == null)
|
||||
{
|
||||
Debug.LogError("UXML에서 UTKToggle을 찾을 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// ReordableList
|
||||
_reordableList = root.Q<UTKReordableList>("window");
|
||||
if (_reordableList == null)
|
||||
{
|
||||
Debug.LogError("UXML에서 UTKReordableList를 찾을 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 테마 초기화
|
||||
UTKThemeManager.Instance.RegisterRoot(root);
|
||||
UTKThemeManager.Instance.SetTheme(initialTheme);
|
||||
|
||||
_themeToggle.OnValueChanged += (isOn) =>
|
||||
{
|
||||
UTKThemeManager.Instance.SetTheme(!isOn ? UTKTheme.Dark : UTKTheme.Light);
|
||||
};
|
||||
|
||||
// 이벤트 핸들러 등록
|
||||
_reordableList.OnOrderChanged += () => Debug.Log("[Sample] 순서 변경됨");
|
||||
_reordableList.OnDataChanged += () => Debug.Log("[Sample] 데이터 변경됨");
|
||||
|
||||
// 샘플 데이터 설정 (Dictionary 방식)
|
||||
SetSampleData();
|
||||
|
||||
// 하단 버튼 영역 생성
|
||||
CreateButtons(root);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary 기반으로 샘플 데이터를 설정합니다.
|
||||
/// </summary>
|
||||
private void SetSampleData()
|
||||
{
|
||||
var listDict = new List<Dictionary<string, string>>
|
||||
{
|
||||
new() { ["order"] = "0", ["active"] = "True", ["text"] = "온도" },
|
||||
new() { ["order"] = "1", ["active"] = "False", ["text"] = "습도" },
|
||||
new() { ["order"] = "2", ["active"] = "True", ["text"] = "압력" },
|
||||
new() { ["order"] = "3", ["active"] = "True", ["text"] = "풍속" },
|
||||
new() { ["order"] = "4", ["active"] = "False", ["text"] = "조도" },
|
||||
};
|
||||
_reordableList.SetData(listDict);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 테스트 버튼들을 생성합니다.
|
||||
/// </summary>
|
||||
private void CreateButtons(VisualElement root)
|
||||
{
|
||||
var buttonContainer = new VisualElement();
|
||||
buttonContainer.style.flexDirection = FlexDirection.Row;
|
||||
buttonContainer.style.justifyContent = Justify.Center;
|
||||
buttonContainer.style.paddingTop = 8;
|
||||
buttonContainer.style.paddingBottom = 8;
|
||||
|
||||
// ToDictionary 버튼
|
||||
var toDictBtn = new UTKButton("ToDictionary", variant: UTKButton.ButtonVariant.Primary);
|
||||
toDictBtn.OnClicked += OnToDictionaryClicked;
|
||||
toDictBtn.style.marginRight = 4;
|
||||
buttonContainer.Add(toDictBtn);
|
||||
|
||||
// 데이터 리셋 버튼
|
||||
var resetBtn = new UTKButton("리셋", variant: UTKButton.ButtonVariant.Normal);
|
||||
resetBtn.OnClicked += () => SetSampleData();
|
||||
resetBtn.style.marginRight = 4;
|
||||
buttonContainer.Add(resetBtn);
|
||||
|
||||
// 아이템 추가 버튼
|
||||
var addBtn = new UTKButton("추가", variant: UTKButton.ButtonVariant.OutlinePrimary);
|
||||
addBtn.OnClicked += OnAddItemClicked;
|
||||
buttonContainer.Add(addBtn);
|
||||
|
||||
root.Add(buttonContainer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ToDictionary를 호출하여 현재 데이터를 콘솔에 출력합니다.
|
||||
/// </summary>
|
||||
private void OnToDictionaryClicked()
|
||||
{
|
||||
var result = _reordableList.ToDictionary();
|
||||
Debug.Log($"[Sample] ToDictionary 결과 ({result.Count}건):");
|
||||
foreach (var dict in result)
|
||||
{
|
||||
Debug.Log($" order={dict["order"]}, active={dict["active"]}, text={dict["text"]}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 새 아이템을 추가합니다.
|
||||
/// </summary>
|
||||
private void OnAddItemClicked()
|
||||
{
|
||||
var currentData = _reordableList.ToDictionary();
|
||||
var newIndex = currentData.Count;
|
||||
currentData.Add(new Dictionary<string, string>
|
||||
{
|
||||
["order"] = newIndex.ToString(),
|
||||
["active"] = "True",
|
||||
["text"] = $"항목 {newIndex}"
|
||||
});
|
||||
_reordableList.SetData(currentData);
|
||||
Debug.Log($"[Sample] 아이템 추가됨 (총 {currentData.Count}건)");
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_reordableList?.Dispose();
|
||||
}
|
||||
}
|
||||
2
Assets/Sample/UIToolkit/UTKReordableListSample.cs.meta
Normal file
2
Assets/Sample/UIToolkit/UTKReordableListSample.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4274ed098fc4bf048bb92836e8982c8f
|
||||
6
Assets/Sample/UIToolkit/UTKReordableListUXML.uxml
Normal file
6
Assets/Sample/UIToolkit/UTKReordableListUXML.uxml
Normal file
@@ -0,0 +1,6 @@
|
||||
<UXML xmlns="UnityEngine.UIElements" xmlns:utk="UVC.UIToolkit" editor-extension-mode="False">
|
||||
<VisualElement style="width: 100%; height: 100%;">
|
||||
<utk:UTKReordableList name="window" style="width: 300px; height: 200px;" />
|
||||
<utk:UTKToggle name="toggle" label="테마 변경" style="position: absolute; top: 10px; right: 10px;" />
|
||||
</VisualElement>
|
||||
</UXML>
|
||||
10
Assets/Sample/UIToolkit/UTKReordableListUXML.uxml.meta
Normal file
10
Assets/Sample/UIToolkit/UTKReordableListUXML.uxml.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4bb0d1734d5c1b647ae0ffdb7879a92a
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@@ -371,14 +371,11 @@ public async UniTask SaveDataAsync()
|
||||
}
|
||||
|
||||
SetCodeSamples(root,
|
||||
csharpCode: @"// 1. 초기화 (앱 시작 시 한 번)
|
||||
UTKTooltipManager.Instance.Initialize(rootVisualElement);
|
||||
|
||||
// 2. 버튼에 툴팁 연결
|
||||
csharpCode: @"// 1. 버튼에 툴팁 연결
|
||||
var saveButton = new UTKButton("""", UTKMaterialIcons.Save);
|
||||
UTKTooltipManager.Instance.AttachTooltip(saveButton, ""저장 (Ctrl+S)"");
|
||||
|
||||
// 3. 다국어 키로 툴팁 연결
|
||||
// 2. 다국어 키로 툴팁 연결
|
||||
UTKTooltipManager.Instance.AttachTooltip(settingsButton, ""tooltip_settings"");
|
||||
|
||||
// 4. 아이콘 버튼에 툴팁
|
||||
|
||||
@@ -205,7 +205,6 @@ public partial class UTKStyleGuideSample : MonoBehaviour
|
||||
}
|
||||
|
||||
UTKThemeManager.Instance.SetTheme(initialTheme);
|
||||
UTKTooltipManager.Instance.Initialize(_root);
|
||||
|
||||
CreateUI();
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace UVC.Sample.UIToolkit
|
||||
/// </summary>
|
||||
private void CreateHorizontalToolBar(VisualElement parent)
|
||||
{
|
||||
var label = new Label("Horizontal Toolbar");
|
||||
var label = new Label("Horizontal Toolbar");
|
||||
label.style.fontSize = 14;
|
||||
label.style.marginTop = 8;
|
||||
label.style.marginBottom = 4;
|
||||
@@ -93,30 +93,30 @@ namespace UVC.Sample.UIToolkit
|
||||
_horizontalModel = new UTKToolBarModel();
|
||||
|
||||
// Standard
|
||||
_horizontalModel.AddStandardButton("저장", UTKMaterialIcons.Save, new DebugLogCommand("저장"), "파일 저장");
|
||||
_horizontalModel.AddStandardButton("실행 취소", UTKMaterialIcons.Undo, new DebugLogCommand("실행 취소"));
|
||||
_horizontalModel.AddStandardButton("다시 실행", UTKMaterialIcons.Redo, new DebugLogCommand("다시 실행"));
|
||||
_horizontalModel.AddStandardButton("", UTKMaterialIcons.Save, new DebugLogCommand("저장"), "파일 저장");
|
||||
_horizontalModel.AddStandardButton("", UTKMaterialIcons.Undo, new DebugLogCommand("실행 취소"));
|
||||
_horizontalModel.AddStandardButton("", UTKMaterialIcons.Redo, new DebugLogCommand("다시 실행"));
|
||||
|
||||
_horizontalModel.AddSeparator();
|
||||
|
||||
// Toggle
|
||||
_horizontalModel.AddToggleButton("그리드", false, UTKMaterialIcons.GridOn, UTKMaterialIcons.GridOff, tooltip: "그리드 표시/숨김");
|
||||
_horizontalModel.AddToggleButton("스냅", false, UTKMaterialIcons.FilterCenterFocus, UTKMaterialIcons.CenterFocusWeak, tooltip: "스냅 활성화");
|
||||
_horizontalModel.AddToggleButton("", false, UTKMaterialIcons.GridOn, UTKMaterialIcons.GridOff, tooltip: "그리드 표시/숨김");
|
||||
_horizontalModel.AddToggleButton("", false, UTKMaterialIcons.FilterCenterFocus, UTKMaterialIcons.CenterFocusWeak, tooltip: "스냅 활성화");
|
||||
|
||||
_horizontalModel.AddSeparator();
|
||||
|
||||
// Radio
|
||||
_horizontalModel.AddRadioButton("tool", "선택", true, UTKMaterialIcons.NearMe, tooltip: "선택 도구");
|
||||
_horizontalModel.AddRadioButton("tool", "이동", false, UTKMaterialIcons.OpenWith, tooltip: "이동 도구");
|
||||
_horizontalModel.AddRadioButton("tool", "회전", false, UTKMaterialIcons.Refresh, tooltip: "회전 도구");
|
||||
_horizontalModel.AddRadioButton("tool", "", true, UTKMaterialIcons.NearMe, tooltip: "선택 도구");
|
||||
_horizontalModel.AddRadioButton("tool", "", false, UTKMaterialIcons.OpenWith, tooltip: "이동 도구");
|
||||
_horizontalModel.AddRadioButton("tool", "", false, UTKMaterialIcons.Refresh, tooltip: "회전 도구");
|
||||
|
||||
_horizontalModel.AddSeparator();
|
||||
|
||||
// Expandable
|
||||
var shapeBtn = _horizontalModel.AddExpandableButton("도형", UTKMaterialIcons.Category, tooltip: "도형 추가", updateIconOnSelection: true);
|
||||
shapeBtn.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "사각형", IconPath = UTKMaterialIcons.CropSquare, UseMaterialIcon = true });
|
||||
shapeBtn.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "원형", IconPath = UTKMaterialIcons.Circle, UseMaterialIcon = true });
|
||||
shapeBtn.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "삼각형", IconPath = UTKMaterialIcons.ChangeHistory, UseMaterialIcon = true });
|
||||
var shapeBtn = _horizontalModel.AddExpandableButton("", UTKMaterialIcons.Category, tooltip: "도형 추가", updateIconOnSelection: true);
|
||||
shapeBtn.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "", IconPath = UTKMaterialIcons.CropSquare, UseMaterialIcon = true, Tooltip = "사각형 추가" });
|
||||
shapeBtn.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "", IconPath = UTKMaterialIcons.Circle, UseMaterialIcon = true, Tooltip = "원형 추가" });
|
||||
shapeBtn.SubButtons.Add(new UTKToolBarStandardButtonData { Text = "", IconPath = UTKMaterialIcons.ChangeHistory, UseMaterialIcon = true, Tooltip = "삼각형 추가" });
|
||||
|
||||
_horizontalToolBar = new UTKToolBar();
|
||||
_horizontalToolBar.Orientation = UTKToolBarOrientation.Horizontal;
|
||||
|
||||
@@ -10,17 +10,13 @@ namespace UVC.UIToolkit
|
||||
{
|
||||
/// <summary>
|
||||
/// VisualElement에 툴팁을 설정합니다.
|
||||
/// UTKTooltipManager가 초기화되어 있어야 합니다.
|
||||
/// </summary>
|
||||
/// <param name="element">대상 요소</param>
|
||||
/// <param name="tooltip">툴팁 텍스트 또는 다국어 키</param>
|
||||
/// <returns>체이닝을 위한 원본 요소</returns>
|
||||
public static T SetTooltip<T>(this T element, string tooltip) where T : VisualElement
|
||||
{
|
||||
if (UTKTooltipManager.Instance.IsInitialized)
|
||||
{
|
||||
UTKTooltipManager.Instance.AttachTooltip(element, tooltip);
|
||||
}
|
||||
UTKTooltipManager.Instance.AttachTooltip(element, tooltip);
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -31,10 +27,7 @@ namespace UVC.UIToolkit
|
||||
/// <returns>체이닝을 위한 원본 요소</returns>
|
||||
public static T ClearTooltip<T>(this T element) where T : VisualElement
|
||||
{
|
||||
if (UTKTooltipManager.Instance.IsInitialized)
|
||||
{
|
||||
UTKTooltipManager.Instance.DetachTooltip(element);
|
||||
}
|
||||
UTKTooltipManager.Instance.DetachTooltip(element);
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -46,10 +39,7 @@ namespace UVC.UIToolkit
|
||||
/// <returns>체이닝을 위한 원본 요소</returns>
|
||||
public static T UpdateTooltip<T>(this T element, string tooltip) where T : VisualElement
|
||||
{
|
||||
if (UTKTooltipManager.Instance.IsInitialized)
|
||||
{
|
||||
UTKTooltipManager.Instance.UpdateTooltip(element, tooltip);
|
||||
}
|
||||
UTKTooltipManager.Instance.UpdateTooltip(element, tooltip);
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace UVC.UIToolkit
|
||||
/// <summary>
|
||||
/// UIToolkit 기반 툴팁 매니저.
|
||||
/// VisualElement에 마우스 오버 시 툴팁을 표시하는 싱글톤 관리자입니다.
|
||||
/// panel.visualTree를 사용하여 모든 UI 위에 툴팁을 표시합니다.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para><b>Tooltip(툴팁)이란?</b></para>
|
||||
@@ -25,7 +26,7 @@ namespace UVC.UIToolkit
|
||||
/// <para>
|
||||
/// UTKTooltipManager는 싱글톤으로 구현되어 있습니다.
|
||||
/// <c>UTKTooltipManager.Instance</c>로 접근하며, 앱 전체에서 하나의 툴팁 UI를 공유합니다.
|
||||
/// 사용 전에 반드시 <c>Initialize(root)</c>를 호출해야 합니다.
|
||||
/// panel.visualTree를 사용하므로 별도 Initialize 호출이 필요 없습니다.
|
||||
/// </para>
|
||||
///
|
||||
/// <para><b>주요 기능:</b></para>
|
||||
@@ -38,7 +39,6 @@ namespace UVC.UIToolkit
|
||||
///
|
||||
/// <para><b>주요 메서드:</b></para>
|
||||
/// <list type="bullet">
|
||||
/// <item><description><c>Initialize(root)</c> - 초기화 (루트 요소 지정)</description></item>
|
||||
/// <item><description><c>AttachTooltip(element, text)</c> - 요소에 툴팁 연결</description></item>
|
||||
/// <item><description><c>DetachTooltip(element)</c> - 툴팁 제거</description></item>
|
||||
/// <item><description><c>Show(text, position)</c> - 즉시 표시</description></item>
|
||||
@@ -56,20 +56,17 @@ namespace UVC.UIToolkit
|
||||
/// <example>
|
||||
/// <para><b>C# 코드에서 사용:</b></para>
|
||||
/// <code>
|
||||
/// // 1. 초기화 (앱 시작 시 한 번)
|
||||
/// UTKTooltipManager.Instance.Initialize(rootVisualElement);
|
||||
///
|
||||
/// // 2. 버튼에 툴팁 연결
|
||||
/// // 1. 버튼에 툴팁 연결 (Initialize 불필요)
|
||||
/// var saveButton = new UTKButton("", UTKMaterialIcons.Save);
|
||||
/// UTKTooltipManager.Instance.AttachTooltip(saveButton, "저장 (Ctrl+S)");
|
||||
///
|
||||
/// // 3. 다국어 키로 툴팁 연결
|
||||
/// // 2. 다국어 키로 툴팁 연결
|
||||
/// UTKTooltipManager.Instance.AttachTooltip(settingsButton, "tooltip_settings");
|
||||
///
|
||||
/// // 4. 툴팁 업데이트
|
||||
/// // 3. 툴팁 업데이트
|
||||
/// UTKTooltipManager.Instance.UpdateTooltip(button, "새로운 설명");
|
||||
///
|
||||
/// // 5. 툴팁 제거
|
||||
/// // 4. 툴팁 제거
|
||||
/// UTKTooltipManager.Instance.DetachTooltip(button);
|
||||
/// </code>
|
||||
/// </example>
|
||||
@@ -90,12 +87,11 @@ namespace UVC.UIToolkit
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private VisualElement? _root;
|
||||
private VisualElement? _tooltipContainer;
|
||||
private Label? _tooltipLabel;
|
||||
private bool _isInitialized;
|
||||
private bool _isVisible;
|
||||
private bool _disposed;
|
||||
private StyleSheet? _loadedUss;
|
||||
|
||||
private CancellationTokenSource? _showDelayCts;
|
||||
private readonly Dictionary<VisualElement, string> _tooltipRegistry = new();
|
||||
@@ -105,24 +101,19 @@ namespace UVC.UIToolkit
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public bool IsInitialized => _isInitialized;
|
||||
public bool IsVisible => _isVisible;
|
||||
#endregion
|
||||
|
||||
#region Initialization
|
||||
/// <summary>
|
||||
/// 툴팁 매니저를 초기화합니다.
|
||||
/// 툴팁 UI를 생성합니다 (아직 visual tree에 추가하지 않음).
|
||||
/// </summary>
|
||||
/// <param name="root">VisualElement 트리의 루트</param>
|
||||
public void Initialize(VisualElement root)
|
||||
private void EnsureTooltipUI()
|
||||
{
|
||||
if (_isInitialized)
|
||||
{
|
||||
Debug.LogWarning("[UTKTooltipManager] Already initialized.");
|
||||
return;
|
||||
}
|
||||
if (_tooltipContainer != null) return;
|
||||
|
||||
_root = root;
|
||||
// USS 로드
|
||||
_loadedUss = Resources.Load<StyleSheet>(USS_PATH);
|
||||
|
||||
// UXML 로드 시도
|
||||
var visualTree = Resources.Load<VisualTreeAsset>(UXML_PATH);
|
||||
@@ -143,13 +134,11 @@ namespace UVC.UIToolkit
|
||||
_tooltipContainer.style.position = Position.Absolute;
|
||||
_tooltipContainer.style.display = DisplayStyle.None;
|
||||
_tooltipContainer.pickingMode = PickingMode.Ignore;
|
||||
_root.Add(_tooltipContainer);
|
||||
}
|
||||
|
||||
// 테마 변경 이벤트 구독
|
||||
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -174,16 +163,6 @@ namespace UVC.UIToolkit
|
||||
pickingMode = PickingMode.Ignore
|
||||
};
|
||||
|
||||
// 테마 적용
|
||||
UTKThemeManager.Instance.ApplyThemeToElement(_tooltipContainer);
|
||||
|
||||
// USS 스타일시트 로드
|
||||
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||
if (uss != null)
|
||||
{
|
||||
_tooltipContainer.styleSheets.Add(uss);
|
||||
}
|
||||
|
||||
// USS 클래스로 스타일 적용
|
||||
_tooltipContainer.AddToClassList("utk-tooltip-container");
|
||||
|
||||
@@ -196,6 +175,33 @@ namespace UVC.UIToolkit
|
||||
|
||||
_tooltipContainer.Add(_tooltipLabel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 툴팁 컨테이너를 대상 요소의 panel.visualTree에 추가합니다.
|
||||
/// </summary>
|
||||
/// <param name="element">대상 요소 (panel 접근용)</param>
|
||||
private void AttachToPanel(VisualElement element)
|
||||
{
|
||||
if (_tooltipContainer == null || element.panel == null) return;
|
||||
|
||||
var visualTree = element.panel.visualTree;
|
||||
|
||||
// 이미 해당 visualTree에 추가되어 있으면 스킵
|
||||
if (_tooltipContainer.parent == visualTree) return;
|
||||
|
||||
// 다른 곳에 붙어 있으면 제거
|
||||
_tooltipContainer.RemoveFromHierarchy();
|
||||
|
||||
// panel.visualTree에 추가
|
||||
visualTree.Add(_tooltipContainer);
|
||||
|
||||
// 테마/USS 재적용
|
||||
UTKThemeManager.Instance.ApplyThemeToElement(_tooltipContainer);
|
||||
if (_loadedUss != null)
|
||||
{
|
||||
_tooltipContainer.styleSheets.Add(_loadedUss);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
@@ -203,10 +209,10 @@ namespace UVC.UIToolkit
|
||||
/// 툴팁을 즉시 표시합니다.
|
||||
/// </summary>
|
||||
/// <param name="text">표시할 텍스트</param>
|
||||
/// <param name="position">화면 좌표</param>
|
||||
/// <param name="position">월드 좌표</param>
|
||||
public void Show(string text, Vector2 position)
|
||||
{
|
||||
if (!_isInitialized || _tooltipContainer == null || _tooltipLabel == null)
|
||||
if (_tooltipContainer == null || _tooltipLabel == null)
|
||||
return;
|
||||
|
||||
// 다국어 처리
|
||||
@@ -230,7 +236,7 @@ namespace UVC.UIToolkit
|
||||
/// 지연 후 툴팁을 표시합니다.
|
||||
/// </summary>
|
||||
/// <param name="text">표시할 텍스트</param>
|
||||
/// <param name="position">화면 좌표</param>
|
||||
/// <param name="position">월드 좌표</param>
|
||||
/// <param name="delayMs">지연 시간 (밀리초)</param>
|
||||
public async UniTaskVoid ShowDelayed(string text, Vector2 position, int delayMs = SHOW_DELAY_MS)
|
||||
{
|
||||
@@ -275,21 +281,22 @@ namespace UVC.UIToolkit
|
||||
// 기존 등록 제거
|
||||
DetachTooltip(element);
|
||||
|
||||
// 툴팁 UI 생성 보장
|
||||
EnsureTooltipUI();
|
||||
|
||||
_tooltipRegistry[element] = tooltip;
|
||||
|
||||
// 이벤트 콜백 생성 및 등록
|
||||
// 참고: evt.position은 로컬 좌표이므로, 패널 기준 좌표로 변환 필요
|
||||
EventCallback<PointerEnterEvent> enterCallback = evt =>
|
||||
{
|
||||
if (_tooltipRegistry.TryGetValue(element, out var text))
|
||||
{
|
||||
// 로컬 좌표를 root 좌표로 변환
|
||||
var rootPosition = element.LocalToWorld(evt.localPosition);
|
||||
if (_root != null)
|
||||
{
|
||||
rootPosition = _root.WorldToLocal(rootPosition);
|
||||
}
|
||||
ShowDelayed(text, rootPosition).Forget();
|
||||
// panel.visualTree에 툴팁 컨테이너 추가
|
||||
AttachToPanel(element);
|
||||
|
||||
// worldBound 기준 좌표 사용
|
||||
var worldPos = element.LocalToWorld(evt.localPosition);
|
||||
ShowDelayed(text, worldPos).Forget();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -299,13 +306,9 @@ namespace UVC.UIToolkit
|
||||
{
|
||||
if (_isVisible)
|
||||
{
|
||||
// 로컬 좌표를 root 좌표로 변환
|
||||
var rootPosition = element.LocalToWorld(evt.localPosition);
|
||||
if (_root != null)
|
||||
{
|
||||
rootPosition = _root.WorldToLocal(rootPosition);
|
||||
}
|
||||
AdjustPosition(rootPosition);
|
||||
// worldBound 기준 좌표 사용
|
||||
var worldPos = element.LocalToWorld(evt.localPosition);
|
||||
AdjustPosition(worldPos);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -406,37 +409,39 @@ namespace UVC.UIToolkit
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 화면 경계 내에서 위치 조정
|
||||
/// 화면 경계 내에서 위치 조정 (월드 좌표 기준)
|
||||
/// </summary>
|
||||
private void AdjustPosition(Vector2 mousePosition)
|
||||
private void AdjustPosition(Vector2 worldPosition)
|
||||
{
|
||||
if (_tooltipContainer == null || _root == null)
|
||||
if (_tooltipContainer == null || _tooltipContainer.panel == null)
|
||||
return;
|
||||
|
||||
var panelRoot = _tooltipContainer.panel.visualTree;
|
||||
|
||||
var tooltipSize = new Vector2(
|
||||
_tooltipContainer.resolvedStyle.width,
|
||||
_tooltipContainer.resolvedStyle.height
|
||||
);
|
||||
|
||||
var rootSize = new Vector2(
|
||||
_root.resolvedStyle.width,
|
||||
_root.resolvedStyle.height
|
||||
var panelSize = new Vector2(
|
||||
panelRoot.resolvedStyle.width,
|
||||
panelRoot.resolvedStyle.height
|
||||
);
|
||||
|
||||
// 기본 위치: 마우스 오른쪽 아래
|
||||
float x = mousePosition.x + POSITION_OFFSET;
|
||||
float y = mousePosition.y + POSITION_OFFSET;
|
||||
float x = worldPosition.x + POSITION_OFFSET;
|
||||
float y = worldPosition.y + POSITION_OFFSET;
|
||||
|
||||
// 오른쪽 경계 체크
|
||||
if (x + tooltipSize.x > rootSize.x)
|
||||
if (x + tooltipSize.x > panelSize.x)
|
||||
{
|
||||
x = mousePosition.x - tooltipSize.x - POSITION_OFFSET;
|
||||
x = worldPosition.x - tooltipSize.x - POSITION_OFFSET;
|
||||
}
|
||||
|
||||
// 아래쪽 경계 체크
|
||||
if (y + tooltipSize.y > rootSize.y)
|
||||
if (y + tooltipSize.y > panelSize.y)
|
||||
{
|
||||
y = mousePosition.y - tooltipSize.y - POSITION_OFFSET;
|
||||
y = worldPosition.y - tooltipSize.y - POSITION_OFFSET;
|
||||
}
|
||||
|
||||
// 왼쪽/위쪽 경계 체크
|
||||
@@ -476,9 +481,7 @@ namespace UVC.UIToolkit
|
||||
_tooltipContainer?.RemoveFromHierarchy();
|
||||
_tooltipContainer = null;
|
||||
_tooltipLabel = null;
|
||||
_root = null;
|
||||
|
||||
_isInitialized = false;
|
||||
_isVisible = false;
|
||||
_instance = null;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UVC.Extention;
|
||||
|
||||
namespace UVC.UIToolkit
|
||||
{
|
||||
@@ -233,6 +234,7 @@ namespace UVC.UIToolkit
|
||||
if (_label != null)
|
||||
{
|
||||
_label.selection.isSelectable = value;
|
||||
_label.pickingMode = value ? PickingMode.Position : PickingMode.Ignore;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -456,7 +458,7 @@ namespace UVC.UIToolkit
|
||||
{
|
||||
AddToClassList("utk-label");
|
||||
|
||||
_label = new Label { name = "label" };
|
||||
_label = new Label { name = "label", pickingMode = PickingMode.Ignore };
|
||||
_label.AddToClassList("utk-label__text");
|
||||
Add(_label);
|
||||
|
||||
@@ -621,14 +623,14 @@ namespace UVC.UIToolkit
|
||||
// 아이콘과 텍스트 사이의 간격을 적용
|
||||
if (_iconLabel != null)
|
||||
{
|
||||
_iconLabel.style.marginRight = _iconPosition == IconPosition.Left ? _gap : 0;
|
||||
_iconLabel.style.marginLeft = _iconPosition == IconPosition.Right ? _gap : 0;
|
||||
_iconLabel.style.marginRight = _iconPosition == IconPosition.Left ? (_text.IsNullOrEmpty() ? 0 : _gap) : 0;
|
||||
_iconLabel.style.marginLeft = _iconPosition == IconPosition.Right ? (_text.IsNullOrEmpty() ? 0 : _gap) : 0;
|
||||
}
|
||||
|
||||
if (_imageIcon != null)
|
||||
{
|
||||
_imageIcon.style.marginRight = _iconPosition == IconPosition.Left ? _gap : 0;
|
||||
_imageIcon.style.marginLeft = _iconPosition == IconPosition.Right ? _gap : 0;
|
||||
_imageIcon.style.marginRight = _iconPosition == IconPosition.Left ? (_text.IsNullOrEmpty() ? 0 : _gap) : 0;
|
||||
_imageIcon.style.marginLeft = _iconPosition == IconPosition.Right ? (_text.IsNullOrEmpty() ? 0 : _gap) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -669,7 +671,7 @@ namespace UVC.UIToolkit
|
||||
_iconLabel.style.display = DisplayStyle.Flex;
|
||||
UTKMaterialIcons.ApplyIconStyle(_iconLabel, fontSize ?? GetEffectiveIconSize());
|
||||
}
|
||||
|
||||
if(_text.IsNullOrEmpty()) TextAlignment = TextAlign.Center; // 텍스트가 없는 경우 아이콘 중앙 정렬
|
||||
EnableInClassList("utk-label--has-icon", true);
|
||||
UpdateIconPosition();
|
||||
UpdateGap();
|
||||
@@ -693,6 +695,7 @@ namespace UVC.UIToolkit
|
||||
await UTKMaterialIcons.ApplyIconStyleAsync(_iconLabel, ct, fontSize ?? GetEffectiveIconSize());
|
||||
}
|
||||
|
||||
if(_text.IsNullOrEmpty()) TextAlignment = TextAlign.Center; // 텍스트가 없는 경우 아이콘 중앙 정렬
|
||||
EnableInClassList("utk-label--has-icon", true);
|
||||
UpdateIconPosition();
|
||||
UpdateGap();
|
||||
@@ -816,6 +819,7 @@ namespace UVC.UIToolkit
|
||||
_imageIcon.style.backgroundImage = new StyleBackground(texture);
|
||||
_imageIcon.style.display = DisplayStyle.Flex;
|
||||
|
||||
if(_text.IsNullOrEmpty()) TextAlignment = TextAlign.Center; // 텍스트가 없는 경우 아이콘 중앙 정렬
|
||||
EnableInClassList("utk-label--has-icon", true);
|
||||
UpdateIconPosition();
|
||||
UpdateGap();
|
||||
|
||||
@@ -874,7 +874,8 @@ namespace UVC.UIToolkit
|
||||
|
||||
title = new UTKLabel();
|
||||
title.AddToClassList("utk-property-group__title");
|
||||
|
||||
title.Size = UTKLabel.LabelSize.Label2;
|
||||
title.IsBold = true;
|
||||
// count = new UTKLabel();
|
||||
// count.AddToClassList("utk-property-group__count");
|
||||
|
||||
@@ -887,8 +888,7 @@ namespace UVC.UIToolkit
|
||||
// 데이터 바인딩
|
||||
expandIcon.SetMaterialIcon(group.IsExpanded ? UTKMaterialIcons.ExpandMore : UTKMaterialIcons.ChevronRight, 16);
|
||||
title.Text = group.GroupName;
|
||||
title.Size = UTKLabel.LabelSize.Label1;
|
||||
title.IsBold = true;
|
||||
|
||||
// count.Text = $"({group.ItemCount})";
|
||||
// count.Variant = UTKLabel.LabelVariant.Secondary;
|
||||
|
||||
|
||||
@@ -90,11 +90,32 @@ namespace UVC.UIToolkit
|
||||
_listView.selectionType = SelectionType.Single;
|
||||
_listView.reorderable = true;
|
||||
_listView.reorderMode = ListViewReorderMode.Animated;
|
||||
_listView.selectionType = SelectionType.None; // 선택 비활성화 (체크박스 사용)
|
||||
_listView.itemIndexChanged += OnItemIndexChanged;
|
||||
|
||||
// Unity 내장 reorderable-handle 숨김 (CSS 선택자가 매칭되지 않는 경우 대비)
|
||||
_listView.RegisterCallback<AttachToPanelEvent>(_ =>
|
||||
{
|
||||
_listView.schedule.Execute(() => HideBuiltInHandles()).ExecuteLater(50);
|
||||
});
|
||||
|
||||
Add(_listView);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unity ListView 내장 드래그 핸들을 숨깁니다.
|
||||
/// 커스텀 드래그 핸들(DragIndicator 아이콘)을 사용하므로 내장 핸들은 불필요합니다.
|
||||
/// </summary>
|
||||
private void HideBuiltInHandles()
|
||||
{
|
||||
if (_listView == null) return;
|
||||
_listView.Query(className: "unity-list-view__reorderable-handle").ForEach(el =>
|
||||
{
|
||||
el.style.display = DisplayStyle.None;
|
||||
el.style.width = 0;
|
||||
});
|
||||
}
|
||||
|
||||
private void SubscribeToThemeChanges()
|
||||
{
|
||||
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||
@@ -137,9 +158,9 @@ namespace UVC.UIToolkit
|
||||
root.styleSheets.Add(_itemStyleSheet);
|
||||
|
||||
// 드래그 핸들 아이콘 설정
|
||||
var handle = root.Q<Label>("drag-handle");
|
||||
var handle = root.Q<UTKLabel>("drag-handle");
|
||||
if (handle != null)
|
||||
handle.text = UTKMaterialIcons.DragIndicator;
|
||||
handle.SetMaterialIcon(UTKMaterialIcons.DragIndicator);
|
||||
|
||||
return root;
|
||||
}
|
||||
@@ -156,7 +177,7 @@ namespace UVC.UIToolkit
|
||||
container.style.alignItems = Align.Center;
|
||||
container.style.minHeight = ITEM_HEIGHT;
|
||||
|
||||
var handle = new Label(UTKMaterialIcons.DragIndicator);
|
||||
var handle = new UTKLabel("", UTKMaterialIcons.DragIndicator);
|
||||
handle.name = "drag-handle";
|
||||
handle.AddToClassList("reordable-list-item__drag-handle");
|
||||
container.Add(handle);
|
||||
@@ -178,6 +199,9 @@ namespace UVC.UIToolkit
|
||||
{
|
||||
if (index < 0 || index >= _items.Count) return;
|
||||
|
||||
// ListView가 makeItem 반환 후 inline flex-grow:0을 강제하므로 bindItem에서 덮어씀
|
||||
element.style.flexGrow = 1;
|
||||
|
||||
var data = _items[index];
|
||||
|
||||
// 요소 참조
|
||||
|
||||
@@ -15,10 +15,10 @@ namespace UVC.UIToolkit
|
||||
#region Fields
|
||||
|
||||
/// <summary>아이콘 요소 (Material Icon Label 또는 Image)</summary>
|
||||
protected Label? _iconLabel;
|
||||
protected UTKLabel? _iconLabel;
|
||||
|
||||
/// <summary>텍스트 라벨</summary>
|
||||
protected Label? _textLabel;
|
||||
protected UTKLabel? _textLabel;
|
||||
|
||||
/// <summary>루트 버튼 요소</summary>
|
||||
protected VisualElement? _rootButton;
|
||||
@@ -103,12 +103,13 @@ namespace UVC.UIToolkit
|
||||
{
|
||||
var root = asset.Instantiate();
|
||||
_rootButton = root.Q<VisualElement>("button-root");
|
||||
_iconLabel = root.Q<Label>("icon");
|
||||
_textLabel = root.Q<Label>("label");
|
||||
_iconLabel = root.Q<UTKLabel>("icon");
|
||||
_textLabel = root.Q<UTKLabel>("label");
|
||||
_textLabel.Size = UTKLabel.LabelSize.Caption; // UXML에서 기본 크기를 설정하므로 코드에서 다시 지정
|
||||
|
||||
// TemplateContainer가 아이콘 정렬을 방해하지 않도록 설정
|
||||
root.style.flexGrow = 1;
|
||||
root.style.alignItems = Align.Center;
|
||||
root.style.alignItems = Align.Stretch;
|
||||
root.style.justifyContent = Justify.Center;
|
||||
|
||||
Add(root);
|
||||
@@ -129,12 +130,13 @@ namespace UVC.UIToolkit
|
||||
_rootButton = new VisualElement();
|
||||
_rootButton.AddToClassList("utk-toolbar-btn");
|
||||
|
||||
_iconLabel = new Label();
|
||||
_iconLabel = new UTKLabel();
|
||||
_iconLabel.AddToClassList("utk-toolbar-btn__icon");
|
||||
_rootButton.Add(_iconLabel);
|
||||
|
||||
_textLabel = new Label();
|
||||
_textLabel = new UTKLabel();
|
||||
_textLabel.AddToClassList("utk-toolbar-btn__label");
|
||||
_textLabel.Size = UTKLabel.LabelSize.Caption;
|
||||
_rootButton.Add(_textLabel);
|
||||
|
||||
Add(_rootButton);
|
||||
@@ -164,6 +166,7 @@ namespace UVC.UIToolkit
|
||||
UpdateIcon(_data.IconPath, _data.UseMaterialIcon);
|
||||
UpdateText(_data.Text);
|
||||
UpdateEnabled(_data.IsEnabled);
|
||||
UpdateTooltip(_data.Tooltip);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -216,29 +219,15 @@ namespace UVC.UIToolkit
|
||||
|
||||
if (useMaterialIcon)
|
||||
{
|
||||
// Material Icon (폰트 기반)
|
||||
// Material Icon (폰트 기반) - UTKLabel의 SetMaterialIcon 사용
|
||||
_iconLabel.RemoveFromClassList("utk-toolbar-btn__icon--image");
|
||||
_iconLabel.text = iconPath;
|
||||
_iconLabel.style.backgroundImage = StyleKeyword.None;
|
||||
_iconLabel.SetMaterialIcon(iconPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 이미지 아이콘
|
||||
// 이미지 아이콘 - UTKLabel의 SetImageIcon 사용
|
||||
_iconLabel.AddToClassList("utk-toolbar-btn__icon--image");
|
||||
_iconLabel.text = "";
|
||||
var sprite = Resources.Load<Sprite>(iconPath);
|
||||
if (sprite != null)
|
||||
{
|
||||
_iconLabel.style.backgroundImage = new StyleBackground(sprite);
|
||||
}
|
||||
else
|
||||
{
|
||||
var texture = Resources.Load<Texture2D>(iconPath);
|
||||
if (texture != null)
|
||||
{
|
||||
_iconLabel.style.backgroundImage = new StyleBackground(texture);
|
||||
}
|
||||
}
|
||||
_iconLabel.SetImageIcon(iconPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +239,26 @@ namespace UVC.UIToolkit
|
||||
{
|
||||
if (_textLabel != null)
|
||||
{
|
||||
_textLabel.text = text;
|
||||
_textLabel.Text = text;
|
||||
_textLabel.style.display = string.IsNullOrEmpty(text) ? DisplayStyle.None : DisplayStyle.Flex;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 툴팁을 업데이트합니다.
|
||||
/// </summary>
|
||||
/// <param name="tooltipText">툴팁 텍스트</param>
|
||||
protected void UpdateTooltip(string? tooltipText)
|
||||
{
|
||||
if (_rootButton == null) return;
|
||||
|
||||
if (string.IsNullOrEmpty(tooltipText))
|
||||
{
|
||||
UTKTooltipManager.Instance.DetachTooltip(_rootButton);
|
||||
}
|
||||
else
|
||||
{
|
||||
UTKTooltipManager.Instance.UpdateTooltip(_rootButton, tooltipText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,6 +290,7 @@ namespace UVC.UIToolkit
|
||||
UpdateIcon(_data.IconPath, _data.UseMaterialIcon);
|
||||
UpdateText(_data.Text);
|
||||
UpdateEnabled(_data.IsEnabled);
|
||||
UpdateTooltip(_data.Tooltip);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -354,6 +363,12 @@ namespace UVC.UIToolkit
|
||||
// 데이터 바인딩 해제
|
||||
UnbindData();
|
||||
|
||||
// 툴팁 해제
|
||||
if (_rootButton != null)
|
||||
{
|
||||
UTKTooltipManager.Instance.DetachTooltip(_rootButton);
|
||||
}
|
||||
|
||||
// 테마 구독 해제
|
||||
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||
UnregisterCallback<AttachToPanelEvent>(OnAttachToPanelForTheme);
|
||||
|
||||
Reference in New Issue
Block a user