개발 중
This commit is contained in:
@@ -721,10 +721,10 @@ public class testZip : MonoBehaviour
|
|||||||
// Read some file to a byte[] buffer (as an example only).
|
// Read some file to a byte[] buffer (as an example only).
|
||||||
reusableBuffer2a = File.ReadAllBytes(ppath + "/dir1/dir2/dir3/Unity_1.jpg");
|
reusableBuffer2a = File.ReadAllBytes(ppath + "/dir1/dir2/dir3/Unity_1.jpg");
|
||||||
|
|
||||||
// Add a buffer as a first ItemPrefab in the inMemory zip
|
// AddChild a buffer as a first ItemPrefab in the inMemory zip
|
||||||
lzip.inMemoryZipAdd(t2, 9, reusableBuffer2a, "test.jpg");
|
lzip.inMemoryZipAdd(t2, 9, reusableBuffer2a, "test.jpg");
|
||||||
|
|
||||||
// Add a second buffer as the second ItemPrefab.
|
// AddChild a second buffer as the second ItemPrefab.
|
||||||
lzip.inMemoryZipAdd(t2, 9, reusableBuffer2, "directory/test.bmp");
|
lzip.inMemoryZipAdd(t2, 9, reusableBuffer2, "directory/test.bmp");
|
||||||
|
|
||||||
// !!! -> After finishing adding buffer/files in the inMemory zip we must close it <- !!!
|
// !!! -> After finishing adding buffer/files in the inMemory zip we must close it <- !!!
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ internal enum SpeedType
|
|||||||
[SerializeField] private Vector3 m_CentreOfMassOffset;
|
[SerializeField] private Vector3 m_CentreOfMassOffset;
|
||||||
[SerializeField] private float m_MaximumSteerAngle;
|
[SerializeField] private float m_MaximumSteerAngle;
|
||||||
[Range(0, 1)] [SerializeField] private float m_SteerHelper; // 0 is raw physics , 1 the car will grip in the direction it is facing
|
[Range(0, 1)] [SerializeField] private float m_SteerHelper; // 0 is raw physics , 1 the car will grip in the direction it is facing
|
||||||
[Range(0, 1)] [SerializeField] private float m_TractionControl; // 0 is no traction control, 1 is full interference
|
[Range(0, 1)] [SerializeField] private float m_TractionControl; // 0 is no traction treeList, 1 is full interference
|
||||||
[SerializeField] private float m_FullTorqueOverAllWheels;
|
[SerializeField] private float m_FullTorqueOverAllWheels;
|
||||||
[SerializeField] private float m_ReverseTorque;
|
[SerializeField] private float m_ReverseTorque;
|
||||||
[SerializeField] private float m_MaxHandbrakeTorque;
|
[SerializeField] private float m_MaxHandbrakeTorque;
|
||||||
@@ -306,7 +306,7 @@ internal enum SpeedType
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// crude traction control that reduces the power to wheel if the car is wheel spinning too much
|
// crude traction treeList that reduces the power to wheel if the car is wheel spinning too much
|
||||||
private void TractionControl()
|
private void TractionControl()
|
||||||
{
|
{
|
||||||
WheelHit wheelHit;
|
WheelHit wheelHit;
|
||||||
|
|||||||
1
Assets/Resources/PerformanceTestRunInfo.json
Normal file
1
Assets/Resources/PerformanceTestRunInfo.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"TestSuite":"","Date":0,"Player":{"Development":false,"ScreenWidth":0,"ScreenHeight":0,"ScreenRefreshRate":0,"Fullscreen":false,"Vsync":0,"AntiAliasing":0,"Batchmode":false,"RenderThreadingMode":"GraphicsJobs","GpuSkinning":true,"Platform":"","ColorSpace":"","AnisotropicFiltering":"","BlendWeights":"","GraphicsApi":"","ScriptingBackend":"IL2CPP","AndroidTargetSdkVersion":"AndroidApiLevelAuto","AndroidBuildSystem":"Gradle","BuildTarget":"StandaloneWindows64","StereoRenderingPath":"MultiPass"},"Hardware":{"OperatingSystem":"","DeviceModel":"","DeviceName":"","ProcessorType":"","ProcessorCount":0,"GraphicsDeviceName":"","SystemMemorySizeMB":0},"Editor":{"Version":"6000.0.34f1","Branch":"6000.0/staging","Changeset":"5ab2d9ed9190","Date":1736176501},"Dependencies":["com.cysharp.unitask@2.5.10","com.github-glitchenzo.nugetforunity@4.5.0","com.unity.2d.sprite@1.0.0","com.unity.ai.navigation@2.0.5","com.unity.collab-proxy@2.8.2","com.unity.ide.rider@3.0.31","com.unity.ide.visualstudio@2.0.23","com.unity.inputsystem@1.11.2","com.unity.multiplayer.center@1.0.0","com.unity.nuget.newtonsoft-json@3.2.1","com.unity.render-pipelines.core@17.0.3","com.unity.render-pipelines.universal@17.0.3","com.unity.test-framework@1.4.5","com.unity.timeline@1.8.7","com.unity.ugui@2.0.0","com.unity.visualscripting@1.9.5","com.unity.modules.accessibility@1.0.0","com.unity.modules.ai@1.0.0","com.unity.modules.androidjni@1.0.0","com.unity.modules.animation@1.0.0","com.unity.modules.assetbundle@1.0.0","com.unity.modules.audio@1.0.0","com.unity.modules.cloth@1.0.0","com.unity.modules.director@1.0.0","com.unity.modules.imageconversion@1.0.0","com.unity.modules.imgui@1.0.0","com.unity.modules.jsonserialize@1.0.0","com.unity.modules.particlesystem@1.0.0","com.unity.modules.physics@1.0.0","com.unity.modules.physics2d@1.0.0","com.unity.modules.screencapture@1.0.0","com.unity.modules.terrain@1.0.0","com.unity.modules.terrainphysics@1.0.0","com.unity.modules.tilemap@1.0.0","com.unity.modules.ui@1.0.0","com.unity.modules.uielements@1.0.0","com.unity.modules.umbra@1.0.0","com.unity.modules.unityanalytics@1.0.0","com.unity.modules.unitywebrequest@1.0.0","com.unity.modules.unitywebrequestassetbundle@1.0.0","com.unity.modules.unitywebrequestaudio@1.0.0","com.unity.modules.unitywebrequesttexture@1.0.0","com.unity.modules.unitywebrequestwww@1.0.0","com.unity.modules.vehicles@1.0.0","com.unity.modules.video@1.0.0","com.unity.modules.vr@1.0.0","com.unity.modules.wind@1.0.0","com.unity.modules.xr@1.0.0","com.unity.modules.subsystems@1.0.0","com.unity.modules.hierarchycore@1.0.0","com.unity.ext.nunit@2.0.5","com.unity.shadergraph@17.0.3","com.unity.render-pipelines.universal-config@17.0.3","com.unity.burst@1.8.18","com.unity.mathematics@1.3.2","com.unity.collections@2.5.1","com.unity.rendering.light-transport@1.0.1","com.unity.searcher@4.9.2","com.unity.nuget.mono-cecil@1.11.4","com.unity.test-framework.performance@3.0.3"],"Results":[]}
|
||||||
7
Assets/Resources/PerformanceTestRunInfo.json.meta
Normal file
7
Assets/Resources/PerformanceTestRunInfo.json.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 53771bd6e60a7544eac2221495a58a20
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
1
Assets/Resources/PerformanceTestRunSettings.json
Normal file
1
Assets/Resources/PerformanceTestRunSettings.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"MeasurementCount":-1}
|
||||||
7
Assets/Resources/PerformanceTestRunSettings.json.meta
Normal file
7
Assets/Resources/PerformanceTestRunSettings.json.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 45e7debe8080b86438553c8a252c7d91
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -491,6 +491,8 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
itemPrefab: {fileID: 4190301731963491743, guid: 3b667b13f22b81b4896e14bd416de1f7, type: 3}
|
itemPrefab: {fileID: 4190301731963491743, guid: 3b667b13f22b81b4896e14bd416de1f7, type: 3}
|
||||||
root: {fileID: 6986221832819843173}
|
root: {fileID: 6986221832819843173}
|
||||||
|
allowMultipleSelection: 1
|
||||||
|
enableDragDrop: 1
|
||||||
--- !u!1 &4144761513685641481
|
--- !u!1 &4144761513685641481
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -817,8 +819,8 @@ RectTransform:
|
|||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
m_AnchoredPosition: {x: 0, y: -12}
|
m_AnchoredPosition: {x: 0, y: -11}
|
||||||
m_SizeDelta: {x: 0, y: -44}
|
m_SizeDelta: {x: 0, y: -42}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!222 &6476927354465729135
|
--- !u!222 &6476927354465729135
|
||||||
CanvasRenderer:
|
CanvasRenderer:
|
||||||
@@ -899,9 +901,8 @@ GameObject:
|
|||||||
- component: {fileID: 6986221832819843173}
|
- component: {fileID: 6986221832819843173}
|
||||||
- component: {fileID: 1154093525567517578}
|
- component: {fileID: 1154093525567517578}
|
||||||
- component: {fileID: 2733383086465723583}
|
- component: {fileID: 2733383086465723583}
|
||||||
- component: {fileID: 7936280494337962146}
|
|
||||||
m_Layer: 5
|
m_Layer: 5
|
||||||
m_Name: EntryRoot
|
m_Name: Root
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
@@ -941,7 +942,7 @@ MonoBehaviour:
|
|||||||
m_Padding:
|
m_Padding:
|
||||||
m_Left: 20
|
m_Left: 20
|
||||||
m_Right: 0
|
m_Right: 0
|
||||||
m_Top: 0
|
m_Top: 2
|
||||||
m_Bottom: 0
|
m_Bottom: 0
|
||||||
m_ChildAlignment: 0
|
m_ChildAlignment: 0
|
||||||
m_Spacing: 0
|
m_Spacing: 0
|
||||||
@@ -966,21 +967,6 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
m_HorizontalFit: 2
|
m_HorizontalFit: 2
|
||||||
m_VerticalFit: 2
|
m_VerticalFit: 2
|
||||||
--- !u!114 &7936280494337962146
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 6690344807426313734}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: de4afb3a0d93f05448f2fc60683275c0, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
margin: {x: 0, y: 0}
|
|
||||||
target:
|
|
||||||
- {fileID: 2240268413977263779}
|
|
||||||
--- !u!1 &6757006638454796643
|
--- !u!1 &6757006638454796643
|
||||||
GameObject:
|
GameObject:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -1369,7 +1355,7 @@ RectTransform:
|
|||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: -5, y: 0}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0, y: 1}
|
m_Pivot: {x: 0, y: 1}
|
||||||
--- !u!114 &8340655046281950868
|
--- !u!114 &8340655046281950868
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
@@ -1506,7 +1492,7 @@ RectTransform:
|
|||||||
m_Father: {fileID: 1824308313848313193}
|
m_Father: {fileID: 1824308313848313193}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 1}
|
m_AnchorMin: {x: 0, y: 1}
|
||||||
m_AnchorMax: {x: 0, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 30, y: 10}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0, y: 1}
|
m_Pivot: {x: 0, y: 1}
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ RectTransform:
|
|||||||
m_AnchorMin: {x: 0, y: 1}
|
m_AnchorMin: {x: 0, y: 1}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 0, y: 20}
|
m_SizeDelta: {x: 0, y: 0}
|
||||||
m_Pivot: {x: 0, y: 1}
|
m_Pivot: {x: 0, y: 1}
|
||||||
--- !u!114 &1842670862426916792
|
--- !u!114 &1842670862426916792
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
@@ -342,7 +342,7 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 44c14fec77c285b4cb620db0f31c7ad1, type: 3}
|
m_Script: {fileID: 11500000, guid: 44c14fec77c285b4cb620db0f31c7ad1, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
control: {fileID: 0}
|
treeList: {fileID: 0}
|
||||||
valueText: {fileID: 906041055054714701}
|
valueText: {fileID: 906041055054714701}
|
||||||
childExpand: {fileID: 7394439186909941661}
|
childExpand: {fileID: 7394439186909941661}
|
||||||
childContainer: {fileID: 1842670861640538166}
|
childContainer: {fileID: 1842670861640538166}
|
||||||
@@ -688,13 +688,13 @@ RectTransform:
|
|||||||
m_PrefabInstance: {fileID: 0}
|
m_PrefabInstance: {fileID: 0}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 7184699774172569858}
|
m_GameObject: {fileID: 7184699774172569858}
|
||||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0.7071068, w: 0.7071068}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
m_ConstrainProportionsScale: 0
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 1842670860593731849}
|
m_Father: {fileID: 1842670860593731849}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 90}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 0, y: 0}
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
m_AnchoredPosition: {x: 0, y: 0}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ namespace Gpm.Ui.Sample
|
|||||||
removeCount++;
|
removeCount++;
|
||||||
UpdateDataCount();
|
UpdateDataCount();
|
||||||
|
|
||||||
AddLog(string.Format("Remove data : {0}", data.index));
|
AddLog(string.Format("RemoveChild data : {0}", data.index));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class HierarchySample : MonoBehaviour
|
|||||||
{
|
{
|
||||||
TreeListItemData itemData = new TreeListItemData("Item " + i);
|
TreeListItemData itemData = new TreeListItemData("Item " + i);
|
||||||
|
|
||||||
int len = 0;// Random.Range(1, 5);
|
int len = 3;// Random.Range(1, 5);
|
||||||
Debug.Log("len: " + len);
|
Debug.Log("len: " + len);
|
||||||
for (int j = 0; j < len; j++)
|
for (int j = 0; j < len; j++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -941,22 +941,6 @@ PrefabInstance:
|
|||||||
propertyPath: m_AnchorMax.y
|
propertyPath: m_AnchorMax.y
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 1824308313848313193, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
|
||||||
propertyPath: m_SizeDelta.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2240268413977263779, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
|
||||||
propertyPath: m_AnchorMax.x
|
|
||||||
value: 1
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2240268413977263779, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
|
||||||
propertyPath: m_SizeDelta.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2240268413977263779, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
|
||||||
propertyPath: m_SizeDelta.y
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 2651864206743669424, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
- target: {fileID: 2651864206743669424, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
||||||
propertyPath: m_Name
|
propertyPath: m_Name
|
||||||
value: TreeList
|
value: TreeList
|
||||||
@@ -1049,24 +1033,15 @@ PrefabInstance:
|
|||||||
propertyPath: m_LocalEulerAnglesHint.z
|
propertyPath: m_LocalEulerAnglesHint.z
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 6690344807426313734, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
|
||||||
propertyPath: m_Name
|
|
||||||
value: Root
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 6986221832819843173, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
|
||||||
propertyPath: m_AnchorMax.x
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
- target: {fileID: 6986221832819843173, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
- target: {fileID: 6986221832819843173, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
||||||
propertyPath: m_SizeDelta.x
|
propertyPath: m_SizeDelta.x
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 7936280494337962146, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
- target: {fileID: 6986221832819843173, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
||||||
propertyPath: m_Enabled
|
propertyPath: m_SizeDelta.y
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents:
|
m_RemovedComponents: []
|
||||||
- {fileID: 7936280494337962146, guid: a030935af8c62d748b6fe3d01bd4851f, type: 3}
|
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
m_AddedComponents: []
|
m_AddedComponents: []
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Gpm.Ui
|
|||||||
/// <b>사용 방법:</b>
|
/// <b>사용 방법:</b>
|
||||||
/// <code>
|
/// <code>
|
||||||
/// 1. 움직이게 하고 싶은 UI GameObject(예: Image, Panel)를 선택합니다.
|
/// 1. 움직이게 하고 싶은 UI GameObject(예: Image, Panel)를 선택합니다.
|
||||||
/// 2. 인스펙터 창에서 [Add Component] 버튼을 누르고 'DraggableRect'를 검색하여 추가합니다.
|
/// 2. 인스펙터 창에서 [AddChild Component] 버튼을 누르고 'DraggableRect'를 검색하여 추가합니다.
|
||||||
/// 3. 'Drag Rect Transform' 필드에 움직일 대상을 지정합니다. 비워두면 컴포넌트가 부착된 GameObject 자신이 움직입니다.
|
/// 3. 'Drag Rect Transform' 필드에 움직일 대상을 지정합니다. 비워두면 컴포넌트가 부착된 GameObject 자신이 움직입니다.
|
||||||
/// 4. 게임을 실행하고 UI를 마우스로 드래그하면 이동하는 것을 확인할 수 있습니다.
|
/// 4. 게임을 실행하고 UI를 마우스로 드래그하면 이동하는 것을 확인할 수 있습니다.
|
||||||
/// </code>
|
/// </code>
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ namespace SampleProject
|
|||||||
// .SetSplitResponseByKey(true) // 응답을 키별로 분할
|
// .SetSplitResponseByKey(true) // 응답을 키별로 분할
|
||||||
// .AddSplitConfig("AGV", DataMapperValidator.Get("AGV")) // "AGV" 키에 대한 매퍼, Validator 설정
|
// .AddSplitConfig("AGV", DataMapperValidator.Get("AGV")) // "AGV" 키에 대한 매퍼, Validator 설정
|
||||||
// .AddSplitConfig("ALARM", DataMapperValidator.Get("ALARM")); // "ALARM" 키에 대한 매퍼, Validator 설정
|
// .AddSplitConfig("ALARM", DataMapperValidator.Get("ALARM")); // "ALARM" 키에 대한 매퍼, Validator 설정
|
||||||
//httpFetcher.Add("baseInfo", splitRequest);
|
//httpFetcher.AddChild("baseInfo", splitRequest);
|
||||||
//await httpFetcher.Excute("baseInfo");
|
//await httpFetcher.Excute("baseInfo");
|
||||||
//Debug.Log("BaseInfo data request completed.");
|
//Debug.Log("BaseInfo data request completed.");
|
||||||
//UILoading.Hide();
|
//UILoading.Hide();
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace UVC.Data.Http
|
|||||||
/// // 데이터 처리 로직
|
/// // 데이터 처리 로직
|
||||||
/// ULog.Debug($"데이터 수신: {data?.ToString() ?? "null"}");
|
/// ULog.Debug($"데이터 수신: {data?.ToString() ?? "null"}");
|
||||||
/// });
|
/// });
|
||||||
/// httpFetcher.Add("dataRequest", singleRequest);
|
/// httpFetcher.AddChild("dataRequest", singleRequest);
|
||||||
///
|
///
|
||||||
/// // 반복 요청 설정 및 등록
|
/// // 반복 요청 설정 및 등록
|
||||||
/// var repeatingRequest = new HttpRequestConfig("https://api.example.com/status")
|
/// var repeatingRequest = new HttpRequestConfig("https://api.example.com/status")
|
||||||
@@ -63,7 +63,7 @@ namespace UVC.Data.Http
|
|||||||
/// ULog.Debug($"상태 업데이트: {data?.ToString() ?? "null"}");
|
/// ULog.Debug($"상태 업데이트: {data?.ToString() ?? "null"}");
|
||||||
/// })
|
/// })
|
||||||
/// .SetRepeat(true, 0, 5000); // 5초마다 무한 반복
|
/// .SetRepeat(true, 0, 5000); // 5초마다 무한 반복
|
||||||
/// httpFetcher.Add("statusMonitor", repeatingRequest);
|
/// httpFetcher.AddChild("statusMonitor", repeatingRequest);
|
||||||
///
|
///
|
||||||
/// // 응답 분할 요청 설정 (예: 응답이 {"AGV": [...], "ALARM": [...]} 형태)
|
/// // 응답 분할 요청 설정 (예: 응답이 {"AGV": [...], "ALARM": [...]} 형태)
|
||||||
/// // 각 키에 맞는 DataMapper와 Validator를 준비합니다.
|
/// // 각 키에 맞는 DataMapper와 Validator를 준비합니다.
|
||||||
@@ -76,7 +76,7 @@ namespace UVC.Data.Http
|
|||||||
/// .SetSplitResponseByKey(true) // 응답을 키별로 분할
|
/// .SetSplitResponseByKey(true) // 응답을 키별로 분할
|
||||||
/// .AddSplitConfig("AGV", agvMapper) // "AGV" 키에 대한 매퍼 설정
|
/// .AddSplitConfig("AGV", agvMapper) // "AGV" 키에 대한 매퍼 설정
|
||||||
/// .AddSplitConfig("ALARM", alarmMapper); // "ALARM" 키에 대한 매퍼 설정
|
/// .AddSplitConfig("ALARM", alarmMapper); // "ALARM" 키에 대한 매퍼 설정
|
||||||
/// httpFetcher.Add("baseInfo", splitRequest);
|
/// httpFetcher.AddChild("baseInfo", splitRequest);
|
||||||
///
|
///
|
||||||
/// // 요청 실행
|
/// // 요청 실행
|
||||||
/// await httpFetcher.Excute("dataRequest"); // 단일 실행
|
/// await httpFetcher.Excute("dataRequest"); // 단일 실행
|
||||||
@@ -93,7 +93,7 @@ namespace UVC.Data.Http
|
|||||||
/// httpFetcher.StopRepeat("statusMonitor");
|
/// httpFetcher.StopRepeat("statusMonitor");
|
||||||
///
|
///
|
||||||
/// // 더 이상 필요없는 요청 제거
|
/// // 더 이상 필요없는 요청 제거
|
||||||
/// httpFetcher.Remove("dataRequest");
|
/// httpFetcher.RemoveChild("dataRequest");
|
||||||
/// </code>
|
/// </code>
|
||||||
/// </example>
|
/// </example>
|
||||||
public class HttpDataFetcher
|
public class HttpDataFetcher
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ namespace UVC.Data.Mqtt
|
|||||||
/// var mqttReceiver = new MqttDataReceiver("mqtt.eclipseprojects.io", 1883);
|
/// var mqttReceiver = new MqttDataReceiver("mqtt.eclipseprojects.io", 1883);
|
||||||
///
|
///
|
||||||
/// // 6. 파이프라인 정보 추가
|
/// // 6. 파이프라인 정보 추가
|
||||||
/// mqttReceiver.Add(pipelineInfo);
|
/// mqttReceiver.AddChild(pipelineInfo);
|
||||||
///
|
///
|
||||||
/// // 7. 파이프라인 실행
|
/// // 7. 파이프라인 실행
|
||||||
/// mqttReceiver.Start();
|
/// mqttReceiver.Start();
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ namespace UVC.Data
|
|||||||
/// <param name="url">저장할 URL 문자열</param>
|
/// <param name="url">저장할 URL 문자열</param>
|
||||||
/// <example>
|
/// <example>
|
||||||
/// <code>
|
/// <code>
|
||||||
/// URLList.Add("google", "https://www.google.com");
|
/// URLList.AddChild("google", "https://www.google.com");
|
||||||
/// URLList.Add("naver", "https://www.naver.com");
|
/// URLList.AddChild("naver", "https://www.naver.com");
|
||||||
///
|
///
|
||||||
/// // 기존 키의 URL 업데이트
|
/// // 기존 키의 URL 업데이트
|
||||||
/// URLList.Add("google", "https://www.google.co.kr");
|
/// URLList.AddChild("google", "https://www.google.co.kr");
|
||||||
/// </code>
|
/// </code>
|
||||||
/// </example>
|
/// </example>
|
||||||
public static void Add(string key, string url)
|
public static void Add(string key, string url)
|
||||||
@@ -48,13 +48,13 @@ namespace UVC.Data
|
|||||||
/// <param name="key">제거할 URL의 키</param>
|
/// <param name="key">제거할 URL의 키</param>
|
||||||
/// <example>
|
/// <example>
|
||||||
/// <code>
|
/// <code>
|
||||||
/// URLList.Add("temp", "https://www.temp.com");
|
/// URLList.AddChild("temp", "https://www.temp.com");
|
||||||
///
|
///
|
||||||
/// // URL 제거
|
/// // URL 제거
|
||||||
/// URLList.Remove("temp");
|
/// URLList.RemoveChild("temp");
|
||||||
///
|
///
|
||||||
/// // 존재하지 않는 키 제거 시도(아무 일도 발생하지 않음)
|
/// // 존재하지 않는 키 제거 시도(아무 일도 발생하지 않음)
|
||||||
/// URLList.Remove("nonexistent");
|
/// URLList.RemoveChild("nonexistent");
|
||||||
/// </code>
|
/// </code>
|
||||||
/// </example>
|
/// </example>
|
||||||
public static void Remove(string key)
|
public static void Remove(string key)
|
||||||
@@ -72,7 +72,7 @@ namespace UVC.Data
|
|||||||
/// <returns>키가 존재하면 true, 그렇지 않으면 false</returns>
|
/// <returns>키가 존재하면 true, 그렇지 않으면 false</returns>
|
||||||
/// <example>
|
/// <example>
|
||||||
/// <code>
|
/// <code>
|
||||||
/// URLList.Add("github", "https://github.com");
|
/// URLList.AddChild("github", "https://github.com");
|
||||||
///
|
///
|
||||||
/// // 키 존재 여부 확인
|
/// // 키 존재 여부 확인
|
||||||
/// if(URLList.ContainsKey("github"))
|
/// if(URLList.ContainsKey("github"))
|
||||||
@@ -98,7 +98,7 @@ namespace UVC.Data
|
|||||||
/// <returns>키에 해당하는 URL 또는 키가 존재하지 않을 경우 null</returns>
|
/// <returns>키에 해당하는 URL 또는 키가 존재하지 않을 경우 null</returns>
|
||||||
/// <example>
|
/// <example>
|
||||||
/// <code>
|
/// <code>
|
||||||
/// URLList.Add("youtube", "https://www.youtube.com");
|
/// URLList.AddChild("youtube", "https://www.youtube.com");
|
||||||
///
|
///
|
||||||
/// // URL 가져오기
|
/// // URL 가져오기
|
||||||
/// string youtubeUrl = URLList.Get("youtube");
|
/// string youtubeUrl = URLList.Get("youtube");
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -18,9 +18,9 @@ namespace UVC.Extention
|
|||||||
/// var cityPopulation = new OrderedDictionary<string, int>();
|
/// var cityPopulation = new OrderedDictionary<string, int>();
|
||||||
///
|
///
|
||||||
/// // 데이터 추가 (순서대로 추가됨)
|
/// // 데이터 추가 (순서대로 추가됨)
|
||||||
/// cityPopulation.Add("서울", 9700000);
|
/// cityPopulation.AddChild("서울", 9700000);
|
||||||
/// cityPopulation.Add("부산", 3400000);
|
/// cityPopulation.AddChild("부산", 3400000);
|
||||||
/// cityPopulation.Add("인천", 3000000);
|
/// cityPopulation.AddChild("인천", 3000000);
|
||||||
///
|
///
|
||||||
/// // 키를 이용한 값 접근
|
/// // 키를 이용한 값 접근
|
||||||
/// Console.WriteLine($"서울 인구: {cityPopulation["서울"]}"); // 출력: 서울 인구: 9700000
|
/// Console.WriteLine($"서울 인구: {cityPopulation["서울"]}"); // 출력: 서울 인구: 9700000
|
||||||
@@ -44,7 +44,7 @@ namespace UVC.Extention
|
|||||||
/// // - 인천: 3000000
|
/// // - 인천: 3000000
|
||||||
///
|
///
|
||||||
/// // 항목 삭제
|
/// // 항목 삭제
|
||||||
/// cityPopulation.Remove("부산");
|
/// cityPopulation.RemoveChild("부산");
|
||||||
///
|
///
|
||||||
/// Console.WriteLine("\n'부산' 삭제 후 도시 목록:");
|
/// Console.WriteLine("\n'부산' 삭제 후 도시 목록:");
|
||||||
/// foreach(var city in cityPopulation)
|
/// foreach(var city in cityPopulation)
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ namespace UVC.Factory.Alarm
|
|||||||
// 현재는 알람 데이터에 AGV 정보가 없는 경우가 많아, 임시로 AGV 이름을 할당하기 위해 사용됩니다.
|
// 현재는 알람 데이터에 AGV 정보가 없는 경우가 많아, 임시로 AGV 이름을 할당하기 위해 사용됩니다.
|
||||||
for (int i = 1; i <= 115; i++)
|
for (int i = 1; i <= 115; i++)
|
||||||
{
|
{
|
||||||
//agvNames.Add($"HFF09CNA8{i.ToString("D3")}");
|
//agvNames.AddChild($"HFF09CNA8{i.ToString("D3")}");
|
||||||
agvNames.Add($"HFF09CNA8061");
|
agvNames.Add($"HFF09CNA8061");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ namespace UVC.Factory.Playback
|
|||||||
int newSecond = second;
|
int newSecond = second;
|
||||||
if (newSecond > 36000) newSecond = 36000;
|
if (newSecond > 36000) newSecond = 36000;
|
||||||
//utc 시간으로 변환
|
//utc 시간으로 변환
|
||||||
DateTime dateTime = DateTimeUtil.UtcParse($"{date}T{int.Parse(time).ToString("00")}:00:00.000Z").AddSeconds(newSecond);//.Add(-DateTimeUtil.UtcKoreaGap);
|
DateTime dateTime = DateTimeUtil.UtcParse($"{date}T{int.Parse(time).ToString("00")}:00:00.000Z").AddSeconds(newSecond);//.AddChild(-DateTimeUtil.UtcKoreaGap);
|
||||||
string formatTime = DateTimeUtil.FormatTime(dateTime);
|
string formatTime = DateTimeUtil.FormatTime(dateTime);
|
||||||
|
|
||||||
List<PlaybackSQLiteDataEntity> list = await repository.SelectBySecondAsync(date, fileName, formatTime, 1);
|
List<PlaybackSQLiteDataEntity> list = await repository.SelectBySecondAsync(date, fileName, formatTime, 1);
|
||||||
@@ -255,7 +255,7 @@ namespace UVC.Factory.Playback
|
|||||||
string zipFilePath = Path.Combine(datePath, fileName);
|
string zipFilePath = Path.Combine(datePath, fileName);
|
||||||
string sqlFilePath = Path.Combine(datePath, fileNameArr[0] + ".sqlite");
|
string sqlFilePath = Path.Combine(datePath, fileNameArr[0] + ".sqlite");
|
||||||
|
|
||||||
DateTime utcDateTime = DateTimeUtil.Parse(fileNameArr[0], "yyyy-MM-dd_H");//.Add(-DateTimeUtil.UtcKoreaGap);
|
DateTime utcDateTime = DateTimeUtil.Parse(fileNameArr[0], "yyyy-MM-dd_H");//.AddChild(-DateTimeUtil.UtcKoreaGap);
|
||||||
string utcDatePath = Path.Combine(playbackPath, utcDateTime.ToString("yyyy-MM-dd"));
|
string utcDatePath = Path.Combine(playbackPath, utcDateTime.ToString("yyyy-MM-dd"));
|
||||||
string utcFileName = utcDateTime.ToString("yyyy-MM-dd_H") + "." + fileNameArr[1] + "." + fileNameArr[2];
|
string utcFileName = utcDateTime.ToString("yyyy-MM-dd_H") + "." + fileNameArr[1] + "." + fileNameArr[2];
|
||||||
var utcFileNameArr = utcFileName.Split(".");
|
var utcFileNameArr = utcFileName.Split(".");
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace UVC.Linq
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public enum TransformCloneType
|
public enum TransformCloneType
|
||||||
{
|
{
|
||||||
/// <summary>원본과 동일하게 설정합니다. Add 메소드의 기본값입니다.</summary>
|
/// <summary>원본과 동일하게 설정합니다. AddChild 메소드의 기본값입니다.</summary>
|
||||||
KeepOriginal,
|
KeepOriginal,
|
||||||
/// <summary>부모와 동일하게 설정합니다.</summary>
|
/// <summary>부모와 동일하게 설정합니다.</summary>
|
||||||
FollowParent,
|
FollowParent,
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ namespace UVC.Pool
|
|||||||
/// 사용 예:
|
/// 사용 예:
|
||||||
/// <code>
|
/// <code>
|
||||||
/// SmallList<int> numbers = new SmallList<int>();
|
/// SmallList<int> numbers = new SmallList<int>();
|
||||||
/// numbers.Add(10);
|
/// numbers.AddChild(10);
|
||||||
/// numbers.Add(20);
|
/// numbers.AddChild(20);
|
||||||
/// int firstNumber = numbers[0]; // 10
|
/// int firstNumber = numbers[0]; // 10
|
||||||
/// </code>
|
/// </code>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ namespace UVC.Tests.Data
|
|||||||
// Assert
|
// Assert
|
||||||
Assert.AreEqual(3, _dataArray.Count, "DataArray의 전체 개수는 3이어야 합니다.");
|
Assert.AreEqual(3, _dataArray.Count, "DataArray의 전체 개수는 3이어야 합니다.");
|
||||||
Assert.Contains(_item3, _dataArray.ToList());
|
Assert.Contains(_item3, _dataArray.ToList());
|
||||||
Assert.AreEqual(0, _dataArray.AddedItems.Count, "Add 메서드는 더 이상 AddedItems를 직접 채우지 않아야 합니다.");
|
Assert.AreEqual(0, _dataArray.AddedItems.Count, "AddChild 메서드는 더 이상 AddedItems를 직접 채우지 않아야 합니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -91,7 +91,7 @@ namespace UVC.Tests.Data
|
|||||||
Assert.IsTrue(result, "항목 제거는 성공해야 합니다.");
|
Assert.IsTrue(result, "항목 제거는 성공해야 합니다.");
|
||||||
Assert.AreEqual(1, _dataArray.Count, "DataArray의 전체 개수는 1이어야 합니다.");
|
Assert.AreEqual(1, _dataArray.Count, "DataArray의 전체 개수는 1이어야 합니다.");
|
||||||
Assert.IsFalse(_dataArray.Contains(_item1));
|
Assert.IsFalse(_dataArray.Contains(_item1));
|
||||||
Assert.AreEqual(0, _dataArray.RemovedItems.Count, "Remove 메서드는 더 이상 RemovedItems를 직접 채우지 않아야 합니다.");
|
Assert.AreEqual(0, _dataArray.RemovedItems.Count, "RemoveChild 메서드는 더 이상 RemovedItems를 직접 채우지 않아야 합니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ namespace UVC.Tests.Data
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 존재하지 않는 키에 대한 Remove 호출 테스트
|
/// 존재하지 않는 키에 대한 RemoveChild 호출 테스트
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Test]
|
[Test]
|
||||||
public async UniTask Remove_NonExistingInfo_DoesNothing()
|
public async UniTask Remove_NonExistingInfo_DoesNothing()
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,4 +1,5 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -62,7 +63,7 @@ namespace UVC.UI.List.Tree
|
|||||||
///
|
///
|
||||||
/// 역할:
|
/// 역할:
|
||||||
/// - AddItem()에서 새 아이템의 부모로 지정
|
/// - AddItem()에서 새 아이템의 부모로 지정
|
||||||
/// - UpdateFlattenedItemList()에서 모든 자식을 순회
|
/// - UpdateFlattenedItemDataList()에서 모든 자식을 순회
|
||||||
///
|
///
|
||||||
/// 구조 예:
|
/// 구조 예:
|
||||||
/// root (이것)
|
/// root (이것)
|
||||||
@@ -150,16 +151,20 @@ namespace UVC.UI.List.Tree
|
|||||||
/// - SelectRange()에서 두 아이템 사이의 인덱스를 빠르게 찾기
|
/// - SelectRange()에서 두 아이템 사이의 인덱스를 빠르게 찾기
|
||||||
/// - Shift+클릭 범위 선택 구현
|
/// - Shift+클릭 범위 선택 구현
|
||||||
///
|
///
|
||||||
/// UpdateFlattenedItemList() 메서드로 항상 최신 상태로 유지됩니다.
|
/// UpdateFlattenedItemDataList() 메서드로 항상 최신 상태로 유지됩니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected List<TreeListItemData> allItemsFlattened = new List<TreeListItemData>();
|
protected List<TreeListItemData> allItemDatasFlattened = new List<TreeListItemData>();
|
||||||
|
|
||||||
public List<TreeListItemData> AllItemsFlattened => allItemsFlattened;
|
public List<TreeListItemData> AllItemsFlattened => allItemDatasFlattened;
|
||||||
|
|
||||||
protected List<TreeListItemData> items = new List<TreeListItemData>();
|
protected List<TreeListItemData> items = new List<TreeListItemData>();
|
||||||
|
|
||||||
public List<TreeListItemData> Items => items;
|
public List<TreeListItemData> Items => items;
|
||||||
|
|
||||||
|
protected List<TreeListItem> allItemFlattened = new List<TreeListItem>();
|
||||||
|
|
||||||
|
public List<TreeListItem> AllItemFlattened => allItemFlattened;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 드래그 & 드롭 매니저입니다.
|
/// 드래그 & 드롭 매니저입니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -174,7 +179,7 @@ namespace UVC.UI.List.Tree
|
|||||||
/// 무언가 일어났을 때 다른 코드에 알려주는 메커니즘입니다.
|
/// 무언가 일어났을 때 다른 코드에 알려주는 메커니즘입니다.
|
||||||
/// 구독자(listener)가 등록되어 있으면 자동으로 호출됩니다.
|
/// 구독자(listener)가 등록되어 있으면 자동으로 호출됩니다.
|
||||||
///
|
///
|
||||||
/// 문법: event Action<TreeListItemData, bool>?
|
/// 문법: Action<TreeListItemData, bool>?
|
||||||
/// = TreeListItemData 1개, bool 1개를 매개변수로 받는 함수들을 등록
|
/// = TreeListItemData 1개, bool 1개를 매개변수로 받는 함수들을 등록
|
||||||
///
|
///
|
||||||
/// 호출되는 경우:
|
/// 호출되는 경우:
|
||||||
@@ -186,7 +191,7 @@ namespace UVC.UI.List.Tree
|
|||||||
/// Debug.Log($"{data.Name}이 {(isSelected ? "선택됨" : "해제됨")}");
|
/// Debug.Log($"{data.Name}이 {(isSelected ? "선택됨" : "해제됨")}");
|
||||||
/// };
|
/// };
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<TreeListItemData, bool>? OnItemSelectionChanged;
|
public Action<TreeListItemData, bool>? OnItemSelectionChanged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 현재 선택된 아이템 목록을 반환합니다. (읽기 전용)
|
/// 현재 선택된 아이템 목록을 반환합니다. (읽기 전용)
|
||||||
@@ -197,7 +202,7 @@ namespace UVC.UI.List.Tree
|
|||||||
///
|
///
|
||||||
/// AsReadOnly()란?
|
/// AsReadOnly()란?
|
||||||
/// 리스트를 읽기 전용으로 변환합니다.
|
/// 리스트를 읽기 전용으로 변환합니다.
|
||||||
/// 따라서 외부에서 SelectedItems.Add()같은 수정이 불가능합니다.
|
/// 따라서 외부에서 SelectedItems.AddChild()같은 수정이 불가능합니다.
|
||||||
///
|
///
|
||||||
/// 왜 이렇게 하나?
|
/// 왜 이렇게 하나?
|
||||||
/// 클래스 내부에서만 selectedItems를 제어하고,
|
/// 클래스 내부에서만 selectedItems를 제어하고,
|
||||||
@@ -211,6 +216,8 @@ namespace UVC.UI.List.Tree
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public IReadOnlyList<TreeListItemData> SelectedItems => selectedItems.AsReadOnly();
|
public IReadOnlyList<TreeListItemData> SelectedItems => selectedItems.AsReadOnly();
|
||||||
|
|
||||||
|
public List<TreeListItem> TreeLists => root.GetComponentsInChildren<TreeListItem>().ToList();
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
// 드래그 & 드롭 이벤트 구독
|
// 드래그 & 드롭 이벤트 구독
|
||||||
@@ -226,6 +233,54 @@ namespace UVC.UI.List.Tree
|
|||||||
{
|
{
|
||||||
dragDropManager.OnDropped -= HandleItemDropped;
|
dragDropManager.OnDropped -= HandleItemDropped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(OnItemSelectionChanged != null) OnItemSelectionChanged = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
// Delete 키 입력 감지
|
||||||
|
if (Input.GetKeyDown(KeyCode.Delete))
|
||||||
|
{
|
||||||
|
HandleDeleteKeyPressed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete 키가 눌렸을 때 선택된 아이템들을 삭제합니다.
|
||||||
|
///
|
||||||
|
/// 동작:
|
||||||
|
/// 1. 현재 선택된 아이템 목록을 복사 (선택 상태 변경 중 문제 방지)
|
||||||
|
/// 2. 복사본을 역순으로 순회 (뒤에서 앞으로)
|
||||||
|
/// 3. 각 아이템을 RemoveItem()으로 삭제
|
||||||
|
///
|
||||||
|
/// 역순 삭제 이유:
|
||||||
|
/// - 앞에서부터 삭제하면 인덱스가 변경되어 뒤의 아이템을 놓칠 수 있음
|
||||||
|
/// - 뒤에서부터 삭제하면 앞의 인덱스는 영향을 받지 않음
|
||||||
|
///
|
||||||
|
/// ToList()로 복사하는 이유:
|
||||||
|
/// - RemoveItem() 호출 중 selectedItems가 수정될 수 있음
|
||||||
|
/// - 복사본을 순회하면 안전하게 모든 아이템을 삭제 가능
|
||||||
|
/// </summary>
|
||||||
|
private void HandleDeleteKeyPressed()
|
||||||
|
{
|
||||||
|
// 선택된 아이템이 없으면 아무것도 하지 않음
|
||||||
|
if (selectedItems.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 선택된 아이템 목록을 복사 (역순 삭제 시 안전)
|
||||||
|
var itemsToDelete = selectedItems.ToList();
|
||||||
|
|
||||||
|
// 디버그 로그
|
||||||
|
Debug.Log($"Delete key pressed. Removing {itemsToDelete.Count} selected item(s).");
|
||||||
|
|
||||||
|
// 각 선택된 아이템을 삭제
|
||||||
|
foreach (var item in itemsToDelete)
|
||||||
|
{
|
||||||
|
DeleteItem(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -254,66 +309,98 @@ namespace UVC.UI.List.Tree
|
|||||||
public void AddItem(TreeListItemData data)
|
public void AddItem(TreeListItemData data)
|
||||||
{
|
{
|
||||||
data.Parent = null;
|
data.Parent = null;
|
||||||
// Instantiate(템플릿, 부모 Transform)
|
//data에 해당하는 TreeListItem 찾기
|
||||||
// = 템플릿을 복제하고 부모의 자식으로 설정
|
TreeListItem? item = allItemFlattened.FirstOrDefault(x => x.Data == data);
|
||||||
TreeListItem item = GameObject.Instantiate<TreeListItem>(ItemPrefab, root);
|
if (item != null)
|
||||||
|
{
|
||||||
|
item.transform.SetParent(root);
|
||||||
|
item.SetExpand();
|
||||||
|
|
||||||
// 생성된 아이템 초기화
|
UniTask.DelayFrame(1).ContinueWith(() =>
|
||||||
// 데이터를 UI에 바인딩하고 이벤트 리스너 등록
|
{
|
||||||
item.Init(data, this, dragDropManager);
|
//gameObject 순서 조절
|
||||||
|
item.transform.SetAsLastSibling();
|
||||||
|
|
||||||
items.Add(data);
|
// 범위 선택에 필요한 평탄화 리스트 업데이트
|
||||||
|
UpdateFlattenedItemDataList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Instantiate(템플릿, 부모 Transform)
|
||||||
|
// = 템플릿을 복제하고 부모의 자식으로 설정
|
||||||
|
item = GameObject.Instantiate<TreeListItem>(ItemPrefab, root);
|
||||||
|
|
||||||
// 범위 선택에 필요한 평탄화 리스트 업데이트
|
// 생성된 아이템 초기화
|
||||||
UpdateFlattenedItemList();
|
// 데이터를 UI에 바인딩하고 이벤트 리스너 등록
|
||||||
|
item.Init(data, this, dragDropManager);
|
||||||
|
items.Add(data);
|
||||||
|
|
||||||
|
// 범위 선택에 필요한 평탄화 리스트 업데이트
|
||||||
|
UpdateFlattenedItemDataList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddItemAt(TreeListItemData data, int index)
|
public void AddItemAt(TreeListItemData data, int index)
|
||||||
{
|
{
|
||||||
data.Parent = null;
|
data.Parent = null;
|
||||||
TreeListItem item = GameObject.Instantiate<TreeListItem>(ItemPrefab, root);
|
//data에 해당하는 TreeListItem 찾기
|
||||||
item.Init(data, this, dragDropManager);
|
TreeListItem? item = allItemFlattened.FirstOrDefault(x => x.Data == data);
|
||||||
items.Insert(index, data);
|
if (item != null)
|
||||||
|
{
|
||||||
|
item.transform.SetParent(root);
|
||||||
|
item.SetExpand();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item = GameObject.Instantiate<TreeListItem>(ItemPrefab, root);
|
||||||
|
item.Init(data, this, dragDropManager);
|
||||||
|
items.Insert(index, data);
|
||||||
|
}
|
||||||
|
|
||||||
//gameObject 순서 조절
|
UniTask.DelayFrame(1).ContinueWith(() =>
|
||||||
item.transform.SetSiblingIndex(index);
|
{
|
||||||
|
//gameObject 순서 조절
|
||||||
// 범위 선택에 필요한 평탄화 리스트 업데이트
|
item.transform.SetSiblingIndex(index);
|
||||||
UpdateFlattenedItemList();
|
|
||||||
|
// 범위 선택에 필요한 평탄화 리스트 업데이트
|
||||||
|
UpdateFlattenedItemDataList();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 해당 항목을 트리 리스트에서 제거합니다. date 자체를 삭제하지 않습니다.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
public void RemoveItem(TreeListItemData data)
|
public void RemoveItem(TreeListItemData data)
|
||||||
{
|
{
|
||||||
if (data.Parent != null)
|
|
||||||
{
|
|
||||||
data.Parent.RemoveChild(data);
|
|
||||||
}
|
|
||||||
data.Parent = null;
|
|
||||||
items.Remove(data);
|
items.Remove(data);
|
||||||
//gameObject 삭제
|
|
||||||
// 🎯 root가 부모인 TreeListItem을 찾아 Destroy하기
|
|
||||||
// 1️. root의 모든 직접 자식을 순회
|
// selectedItems에서도 제거
|
||||||
for (int i = 0; i < root.childCount; i++)
|
if (selectedItems.Contains(data))
|
||||||
{
|
{
|
||||||
// 자식 Transform 가져오기
|
selectedItems.Remove(data);
|
||||||
Transform childTransform = root.GetChild(i);
|
|
||||||
|
|
||||||
// TreeListItem 컴포넌트 검색
|
|
||||||
TreeListItem treeListItem = childTransform.GetComponent<TreeListItem>();
|
|
||||||
|
|
||||||
// TreeListItem이 있고, 그 데이터가 제거할 데이터와 같으면 삭제
|
|
||||||
if (treeListItem != null && treeListItem.Data == data)
|
|
||||||
{
|
|
||||||
// TreeListItem의 Delete() 메서드로 정리 작업 수행
|
|
||||||
// (이벤트 구독 해제 및 GameObject 삭제)
|
|
||||||
treeListItem.Delete();
|
|
||||||
|
|
||||||
break; // 해당 아이템을 찾았으므로 루프 종료
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TreeListItem? item = allItemFlattened.FirstOrDefault(x => x.Data == data);
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
item.Delete();
|
||||||
|
}
|
||||||
|
|
||||||
// 범위 선택에 필요한 평탄화 리스트 업데이트
|
// 범위 선택에 필요한 평탄화 리스트 업데이트
|
||||||
UpdateFlattenedItemList();
|
UpdateFlattenedItemDataList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 해당 항목을 트리 리스트에서 제거며 date 자체도 삭제합니다.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
public void DeleteItem(TreeListItemData data)
|
||||||
|
{
|
||||||
|
RemoveItem(data);
|
||||||
|
data.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -323,7 +410,7 @@ namespace UVC.UI.List.Tree
|
|||||||
/// 1. 기존 평탄화 리스트를 비움 (Clear)
|
/// 1. 기존 평탄화 리스트를 비움 (Clear)
|
||||||
/// 2. root의 모든 직접 자식을 순회 (foreach)
|
/// 2. root의 모든 직접 자식을 순회 (foreach)
|
||||||
/// 3. 각 자식의 TreeListItem 컴포넌트 획득 (GetComponent)
|
/// 3. 각 자식의 TreeListItem 컴포넌트 획득 (GetComponent)
|
||||||
/// 4. AddItemToFlattened() 호출해서 자식과 손자까지 재귀 추가
|
/// 4. AddItemDataToFlattened() 호출해서 자식과 손자까지 재귀 추가
|
||||||
///
|
///
|
||||||
/// 호출되는 시점:
|
/// 호출되는 시점:
|
||||||
/// - AddItem() 실행 후 (새 아이템 추가됨)
|
/// - AddItem() 실행 후 (새 아이템 추가됨)
|
||||||
@@ -342,17 +429,27 @@ namespace UVC.UI.List.Tree
|
|||||||
/// 예: child.GetComponent<TreeListItem>()
|
/// 예: child.GetComponent<TreeListItem>()
|
||||||
/// = child 게임 오브젝트에서 TreeListItem 컴포넌트 찾기
|
/// = child 게임 오브젝트에서 TreeListItem 컴포넌트 찾기
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void UpdateFlattenedItemList()
|
internal void UpdateFlattenedItemDataList()
|
||||||
{
|
{
|
||||||
// 기존 평탄화 리스트 비우기
|
// 기존 평탄화 리스트 비우기
|
||||||
allItemsFlattened.Clear();
|
allItemDatasFlattened.Clear();
|
||||||
|
|
||||||
// root의 모든 직접 자식을 순회
|
// root의 모든 직접 자식을 순회
|
||||||
// (손자, 증손자는 재귀로 처리됨)
|
// (손자, 증손자는 재귀로 처리됨)
|
||||||
foreach (TreeListItemData itemData in items)
|
foreach (TreeListItemData itemData in items)
|
||||||
{
|
{
|
||||||
// 이 아이템과 자식들을 재귀적으로 평탄화 리스트에 추가
|
// 이 아이템과 자식들을 재귀적으로 평탄화 리스트에 추가
|
||||||
AddItemToFlattened(itemData);
|
AddItemDataToFlattened(itemData);
|
||||||
|
}
|
||||||
|
|
||||||
|
allItemFlattened.Clear();
|
||||||
|
foreach (var data in allItemDatasFlattened)
|
||||||
|
{
|
||||||
|
var item = root.GetComponentsInChildren<TreeListItem>().FirstOrDefault(x => x.Data == data);
|
||||||
|
if(item != null)
|
||||||
|
{
|
||||||
|
allItemFlattened.Add(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,31 +463,31 @@ namespace UVC.UI.List.Tree
|
|||||||
/// 동작:
|
/// 동작:
|
||||||
/// 1. 현재 data를 allItemsFlattened에 추가
|
/// 1. 현재 data를 allItemsFlattened에 추가
|
||||||
/// 2. data의 모든 자식 Children을 순회
|
/// 2. data의 모든 자식 Children을 순회
|
||||||
/// 3. 각 자식에 대해 AddItemToFlattened() 재귀 호출
|
/// 3. 각 자식에 대해 AddItemDataToFlattened() 재귀 호출
|
||||||
///
|
///
|
||||||
/// 예시 - 트리 구조를 평탄화하는 과정:
|
/// 예시 - 트리 구조를 평탄화하는 과정:
|
||||||
///
|
///
|
||||||
/// 트리: 재귀 호출 흐름: 결과:
|
/// 트리: 재귀 호출 흐름: 결과:
|
||||||
/// 폴더1 AddItemToFlattened(폴더1) [폴더1,
|
/// 폴더1 AddItemDataToFlattened(폴더1) [폴더1,
|
||||||
/// ├─ 파일1 → AddItemToFlattened(파일1) 파일1,
|
/// ├─ 파일1 → AddItemDataToFlattened(파일1) 파일1,
|
||||||
/// ├─ 파일2 → AddItemToFlattened(파일2) 파일2,
|
/// ├─ 파일2 → AddItemDataToFlattened(파일2) 파일2,
|
||||||
/// └─ 폴더2 → AddItemToFlattened(폴더2) 폴더2,
|
/// └─ 폴더2 → AddItemDataToFlattened(폴더2) 폴더2,
|
||||||
/// └─ 파일3 → AddItemToFlattened(파일3) 파일3]
|
/// └─ 파일3 → AddItemDataToFlattened(파일3) 파일3]
|
||||||
///
|
///
|
||||||
/// 매개변수:
|
/// 매개변수:
|
||||||
/// - data: 현재 처리할 아이템
|
/// - data: 현재 처리할 아이템
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void AddItemToFlattened(TreeListItemData data)
|
private void AddItemDataToFlattened(TreeListItemData data)
|
||||||
{
|
{
|
||||||
// 현재 아이템을 평탄화 리스트에 추가
|
// 현재 아이템을 평탄화 리스트에 추가
|
||||||
allItemsFlattened.Add(data);
|
allItemDatasFlattened.Add(data);
|
||||||
|
|
||||||
// 현재 아이템의 모든 자식을 순회
|
// 현재 아이템의 모든 자식을 순회
|
||||||
foreach (var child in data.Children)
|
foreach (var child in data.Children)
|
||||||
{
|
{
|
||||||
// 각 자식에 대해 재귀 호출
|
// 각 자식에 대해 재귀 호출
|
||||||
// = 자식의 자식들도 모두 추가됨
|
// = 자식의 자식들도 모두 추가됨
|
||||||
AddItemToFlattened(child);
|
AddItemDataToFlattened(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,10 +613,10 @@ namespace UVC.UI.List.Tree
|
|||||||
private void SelectRange(TreeListItemData startItem, TreeListItemData endItem)
|
private void SelectRange(TreeListItemData startItem, TreeListItemData endItem)
|
||||||
{
|
{
|
||||||
// 평탄화 리스트에서 시작 아이템의 위치(인덱스) 찾기
|
// 평탄화 리스트에서 시작 아이템의 위치(인덱스) 찾기
|
||||||
int startIndex = allItemsFlattened.IndexOf(startItem);
|
int startIndex = allItemDatasFlattened.IndexOf(startItem);
|
||||||
|
|
||||||
// 평탄화 리스트에서 끝 아이템의 위치(인덱스) 찾기
|
// 평탄화 리스트에서 끝 아이템의 위치(인덱스) 찾기
|
||||||
int endIndex = allItemsFlattened.IndexOf(endItem);
|
int endIndex = allItemDatasFlattened.IndexOf(endItem);
|
||||||
|
|
||||||
// 두 아이템 모두 리스트에 없으면 종료
|
// 두 아이템 모두 리스트에 없으면 종료
|
||||||
if (startIndex == -1 || endIndex == -1)
|
if (startIndex == -1 || endIndex == -1)
|
||||||
@@ -537,7 +634,7 @@ namespace UVC.UI.List.Tree
|
|||||||
// i = minIndex부터 i = maxIndex까지 (포함)
|
// i = minIndex부터 i = maxIndex까지 (포함)
|
||||||
for (int i = minIndex; i <= maxIndex; i++)
|
for (int i = minIndex; i <= maxIndex; i++)
|
||||||
{
|
{
|
||||||
SelectItem(allItemsFlattened[i]);
|
SelectItem(allItemDatasFlattened[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -722,7 +819,7 @@ namespace UVC.UI.List.Tree
|
|||||||
private void HandleItemDropped(TreeListItemData draggedItem, TreeListItemData? targetItem)
|
private void HandleItemDropped(TreeListItemData draggedItem, TreeListItemData? targetItem)
|
||||||
{
|
{
|
||||||
// 평탄화 리스트 업데이트
|
// 평탄화 리스트 업데이트
|
||||||
UpdateFlattenedItemList();
|
UpdateFlattenedItemDataList();
|
||||||
|
|
||||||
// 필요시 UI 재구성 (예: 자식 컨테이너 위치 변경 등)
|
// 필요시 UI 재구성 (예: 자식 컨테이너 위치 변경 등)
|
||||||
Debug.Log($"Item '{draggedItem.Name}' dropped on '{(targetItem?.Name ?? "Root")}'");
|
Debug.Log($"Item '{draggedItem.Name}' dropped on '{(targetItem?.Name ?? "Root")}'");
|
||||||
|
|||||||
@@ -34,22 +34,22 @@ namespace UVC.UI.List.Tree
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 드래그 시작 시 발생하는 이벤트입니다.
|
/// 드래그 시작 시 발생하는 이벤트입니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<TreeListItemData>? OnDragStarted;
|
public Action<TreeListItemData>? OnDragStarted;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 드래그 진행 중 발생하는 이벤트입니다.
|
/// 드래그 진행 중 발생하는 이벤트입니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<TreeListItemData, TreeListItemData?>? OnDragEntered;
|
public Action<TreeListItemData, TreeListItemData?>? OnDragEntered;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 드래그 종료 시 발생하는 이벤트입니다.
|
/// 드래그 종료 시 발생하는 이벤트입니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<TreeListItemData>? OnDragEnded;
|
public Action<TreeListItemData>? OnDragEnded;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 드롭 완료 시 발생하는 이벤트입니다.
|
/// 드롭 완료 시 발생하는 이벤트입니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event Action<TreeListItemData, TreeListItemData?>? OnDropped;
|
public Action<TreeListItemData, TreeListItemData?>? OnDropped;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 드래그를 시작합니다.
|
/// 드래그를 시작합니다.
|
||||||
@@ -140,44 +140,21 @@ namespace UVC.UI.List.Tree
|
|||||||
/// <returns>조상-후손 관계이면 true</returns>
|
/// <returns>조상-후손 관계이면 true</returns>
|
||||||
public static bool IsAncestorOf(TreeListItemData potentialAncestor, TreeListItemData potentialDescendant)
|
public static bool IsAncestorOf(TreeListItemData potentialAncestor, TreeListItemData potentialDescendant)
|
||||||
{
|
{
|
||||||
var current = potentialDescendant;
|
var current = potentialDescendant.Parent;
|
||||||
|
|
||||||
while (current != null)
|
while (current != null)
|
||||||
{
|
{
|
||||||
// 재귀적으로 부모를 찾는 로직
|
if (current == potentialAncestor)
|
||||||
// TreeListItemData는 부모 참조가 없으므로, 전체 리스트에서 찾아야 함
|
|
||||||
// 여기서는 간단한 버전으로, 자식 리스트를 통해 확인
|
|
||||||
var parent = FindParent(current, potentialAncestor);
|
|
||||||
|
|
||||||
if (parent == null)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent == potentialAncestor)
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
current = parent;
|
current = current.Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 주어진 아이템의 부모를 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="child">자식 아이템</param>
|
|
||||||
/// <param name="searchLimit">검색 제한 (이 아이템이 나타나면 멈춤)</param>
|
|
||||||
/// <returns>부모 아이템 (없으면 null)</returns>
|
|
||||||
private static TreeListItemData? FindParent(TreeListItemData child, TreeListItemData searchLimit)
|
|
||||||
{
|
|
||||||
// 이 구현은 전체 트리를 순회하므로 성능이 낮음
|
|
||||||
// 실제 구현에서는 TreeListItemData에 부모 참조를 추가하는 것이 나음
|
|
||||||
// 여기서는 시연 목적으로 간단하게 구현
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 모든 드래그 & 드롭 상태를 리셋합니다.
|
/// 모든 드래그 & 드롭 상태를 리셋합니다.
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
using DG.Tweening;
|
using DG.Tweening;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
@@ -46,7 +48,7 @@ namespace UVC.UI.List.Tree
|
|||||||
/// (private이지만 Unity가 특별히 접근 가능)
|
/// (private이지만 Unity가 특별히 접근 가능)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
protected TreeList control;
|
protected TreeList treeList;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 이 아이템의 이름을 표시하는 텍스트 UI입니다.
|
/// 이 아이템의 이름을 표시하는 텍스트 UI입니다.
|
||||||
@@ -224,7 +226,7 @@ namespace UVC.UI.List.Tree
|
|||||||
///
|
///
|
||||||
/// 매개변수:
|
/// 매개변수:
|
||||||
/// - data: 표시할 데이터
|
/// - data: 표시할 데이터
|
||||||
/// - control: 부모 TreeList (선택 관리, 클릭 처리 등)
|
/// - treeList: 부모 TreeList (선택 관리, 클릭 처리 등)
|
||||||
///
|
///
|
||||||
/// 사용 예:
|
/// 사용 예:
|
||||||
/// var item = Instantiate(prefab);
|
/// var item = Instantiate(prefab);
|
||||||
@@ -233,40 +235,29 @@ namespace UVC.UI.List.Tree
|
|||||||
public void Init(TreeListItemData data, TreeList control, TreeListDragDropManager dragDropManager)
|
public void Init(TreeListItemData data, TreeList control, TreeListDragDropManager dragDropManager)
|
||||||
{
|
{
|
||||||
// 1. 기본 정보 할당
|
// 1. 기본 정보 할당
|
||||||
this.control = control;
|
this.treeList = control;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
|
||||||
|
gameObject.name = "TreeListItem_" + data.Name;
|
||||||
|
|
||||||
// 2. 아이템 이름을 UI에 표시
|
// 2. 아이템 이름을 UI에 표시
|
||||||
valueText.text = data.Name;
|
valueText.text = data.Name;
|
||||||
|
|
||||||
// 3. 자식 아이템들을 UI로 생성
|
// 3. 자식 아이템들을 UI로 생성
|
||||||
Debug.Log("Creating Children for " + data.Name + ", " + data.Children.Count);
|
Debug.Log("Creating Children for " + data.Name + ", " + data.Children.Count);
|
||||||
|
|
||||||
// 자식이 없는 경우
|
|
||||||
if (data.Children.Count == 0)
|
|
||||||
{
|
|
||||||
// 펼침 버튼 숨기기 (자식이 없으니까 펼칠 게 없음)
|
|
||||||
childExpand.gameObject.SetActive(false);
|
|
||||||
|
|
||||||
// 자식 컨테이너도 숨기기
|
if (data.Children.Count > 0)
|
||||||
childContainer.SetActive(false);
|
{
|
||||||
}
|
|
||||||
// 자식이 있는 경우
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 각 자식 데이터에 대해 UI 생성
|
// 각 자식 데이터에 대해 UI 생성
|
||||||
foreach (var childData in data.Children)
|
foreach (var childData in data.Children)
|
||||||
{
|
{
|
||||||
CreateItem(childData); // 재귀적으로 트리 구조 생성
|
CreateItem(childData); // 재귀적으로 트리 구조 생성
|
||||||
}
|
}
|
||||||
|
|
||||||
// 펼침 버튼과 컨테이너 표시
|
|
||||||
childExpand.gameObject.SetActive(true);
|
|
||||||
childContainer.SetActive(true);
|
|
||||||
|
|
||||||
// 화살표 방향 설정 (초기에는 펼쳐짐)
|
|
||||||
SetExpand();
|
|
||||||
}
|
}
|
||||||
|
// 화살표 방향 설정 (초기에는 펼쳐짐)
|
||||||
|
SetExpand();
|
||||||
|
|
||||||
// 4. 데이터 변경 감지 구독
|
// 4. 데이터 변경 감지 구독
|
||||||
// 데이터의 이름, 자식 목록 등이 변경되면 OnDataChanged 호출
|
// 데이터의 이름, 자식 목록 등이 변경되면 OnDataChanged 호출
|
||||||
@@ -323,118 +314,93 @@ namespace UVC.UI.List.Tree
|
|||||||
/// 데이터가 변경되면 UI가 자동으로 업데이트되는 패턴입니다.
|
/// 데이터가 변경되면 UI가 자동으로 업데이트되는 패턴입니다.
|
||||||
/// 이렇게 하면 데이터와 UI를 동기화 유지하기 쉽습니다.
|
/// 이렇게 하면 데이터와 UI를 동기화 유지하기 쉽습니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnDataChanged(TreeListItemData changedData)
|
private void OnDataChanged(ChangedType changedType, TreeListItemData changedData, int index)
|
||||||
{
|
{
|
||||||
if (data == null) return;
|
if (data == null) return;
|
||||||
|
|
||||||
// 이름이 변경된 경우
|
if (changedType == ChangedType.Expanded)
|
||||||
if (valueText.text != data.Name)
|
|
||||||
{
|
{
|
||||||
valueText.text = data.Name;
|
childContainer.SetActive(data.IsExpanded);
|
||||||
|
// 펼침/접힘 상태 변경 처리
|
||||||
|
SetExpand();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 자식 목록이 변경된 경우 (추가/제거/순서 변경)
|
|
||||||
// 1️. 현재 UI의 모든 자식 TreeListItem을 수집
|
if (changedType == ChangedType.Name)
|
||||||
var currentUIChildren = new List<TreeListItem>();
|
{
|
||||||
for (int i = 0; i < childRoot.childCount; i++)
|
// 이름이 변경된 경우
|
||||||
{
|
if (valueText.text != data.Name)
|
||||||
var childItem = childRoot.GetChild(i).GetComponent<TreeListItem>();
|
|
||||||
if (childItem != null && childItem.Data != null)
|
|
||||||
{
|
{
|
||||||
currentUIChildren.Add(childItem);
|
valueText.text = data.Name;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
if (changedType == ChangedType.ResetChildren)
|
||||||
// 2️. 데이터와 UI의 자식 개수가 다르거나 순서가 다르면 동기화
|
|
||||||
bool needsReorder = false;
|
|
||||||
|
|
||||||
// 2-1️. 기본적인 개수 확인
|
|
||||||
if (currentUIChildren.Count != data.Children.Count)
|
|
||||||
{
|
{
|
||||||
needsReorder = true;
|
// 전체 리셋 처리
|
||||||
}
|
// 자식 모두 삭제 후 재생성
|
||||||
// 2-2️. 개수가 같으면 순서 확인
|
for (int i = childRoot.childCount - 1; i >= 0; i--)
|
||||||
else if (currentUIChildren.Count > 0)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < data.Children.Count; i++)
|
|
||||||
{
|
{
|
||||||
// UI 아이템의 데이터와 데이터 리스트의 순서가 다르면 재정렬 필요
|
var childItem = childRoot.GetChild(i).GetComponent<TreeListItem>();
|
||||||
if (currentUIChildren[i].Data != data.Children[i])
|
if (childItem != null)
|
||||||
{
|
{
|
||||||
needsReorder = true;
|
childItem.Delete(true);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 3️. 재정렬이 필요하면 전체 재구성
|
|
||||||
if (needsReorder)
|
|
||||||
{
|
|
||||||
// 데이터에는 있지만 UI에는 없는 자식 추가
|
|
||||||
var childrenToAdd = new List<TreeListItemData>();
|
|
||||||
foreach (var childData in data.Children)
|
foreach (var childData in data.Children)
|
||||||
{
|
|
||||||
bool uiChildExists = currentUIChildren.Any(ui => ui.Data == childData);
|
|
||||||
if (!uiChildExists)
|
|
||||||
{
|
|
||||||
childrenToAdd.Add(childData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UI에는 있지만 데이터에는 없는 자식 제거
|
|
||||||
var childrenToDestroy = new List<TreeListItem>();
|
|
||||||
foreach (var uiChild in currentUIChildren)
|
|
||||||
{
|
|
||||||
if (uiChild.Data != null && !data.Children.Contains(uiChild.Data))
|
|
||||||
{
|
|
||||||
childrenToDestroy.Add(uiChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 수집한 자식들 삭제
|
|
||||||
foreach (var child in childrenToDestroy)
|
|
||||||
{
|
|
||||||
child.Delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 새로운 자식 추가
|
|
||||||
foreach (var childData in childrenToAdd)
|
|
||||||
{
|
{
|
||||||
CreateItem(childData);
|
CreateItem(childData);
|
||||||
}
|
}
|
||||||
|
treeList.UpdateFlattenedItemDataList();
|
||||||
// 4️. 자식들을 데이터 순서대로 재정렬
|
}
|
||||||
// 현재 UI 자식들을 다시 수집 (추가/삭제 후이므로)
|
else if (changedType == ChangedType.AddChild)
|
||||||
var updatedUIChildren = new List<TreeListItem>();
|
{
|
||||||
for (int i = 0; i < childRoot.childCount; i++)
|
TreeListItem? item = treeList.AllItemFlattened.FirstOrDefault(x => x.Data == changedData);
|
||||||
|
if (item != null)
|
||||||
{
|
{
|
||||||
var childItem = childRoot.GetChild(i).GetComponent<TreeListItem>();
|
item.transform.SetParent(childRoot);
|
||||||
if (childItem != null && childItem.Data != null)
|
item.SetExpand();
|
||||||
{
|
}
|
||||||
updatedUIChildren.Add(childItem);
|
else
|
||||||
}
|
{
|
||||||
|
CreateItem(changedData);
|
||||||
|
}
|
||||||
|
UniTask.DelayFrame(1).ContinueWith(() =>
|
||||||
|
{
|
||||||
|
if (item != null) item.transform.SetAsLastSibling();
|
||||||
|
treeList.UpdateFlattenedItemDataList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (changedType == ChangedType.AddAtChild)
|
||||||
|
{
|
||||||
|
TreeListItem? item = treeList.AllItemFlattened.FirstOrDefault(x => x.Data == changedData);
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
item.transform.SetParent(childRoot);
|
||||||
|
item.SetExpand();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item = CreateItem(changedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 데이터 순서에 맞게 UI 자식들을 정렬
|
UniTask.DelayFrame(1).ContinueWith(() =>
|
||||||
for (int i = 0; i < data.Children.Count; i++)
|
|
||||||
{
|
{
|
||||||
var targetData = data.Children[i];
|
item.transform.SetSiblingIndex(index);
|
||||||
|
treeList.UpdateFlattenedItemDataList();
|
||||||
// 현재 위치의 UI 자식이 목표 데이터와 다르면 이동
|
});
|
||||||
if (updatedUIChildren[i].Data != targetData)
|
}
|
||||||
|
else if (changedType == ChangedType.RemoveChild)
|
||||||
|
{
|
||||||
|
var childItem = childRoot.GetChild(index).GetComponent<TreeListItem>();
|
||||||
|
if (childItem != null)
|
||||||
|
{
|
||||||
|
childItem.Delete(false);
|
||||||
|
UniTask.DelayFrame(1).ContinueWith(() =>
|
||||||
{
|
{
|
||||||
// 목표 데이터에 해당하는 UI 자식을 찾기
|
treeList.UpdateFlattenedItemDataList();
|
||||||
var targetUIChild = updatedUIChildren.FirstOrDefault(ui => ui.Data == targetData);
|
});
|
||||||
if (targetUIChild != null)
|
|
||||||
{
|
|
||||||
// 목표 위치로 이동 (SetSiblingIndex: 형제 중 순서 변경)
|
|
||||||
targetUIChild.transform.SetSiblingIndex(i);
|
|
||||||
|
|
||||||
// 로컬 리스트에서도 위치 업데이트
|
|
||||||
updatedUIChildren.Remove(targetUIChild);
|
|
||||||
updatedUIChildren.Insert(i, targetUIChild);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -655,7 +621,7 @@ namespace UVC.UI.List.Tree
|
|||||||
// 4️. 부모 TreeList에 클릭 정보 전달
|
// 4️. 부모 TreeList에 클릭 정보 전달
|
||||||
// TreeList는 이 정보를 받아서 선택 로직을 처리합니다.
|
// TreeList는 이 정보를 받아서 선택 로직을 처리합니다.
|
||||||
// (단일 선택 / 다중 선택 / 범위 선택 등)
|
// (단일 선택 / 다중 선택 / 범위 선택 등)
|
||||||
control.OnItemClicked(data, ctrlPressed, shiftPressed);
|
treeList.OnItemClicked(data, ctrlPressed, shiftPressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -690,12 +656,6 @@ namespace UVC.UI.List.Tree
|
|||||||
// ! 연산자: 반대로 변경 (true → false, false → true)
|
// ! 연산자: 반대로 변경 (true → false, false → true)
|
||||||
data!.IsExpanded = !data.IsExpanded;
|
data!.IsExpanded = !data.IsExpanded;
|
||||||
|
|
||||||
// 3️. 자식 컨테이너 표시/숨김
|
|
||||||
// IsExpanded가 true면 표시, false면 숨김
|
|
||||||
childContainer.SetActive(data.IsExpanded);
|
|
||||||
|
|
||||||
// 4️. 0.3초에 걸쳐 펼침/접힘 애니메이션 실행
|
|
||||||
SetExpand(0.3f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -719,34 +679,23 @@ namespace UVC.UI.List.Tree
|
|||||||
/// 애니메이션이 완료되면 호출되는 콜백입니다.
|
/// 애니메이션이 완료되면 호출되는 콜백입니다.
|
||||||
/// 람다 식(=>)으로 익명 함수를 정의합니다.
|
/// 람다 식(=>)으로 익명 함수를 정의합니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void SetExpand(float duration = 0.0f)
|
internal void SetExpand(float duration = 0.0f)
|
||||||
{
|
{
|
||||||
// 1️. 자식이 있는지 확인해서 펼침 버튼 표시 여부 결정
|
|
||||||
childExpand.gameObject.SetActive(childRoot.childCount > 0);
|
|
||||||
|
|
||||||
// 2️. 자식이 있는 경우에만 애니메이션 실행
|
// 펼침 버튼
|
||||||
if (childRoot.childCount > 0)
|
childExpand.gameObject.SetActive(data!.Children.Count > 0);
|
||||||
{
|
childContainer.SetActive(data!.Children.Count > 0 && data!.IsExpanded);
|
||||||
// UI 상태와 데이터 동기화
|
|
||||||
if (data != null) data.IsExpanded = childContainer.activeSelf == true;
|
|
||||||
// 3️. 화살표 회전 애니메이션 실행
|
|
||||||
// DORotate(목표 각도, 지속 시간)
|
|
||||||
// IsExpanded가 true면 0도 (▼), false면 90도 (▶)
|
|
||||||
childExpand.transform.DOKill();
|
|
||||||
childExpand.transform.DORotate(new Vector3(0, 0, data.IsExpanded ? 0 : 90), duration)
|
|
||||||
.OnComplete(() =>
|
|
||||||
{
|
|
||||||
// 4️. 애니메이션이 완료되면 플래그 리셋
|
|
||||||
// 이제 다시 ToggleChild() 호출 가능
|
|
||||||
isAnimating = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 자식이 없으면 IsExpanded는 항상 false
|
|
||||||
if (data != null) data.IsExpanded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// DORotate(목표 각도, 지속 시간)
|
||||||
|
// IsExpanded가 true면 0도 (▼), false면 90도 (▶)
|
||||||
|
childExpand.transform.DOKill();
|
||||||
|
childExpand.transform.DORotate(new Vector3(0, 0, data!.IsExpanded ? 0 : 90), duration)
|
||||||
|
.OnComplete(() =>
|
||||||
|
{
|
||||||
|
// 4️. 애니메이션이 완료되면 플래그 리셋
|
||||||
|
// 이제 다시 ToggleChild() 호출 가능
|
||||||
|
isAnimating = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -794,7 +743,7 @@ namespace UVC.UI.List.Tree
|
|||||||
/// - AddChild()에서 새 자식을 추가할 때
|
/// - AddChild()에서 새 자식을 추가할 때
|
||||||
///
|
///
|
||||||
/// 동작:
|
/// 동작:
|
||||||
/// 1. control.ItemPrefab를 childRoot 아래에 인스턴스화
|
/// 1. treeList.ItemPrefab를 childRoot 아래에 인스턴스화
|
||||||
/// 2. 생성된 item의 Init() 메서드 호출
|
/// 2. 생성된 item의 Init() 메서드 호출
|
||||||
/// 3. 생성된 item 반환
|
/// 3. 생성된 item 반환
|
||||||
///
|
///
|
||||||
@@ -816,15 +765,15 @@ namespace UVC.UI.List.Tree
|
|||||||
{
|
{
|
||||||
// 1️. 프리팹을 복제해서 새로운 TreeListItem 생성
|
// 1️. 프리팹을 복제해서 새로운 TreeListItem 생성
|
||||||
// Instantiate<T>(원본, 부모, 옵션)
|
// Instantiate<T>(원본, 부모, 옵션)
|
||||||
// control.ItemPrefab: UI 아이템 템플릿
|
// treeList.ItemPrefab: UI 아이템 템플릿
|
||||||
// childRoot: 새 아이템의 부모 Transform
|
// childRoot: 새 아이템의 부모 Transform
|
||||||
TreeListItem item = GameObject.Instantiate<TreeListItem>(
|
TreeListItem item = GameObject.Instantiate<TreeListItem>(
|
||||||
control.ItemPrefab, // 복제할 프리팹
|
treeList.ItemPrefab, // 복제할 프리팹
|
||||||
childRoot // 부모로 배치할 위치
|
childRoot // 부모로 배치할 위치
|
||||||
);
|
);
|
||||||
|
|
||||||
// 2️. 생성된 아이템 초기화
|
// 2️. 생성된 아이템 초기화
|
||||||
item.Init(data, control, control.DragDropManager);
|
item.Init(data, treeList, treeList.DragDropManager);
|
||||||
|
|
||||||
// 3️. 생성된 아이템 반환
|
// 3️. 생성된 아이템 반환
|
||||||
return item;
|
return item;
|
||||||
@@ -856,7 +805,7 @@ namespace UVC.UI.List.Tree
|
|||||||
/// 게임이 계속 실행되면서 메모리 사용량이 증가해서
|
/// 게임이 계속 실행되면서 메모리 사용량이 증가해서
|
||||||
/// 결국 게임이 느려지거나 충돌할 수 있습니다.
|
/// 결국 게임이 느려지거나 충돌할 수 있습니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Delete()
|
public void Delete(bool deleteData = false)
|
||||||
{
|
{
|
||||||
// 1️. 데이터 변경 이벤트 구독 해제
|
// 1️. 데이터 변경 이벤트 구독 해제
|
||||||
if (data != null)
|
if (data != null)
|
||||||
@@ -865,6 +814,8 @@ namespace UVC.UI.List.Tree
|
|||||||
data.OnDataChanged -= OnDataChanged;
|
data.OnDataChanged -= OnDataChanged;
|
||||||
data.OnSelectionChanged -= OnSelectionChanged;
|
data.OnSelectionChanged -= OnSelectionChanged;
|
||||||
data.Parent = null;
|
data.Parent = null;
|
||||||
|
if(deleteData) data.Dispose();
|
||||||
|
data = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2️. 버튼 클릭 이벤트 구독 해제
|
// 2️. 버튼 클릭 이벤트 구독 해제
|
||||||
@@ -908,6 +859,9 @@ namespace UVC.UI.List.Tree
|
|||||||
{
|
{
|
||||||
data.OnDataChanged -= OnDataChanged;
|
data.OnDataChanged -= OnDataChanged;
|
||||||
data.OnSelectionChanged -= OnSelectionChanged;
|
data.OnSelectionChanged -= OnSelectionChanged;
|
||||||
|
data.Parent = null;
|
||||||
|
data.Dispose();
|
||||||
|
data = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2️. 버튼 클릭 이벤트 구독 해제
|
// 2️. 버튼 클릭 이벤트 구독 해제
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace UVC.UI.List.Tree
|
|||||||
///
|
///
|
||||||
/// 이 클래스는 InfiniteScrollData를 상속하여 UI 스크롤 리스트와 연동됩니다.
|
/// 이 클래스는 InfiniteScrollData를 상속하여 UI 스크롤 리스트와 연동됩니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class TreeListItemData
|
public class TreeListItemData: IDisposable
|
||||||
{
|
{
|
||||||
#region 이벤트 (Events)
|
#region 이벤트 (Events)
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ namespace UVC.UI.List.Tree
|
|||||||
/// 사용 예:
|
/// 사용 예:
|
||||||
/// treeItem.OnDataChanged += (data) => Debug.Log("데이터 변경됨!");
|
/// treeItem.OnDataChanged += (data) => Debug.Log("데이터 변경됨!");
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action<TreeListItemData>? OnDataChanged;
|
public Action<ChangedType, TreeListItemData, int>? OnDataChanged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 선택 상태가 변경되었을 때 발생하는 이벤트입니다.
|
/// 선택 상태가 변경되었을 때 발생하는 이벤트입니다.
|
||||||
@@ -136,7 +136,7 @@ namespace UVC.UI.List.Tree
|
|||||||
if (_name != value)
|
if (_name != value)
|
||||||
{
|
{
|
||||||
_name = value;
|
_name = value;
|
||||||
NotifyDataChanged(); // UI에 변경을 알림
|
NotifyDataChanged(ChangedType.Name); // UI에 변경을 알림
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,7 +158,7 @@ namespace UVC.UI.List.Tree
|
|||||||
if (_option != value)
|
if (_option != value)
|
||||||
{
|
{
|
||||||
_option = value;
|
_option = value;
|
||||||
NotifyDataChanged();
|
NotifyDataChanged(ChangedType.Option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,7 +184,7 @@ namespace UVC.UI.List.Tree
|
|||||||
if (_isExpanded != value)
|
if (_isExpanded != value)
|
||||||
{
|
{
|
||||||
_isExpanded = value;
|
_isExpanded = value;
|
||||||
NotifyDataChanged(); // 트리 구조 UI 갱신
|
NotifyDataChanged(ChangedType.Expanded); // 트리 구조 UI 갱신
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,7 +261,7 @@ namespace UVC.UI.List.Tree
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
_children = value ?? new List<TreeListItemData>();
|
_children = value ?? new List<TreeListItemData>();
|
||||||
NotifyDataChanged();
|
NotifyDataChanged(ChangedType.ResetChildren);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,11 +344,18 @@ namespace UVC.UI.List.Tree
|
|||||||
{
|
{
|
||||||
child._parent = this;
|
child._parent = this;
|
||||||
_children.Add(child);
|
_children.Add(child);
|
||||||
NotifyDataChanged(); // UI에 트리 구조 변경 알림
|
NotifyDataChanged(ChangedType.AddChild, child); // UI에 트리 구조 변경 알림
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddChildAt(TreeListItemData child, int index)
|
||||||
|
{
|
||||||
|
child._parent = this;
|
||||||
|
_children.Insert(index, child);
|
||||||
|
NotifyDataChanged(ChangedType.AddAtChild, child, index); // UI에 트리 구조 변경 알림
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 이 아이템에서 지정된 자식 아이템을 제거합니다.
|
/// 이 아이템에서 지정된 자식 아이템을 자식 목록에서 제거하지만 아이템 자체는 삭제하지 않습니다.
|
||||||
///
|
///
|
||||||
/// 동작:
|
/// 동작:
|
||||||
/// 1. 자식을 _children 리스트에서 제거
|
/// 1. 자식을 _children 리스트에서 제거
|
||||||
@@ -371,8 +378,19 @@ namespace UVC.UI.List.Tree
|
|||||||
public void RemoveChild(TreeListItemData child)
|
public void RemoveChild(TreeListItemData child)
|
||||||
{
|
{
|
||||||
child._parent = null;
|
child._parent = null;
|
||||||
|
int index = _children.IndexOf(child);
|
||||||
_children.Remove(child);
|
_children.Remove(child);
|
||||||
NotifyDataChanged(); // UI에 트리 구조 변경 알림
|
NotifyDataChanged(ChangedType.RemoveChild, child, index); // UI에 트리 구조 변경 알림
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 이 아이템에서 지정된 자식 아이템을 자식 목록에서 제거하고 아이템 자체도 삭제합니다.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="child"></param>
|
||||||
|
public void DeleteChild(TreeListItemData child)
|
||||||
|
{
|
||||||
|
RemoveChild(child);
|
||||||
|
child.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -401,9 +419,10 @@ namespace UVC.UI.List.Tree
|
|||||||
foreach (var child in _children)
|
foreach (var child in _children)
|
||||||
{
|
{
|
||||||
child._parent = null;
|
child._parent = null;
|
||||||
|
child.Dispose();
|
||||||
}
|
}
|
||||||
_children.Clear();
|
_children.Clear();
|
||||||
NotifyDataChanged(); // UI에 트리 구조 변경 알림
|
NotifyDataChanged(ChangedType.ResetChildren); // UI에 트리 구조 변경 알림
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -424,11 +443,11 @@ namespace UVC.UI.List.Tree
|
|||||||
/// 왜 protected인가?
|
/// 왜 protected인가?
|
||||||
/// 이 클래스를 상속받은 자식 클래스에서도 호출할 수 있도록 하기 위함입니다.
|
/// 이 클래스를 상속받은 자식 클래스에서도 호출할 수 있도록 하기 위함입니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void NotifyDataChanged()
|
internal void NotifyDataChanged(ChangedType changedType, TreeListItemData? target = null, int index = -1)
|
||||||
{
|
{
|
||||||
// OnDataChanged가 등록되어 있으면 실행
|
// OnDataChanged가 등록되어 있으면 실행
|
||||||
// ?. 연산자: null이면 실행하지 않음 (null reference exception 방지)
|
// ?. 연산자: null이면 실행하지 않음 (null reference exception 방지)
|
||||||
OnDataChanged?.Invoke(this);
|
OnDataChanged?.Invoke(changedType, (target == null ? this : target), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -555,6 +574,32 @@ namespace UVC.UI.List.Tree
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if(OnDataChanged != null) OnDataChanged = null;
|
||||||
|
if(OnSelectionChanged != null) OnSelectionChanged = null;
|
||||||
|
if(OnClickAction != null) OnClickAction = null;
|
||||||
|
if(Children != null)
|
||||||
|
{
|
||||||
|
//foreach(var child in Children)
|
||||||
|
//{
|
||||||
|
// child.Dispose();
|
||||||
|
//}
|
||||||
|
Children.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ChangedType
|
||||||
|
{
|
||||||
|
Name,
|
||||||
|
Option,
|
||||||
|
Expanded,
|
||||||
|
ResetChildren,
|
||||||
|
AddChild,
|
||||||
|
AddAtChild,
|
||||||
|
RemoveChild
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -183,11 +183,6 @@ namespace UVC.UI.List.Tree
|
|||||||
|
|
||||||
// 드롭 위치 표시 업데이트
|
// 드롭 위치 표시 업데이트
|
||||||
UpdateDropIndicator(targetItem);
|
UpdateDropIndicator(targetItem);
|
||||||
|
|
||||||
if (targetItem != null)
|
|
||||||
{
|
|
||||||
Debug.Log($"[OnDrag] 드래그 중: {targetItem.Data?.Name ?? "Unknown"} 위에 있음");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -535,7 +530,7 @@ namespace UVC.UI.List.Tree
|
|||||||
{
|
{
|
||||||
Debug.Log($"[HandleDropSuccess] 루트로 이동");
|
Debug.Log($"[HandleDropSuccess] 루트로 이동");
|
||||||
MoveToRoot(draggedData);
|
MoveToRoot(draggedData);
|
||||||
treeList.UpdateFlattenedItemList();
|
treeList.UpdateFlattenedItemDataList();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,7 +563,7 @@ namespace UVC.UI.List.Tree
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
treeList.UpdateFlattenedItemList();
|
treeList.UpdateFlattenedItemDataList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -584,8 +579,8 @@ namespace UVC.UI.List.Tree
|
|||||||
// 하위 1/3: 아래
|
// 하위 1/3: 아래
|
||||||
|
|
||||||
var height = targetRect.rect.height;
|
var height = targetRect.rect.height;
|
||||||
var thresholdUpper = height * 0.2f;
|
var thresholdUpper = height * 0.3f;
|
||||||
var thresholdLower = height * 0.8f;
|
var thresholdLower = height * 0.7f;
|
||||||
|
|
||||||
// 월드 좌표에서 로컬 좌표로 변환
|
// 월드 좌표에서 로컬 좌표로 변환
|
||||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||||
@@ -597,7 +592,9 @@ namespace UVC.UI.List.Tree
|
|||||||
// 로컬 Y 좌표로 판단 (RectTransform의 피벗이 중앙이면 -height/2 ~ height/2)
|
// 로컬 Y 좌표로 판단 (RectTransform의 피벗이 중앙이면 -height/2 ~ height/2)
|
||||||
float relativeY = localMousePos.y;
|
float relativeY = localMousePos.y;
|
||||||
|
|
||||||
if (relativeY > thresholdUpper)
|
//Debug.Log($"GetDropPosition height:{height}, relativeY:{relativeY}, thresholdUpper:{thresholdUpper}, thresholdLower:{thresholdLower}");
|
||||||
|
|
||||||
|
if (relativeY > -thresholdUpper)
|
||||||
{
|
{
|
||||||
return DropPosition.Above;
|
return DropPosition.Above;
|
||||||
}
|
}
|
||||||
@@ -617,7 +614,7 @@ namespace UVC.UI.List.Tree
|
|||||||
private void MoveToRoot(TreeListItemData draggedData)
|
private void MoveToRoot(TreeListItemData draggedData)
|
||||||
{
|
{
|
||||||
// 기존 부모에서 제거
|
// 기존 부모에서 제거
|
||||||
RemoveFromParent(draggedData);
|
//RemoveFromParent(draggedData);
|
||||||
Debug.Log($"[MoveToRoot] {draggedData.Name}을(를) 루트로 이동");
|
Debug.Log($"[MoveToRoot] {draggedData.Name}을(를) 루트로 이동");
|
||||||
|
|
||||||
// ✅ 루트 레벨에 추가
|
// ✅ 루트 레벨에 추가
|
||||||
@@ -689,7 +686,7 @@ namespace UVC.UI.List.Tree
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void MoveAsChild(TreeListItemData draggedData, TreeListItemData targetData)
|
private void MoveAsChild(TreeListItemData draggedData, TreeListItemData targetData)
|
||||||
{
|
{
|
||||||
RemoveFromParent(draggedData);
|
//RemoveFromParent(draggedData);
|
||||||
targetData.AddChild(draggedData);
|
targetData.AddChild(draggedData);
|
||||||
Debug.Log($"[MoveAsChild] {draggedData.Name}을(를) {targetData.Name}의 자식으로 이동");
|
Debug.Log($"[MoveAsChild] {draggedData.Name}을(를) {targetData.Name}의 자식으로 이동");
|
||||||
}
|
}
|
||||||
@@ -699,16 +696,15 @@ namespace UVC.UI.List.Tree
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void MoveBefore(TreeListItemData draggedData, TreeListItemData targetData)
|
private void MoveBefore(TreeListItemData draggedData, TreeListItemData targetData)
|
||||||
{
|
{
|
||||||
var parentData = FindParentOfItem(draggedData);
|
var parentData = targetData.Parent;// FindParentOfItem(targetData);
|
||||||
RemoveFromParent(draggedData);
|
//RemoveFromParent(draggedData);
|
||||||
|
|
||||||
if (parentData != null)
|
if (parentData != null)
|
||||||
{
|
{
|
||||||
var targetIndex = parentData.Children.IndexOf(targetData);
|
var targetIndex = parentData.Children.IndexOf(targetData);
|
||||||
if (targetIndex >= 0)
|
if (targetIndex >= 0)
|
||||||
{
|
{
|
||||||
parentData.Children.Insert(targetIndex, draggedData);
|
parentData.AddChildAt(draggedData, targetIndex); // 자식으로 추가
|
||||||
parentData.NotifyDataChanged();
|
|
||||||
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 이동");
|
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 이동");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -734,16 +730,15 @@ namespace UVC.UI.List.Tree
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void MoveAfter(TreeListItemData draggedData, TreeListItemData targetData)
|
private void MoveAfter(TreeListItemData draggedData, TreeListItemData targetData)
|
||||||
{
|
{
|
||||||
var parentData = FindParentOfItem(draggedData);
|
var parentData = targetData.Parent;
|
||||||
RemoveFromParent(draggedData);
|
//RemoveFromParent(draggedData);
|
||||||
|
|
||||||
if (parentData != null)
|
if (parentData != null)
|
||||||
{
|
{
|
||||||
var targetIndex = parentData.Children.IndexOf(targetData);
|
var targetIndex = parentData.Children.IndexOf(targetData);
|
||||||
if (targetIndex >= 0)
|
if (targetIndex >= 0)
|
||||||
{
|
{
|
||||||
parentData.Children.Insert(targetIndex + 1, draggedData);
|
parentData.AddChildAt(draggedData, targetIndex + 1);
|
||||||
parentData.NotifyDataChanged();
|
|
||||||
Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 이동");
|
Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 이동");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -770,18 +765,17 @@ namespace UVC.UI.List.Tree
|
|||||||
private void RemoveFromParent(TreeListItemData item)
|
private void RemoveFromParent(TreeListItemData item)
|
||||||
{
|
{
|
||||||
|
|
||||||
var parent = FindParentOfItem(item);
|
Debug.Log($"[RemoveFromParent] {item.Name}을(를) 부모 {item.Parent == null}에서 제거");
|
||||||
Debug.Log($"[RemoveFromParent] {item.Name}을(를) 부모 {parent == null}에서 제거");
|
if (item.Parent != null)
|
||||||
if (parent != null)
|
|
||||||
{
|
{
|
||||||
parent.RemoveChild(item);
|
item.Parent.RemoveChild(item);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 루트 레벨에서 제거
|
// 루트 레벨에서 제거
|
||||||
treeList?.RemoveItem(item);
|
treeList?.RemoveItem(item);
|
||||||
}
|
}
|
||||||
treeList?.UpdateFlattenedItemList();
|
treeList?.UpdateFlattenedItemDataList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace UVC.UI.Modal
|
|||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// // 예시: 설정 초기화 전에 다국어로 확인을 받습니다.
|
/// // 예시: 설정 초기화 전에 다국어로 확인을 받습니다.
|
||||||
/// // titleLocalizationKey: "settings_reset_title" -> "설정 초기화" (한국어), "Reset Settings" (영어)
|
/// // titleLocalizationKey: "settings_reset_title" -> "설정 초기화" (한국어), "ResetChildren Settings" (영어)
|
||||||
/// // messageLocalizationKey: "settings_reset_confirm_message" -> "모든 설정을 초기화하시겠습니까?" (한국어), "Are you sure you want to reset all settings?" (영어)
|
/// // messageLocalizationKey: "settings_reset_confirm_message" -> "모든 설정을 초기화하시겠습니까?" (한국어), "Are you sure you want to reset all settings?" (영어)
|
||||||
///
|
///
|
||||||
/// bool confirmed = await Confirm.ShowLocalized(
|
/// bool confirmed = await Confirm.ShowLocalized(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
// using UnityEngine.UI; // Image 사용을 위해 필요할 수 있으나, 모델 클래스에서는 직접적인 UI 참조를 최소화하는 것이 좋음
|
// using UnityEngine.UI; // Image 사용을 위해 필요할 수 있으나, 모델 클래스에서는 직접적인 UI 참조를 최소화하는 것이 좋음
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ namespace UVC.UI.Toolbar.Model
|
|||||||
/// Tooltip = "tooltip_brush_small",
|
/// Tooltip = "tooltip_brush_small",
|
||||||
/// ClickCommand = new ActionCommand(() => Debug.Log("작은 브러시 선택됨"))
|
/// ClickCommand = new ActionCommand(() => Debug.Log("작은 브러시 선택됨"))
|
||||||
/// };
|
/// };
|
||||||
/// brushToolButton.SubButtons.Add(smallBrush);
|
/// brushToolButton.SubButtons.AddChild(smallBrush);
|
||||||
///
|
///
|
||||||
/// // 하위 버튼2: 중간 브러시
|
/// // 하위 버튼2: 중간 브러시
|
||||||
/// var mediumBrush = new ToolbarStandardButton
|
/// var mediumBrush = new ToolbarStandardButton
|
||||||
@@ -42,7 +42,7 @@ namespace UVC.UI.Toolbar.Model
|
|||||||
/// Tooltip = "tooltip_brush_medium",
|
/// Tooltip = "tooltip_brush_medium",
|
||||||
/// ClickCommand = new ActionCommand(() => Debug.Log("중간 브러시 선택됨"))
|
/// ClickCommand = new ActionCommand(() => Debug.Log("중간 브러시 선택됨"))
|
||||||
/// };
|
/// };
|
||||||
/// brushToolButton.SubButtons.Add(mediumBrush);
|
/// brushToolButton.SubButtons.AddChild(mediumBrush);
|
||||||
///
|
///
|
||||||
/// // 하위 버튼 선택 시 콜백 설정 (선택 사항)
|
/// // 하위 버튼 선택 시 콜백 설정 (선택 사항)
|
||||||
/// brushToolButton.OnSubButtonSelected = (selectedSub) =>
|
/// brushToolButton.OnSubButtonSelected = (selectedSub) =>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace UVC.UI.Toolbar.Model
|
|||||||
///
|
///
|
||||||
/// 사용 흐름:
|
/// 사용 흐름:
|
||||||
/// 1. Toolbar (또는 유사한 관리 클래스)에서 ToolbarModel의 인스턴스를 생성합니다.
|
/// 1. Toolbar (또는 유사한 관리 클래스)에서 ToolbarModel의 인스턴스를 생성합니다.
|
||||||
/// 2. 다양한 Add[ButtonType] 메서드 또는 AddItem 메서드를 호출하여 툴바 항목 모델들을 생성하고 ToolbarModel에 추가합니다.
|
/// 2. 다양한 AddChild[ButtonType] 메서드 또는 AddItem 메서드를 호출하여 툴바 항목 모델들을 생성하고 ToolbarModel에 추가합니다.
|
||||||
/// 3. 설정이 완료된 ToolbarModel 객체를 ToolbarView의 Initialize 메서드에 전달하여 UI를 렌더링하도록 합니다.
|
/// 3. 설정이 완료된 ToolbarModel 객체를 ToolbarView의 Initialize 메서드에 전달하여 UI를 렌더링하도록 합니다.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <example>
|
/// <example>
|
||||||
@@ -62,7 +62,7 @@ namespace UVC.UI.Toolbar.Model
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 툴바에 추가된 모든 항목(IToolbarItem)들의 리스트입니다.
|
/// 툴바에 추가된 모든 항목(IToolbarItem)들의 리스트입니다.
|
||||||
/// 이 리스트의 순서대로 툴바에 항목들이 표시됩니다.
|
/// 이 리스트의 순서대로 툴바에 항목들이 표시됩니다.
|
||||||
/// 외부에서는 읽기만 가능하도록 private set으로 설정되어 있으며, 항목 추가는 AddItem 또는 Add[ButtonType] 메서드를 통해 이루어집니다.
|
/// 외부에서는 읽기만 가능하도록 private set으로 설정되어 있으며, 항목 추가는 AddItem 또는 AddChild[ButtonType] 메서드를 통해 이루어집니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public System.Collections.Generic.List<IToolbarItem> Items { get; private set; }
|
public System.Collections.Generic.List<IToolbarItem> Items { get; private set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace UVC.UI.Toolbar.Model
|
namespace UVC.UI.Toolbar.Model
|
||||||
@@ -30,7 +30,7 @@ namespace UVC.UI.Toolbar.Model
|
|||||||
/// // if (!_radioGroups.TryGetValue(radioButton.GroupName, out var group))
|
/// // if (!_radioGroups.TryGetValue(radioButton.GroupName, out var group))
|
||||||
/// // {
|
/// // {
|
||||||
/// // group = new ToolbarRadioButtonGroup();
|
/// // group = new ToolbarRadioButtonGroup();
|
||||||
/// // _radioGroups.Add(radioButton.GroupName, group);
|
/// // _radioGroups.AddChild(radioButton.GroupName, group);
|
||||||
/// // }
|
/// // }
|
||||||
/// // group.RegisterButton(radioButton); // 라디오 버튼을 그룹에 등록
|
/// // group.RegisterButton(radioButton); // 라디오 버튼을 그룹에 등록
|
||||||
/// // radioButton.RadioGroup = group; // 버튼에 그룹 참조 설정
|
/// // radioButton.RadioGroup = group; // 버튼에 그룹 참조 설정
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UVC.UI.Toolbar.Model;
|
using UVC.UI.Toolbar.Model;
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ namespace UVC.UI.Toolbar.View
|
|||||||
/// // ToolbarView 내에서 이 프로세서가 사용되는 방식 (간략화된 예시):
|
/// // ToolbarView 내에서 이 프로세서가 사용되는 방식 (간략화된 예시):
|
||||||
/// // 1. ToolbarModel로부터 ToolbarExpandableButton 객체를 가져옵니다.
|
/// // 1. ToolbarModel로부터 ToolbarExpandableButton 객체를 가져옵니다.
|
||||||
/// // ToolbarExpandableButton expandableModel = new ToolbarExpandableButton { Text = "Brush", ... };
|
/// // ToolbarExpandableButton expandableModel = new ToolbarExpandableButton { Text = "Brush", ... };
|
||||||
/// // expandableModel.SubButtons.Add(new ToolbarStandardButton { Text = "Small Brush", ... });
|
/// // expandableModel.SubButtons.AddChild(new ToolbarStandardButton { Text = "Small Brush", ... });
|
||||||
///
|
///
|
||||||
/// // 2. ToolbarView는 해당 모델 타입에 맞는 Processor를 찾습니다.
|
/// // 2. ToolbarView는 해당 모델 타입에 맞는 Processor를 찾습니다.
|
||||||
/// // IButtonViewProcessor processor = GetButtonViewProcessor(typeof(ToolbarExpandableButton));
|
/// // IButtonViewProcessor processor = GetButtonViewProcessor(typeof(ToolbarExpandableButton));
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
@@ -23,7 +23,7 @@ public class ReadmeEditor : Editor
|
|||||||
|
|
||||||
static void RemoveTutorial()
|
static void RemoveTutorial()
|
||||||
{
|
{
|
||||||
if (EditorUtility.DisplayDialog("Remove Readme Assets",
|
if (EditorUtility.DisplayDialog("RemoveChild Readme Assets",
|
||||||
|
|
||||||
$"All contents under {s_ReadmeSourceDirectory} will be removed, are you sure you want to proceed?",
|
$"All contents under {s_ReadmeSourceDirectory} will be removed, are you sure you want to proceed?",
|
||||||
"Proceed",
|
"Proceed",
|
||||||
@@ -148,7 +148,7 @@ public class ReadmeEditor : Editor
|
|||||||
GUILayout.Space(k_Space);
|
GUILayout.Space(k_Space);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GUILayout.Button("Remove Readme Assets", ButtonStyle))
|
if (GUILayout.Button("RemoveChild Readme Assets", ButtonStyle))
|
||||||
{
|
{
|
||||||
RemoveTutorial();
|
RemoveTutorial();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user