feat: PropertyWindow 상호작용 및 Twin Agent 프로세스 관리 개선
## PropertyWindow 상호작용 개선 - 바닥 클릭 시 PropertyWindow 내용 유지 (선택 해제만) - 같은 엔티티 재선택 시 현재 탭 유지 - 다른 엔티티 선택 시 이벤트 구독 명시적 해제로 메모리 누수 방지 - 중복 탭 방지 로직 추가 (Clear()에서 탭도 함께 제거) ## Twin Agent Auto 프로세스 관리 - 프로세스 상태 관리 (IsRunning, IsCompleted, IsCanceled) - 프로세스 진행 상태 추적 및 복원 기능 (_stepStates) - 백그라운드 실행 지원 (다른 엔티티 선택 시에도 계속 실행) - Cancel 시 즉시 중단 (CancellationToken 전달) - Cancel 시 현재 항목 "Canceled" 표시 및 주황색 강조 - Cancel 후 Run 시 자동 초기화 ## UI 개선 - Run/Cancel 버튼 동적 토글 (ButtonProperty.ButtonText 이벤트) - 프로세스 상태에 따른 UI 복원 (RestoreUIState) - 이벤트 핸들러 명시적 관리로 안정성 향상 Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,68 +1,5 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &269913993450539115
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 9090953805938921716}
|
||||
- component: {fileID: 7230928934374286078}
|
||||
m_Layer: 5
|
||||
m_Name: buttons
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &9090953805938921716
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 269913993450539115}
|
||||
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:
|
||||
- {fileID: 4618630843252738151}
|
||||
m_Father: {fileID: 8627520046702523630}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 1, y: 0.5}
|
||||
m_AnchorMax: {x: 1, y: 0.5}
|
||||
m_AnchoredPosition: {x: -12, y: 0}
|
||||
m_SizeDelta: {x: 80, y: 22}
|
||||
m_Pivot: {x: 1, y: 0.5}
|
||||
--- !u!114 &7230928934374286078
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 269913993450539115}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Padding:
|
||||
m_Left: 0
|
||||
m_Right: 0
|
||||
m_Top: 0
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 5
|
||||
m_Spacing: 4
|
||||
m_ChildForceExpandWidth: 0
|
||||
m_ChildForceExpandHeight: 0
|
||||
m_ChildControlWidth: 0
|
||||
m_ChildControlHeight: 0
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!1 &1602519165350808158
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -76,6 +13,8 @@ GameObject:
|
||||
- component: {fileID: 8243371294842205870}
|
||||
- component: {fileID: 7952136475300671546}
|
||||
- component: {fileID: 2135820803340931774}
|
||||
- component: {fileID: 7834628867600740810}
|
||||
- component: {fileID: 1121243353173408875}
|
||||
m_Layer: 5
|
||||
m_Name: PropertyWindow
|
||||
m_TagString: Untagged
|
||||
@@ -96,7 +35,7 @@ RectTransform:
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 8627520046702523630}
|
||||
- {fileID: 2356082699321362940}
|
||||
- {fileID: 666676363614517562}
|
||||
- {fileID: 1226053771744685714}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
@@ -126,6 +65,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
_view: {fileID: 7952136475300671546}
|
||||
_tabView: {fileID: 7834628867600740810}
|
||||
--- !u!114 &7952136475300671546
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -155,6 +95,8 @@ MonoBehaviour:
|
||||
_dateRangePropertyPrefab: {fileID: 6043687085342628170, guid: e71306480d7b2564598f831a2092581d, type: 3}
|
||||
_dateTimeRangePropertyPrefab: {fileID: 7433683561883899171, guid: aefa6eef8bc142b42bf9eb0413d0f08f, type: 3}
|
||||
_colorStatePropertyPrefab: {fileID: 594329095134119449, guid: 20057cedcc15d744e970f5bcef773a05, type: 3}
|
||||
_buttonPropertyPrefab: {fileID: 0}
|
||||
_labelPropertyPrefab: {fileID: 0}
|
||||
--- !u!114 &2135820803340931774
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -185,6 +127,113 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!114 &7834628867600740810
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1602519165350808158}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 8ad4c10a9bdb92244a68c6269e11fe03, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::UVC.UI.Window.PropertyWindow.PropertyTabView
|
||||
_tabContainer: {fileID: 3895350603835143446}
|
||||
_tabButtonPrefab: {fileID: 5817941051672006636, guid: c52761060ad8f2c45b4783fca02a4b95, type: 3}
|
||||
_selectedColor: {r: 0.509434, g: 0.509434, b: 0.509434, a: 1}
|
||||
_normalColor: {r: 0.15, g: 0.15, b: 0.15, a: 0}
|
||||
_hoverColor: {r: 0.25, g: 0.25, b: 0.25, a: 1}
|
||||
_normalTextColor: {r: 0.7735849, g: 0.7735849, b: 0.7735849, a: 1}
|
||||
_selectedTextColor: {r: 0, g: 1, b: 0.3195498, a: 1}
|
||||
--- !u!114 &1121243353173408875
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1602519165350808158}
|
||||
m_Enabled: 0
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.VerticalLayoutGroup
|
||||
m_Padding:
|
||||
m_Left: 4
|
||||
m_Right: 0
|
||||
m_Top: 0
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 0
|
||||
m_Spacing: 1
|
||||
m_ChildForceExpandWidth: 1
|
||||
m_ChildForceExpandHeight: 0
|
||||
m_ChildControlWidth: 1
|
||||
m_ChildControlHeight: 0
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!1 &2452132584805859615
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3895350603835143446}
|
||||
- component: {fileID: 5072967231822505595}
|
||||
m_Layer: 5
|
||||
m_Name: TabContainer
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &3895350603835143446
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2452132584805859615}
|
||||
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: 8627520046702523630}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: -16}
|
||||
m_SizeDelta: {x: 260, y: 32}
|
||||
m_Pivot: {x: 0, y: 0.5}
|
||||
--- !u!114 &5072967231822505595
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2452132584805859615}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.HorizontalLayoutGroup
|
||||
m_Padding:
|
||||
m_Left: 1
|
||||
m_Right: 1
|
||||
m_Top: 0
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 3
|
||||
m_Spacing: 0
|
||||
m_ChildForceExpandWidth: 0
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildControlWidth: 0
|
||||
m_ChildControlHeight: 1
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!1 &2543418585224058098
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -291,11 +340,11 @@ RectTransform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 9090953805938921716}
|
||||
m_Father: {fileID: 8627520046702523630}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_AnchorMin: {x: 1, y: 1}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: -22, y: -16}
|
||||
m_SizeDelta: {x: 22, y: 22}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &4044982756471701802
|
||||
@@ -392,142 +441,6 @@ MonoBehaviour:
|
||||
m_StringArgument:
|
||||
m_BoolArgument: 0
|
||||
m_CallState: 2
|
||||
--- !u!1 &4365271205290706374
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 6688510942695995059}
|
||||
- component: {fileID: 5170429802813097353}
|
||||
- component: {fileID: 4193667190773534540}
|
||||
m_Layer: 5
|
||||
m_Name: Text (TMP)
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &6688510942695995059
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4365271205290706374}
|
||||
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: 8627520046702523630}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0.5}
|
||||
m_AnchorMax: {x: 0, y: 0.5}
|
||||
m_AnchoredPosition: {x: 20, y: 0}
|
||||
m_SizeDelta: {x: 184, y: 24}
|
||||
m_Pivot: {x: 0, y: 0.5}
|
||||
--- !u!222 &5170429802813097353
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4365271205290706374}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &4193667190773534540
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4365271205290706374}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: PROPERTIES
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: d1fa8a1da59a4de4485cae7c4f9c196b, type: 2}
|
||||
m_sharedMaterial: {fileID: -6974119170906569483, guid: d1fa8a1da59a4de4485cae7c4f9c196b, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4291611852
|
||||
m_fontColor: {r: 0.8, g: 0.8, b: 0.8, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 11
|
||||
m_fontSizeBase: 11
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 1
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!1 &4849192001222621641
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -682,14 +595,14 @@ RectTransform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 6688510942695995059}
|
||||
- {fileID: 9090953805938921716}
|
||||
- {fileID: 3895350603835143446}
|
||||
- {fileID: 4618630843252738151}
|
||||
m_Father: {fileID: 8065352563668446013}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 300, y: 32}
|
||||
m_AnchoredPosition: {x: 4, y: 0}
|
||||
m_SizeDelta: {x: 296, y: 30}
|
||||
m_Pivot: {x: 0, y: 1}
|
||||
--- !u!1 &5452038161345497601
|
||||
GameObject:
|
||||
@@ -858,68 +771,6 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &7729491783646672551
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2356082699321362940}
|
||||
- component: {fileID: 3182475191728020799}
|
||||
m_Layer: 5
|
||||
m_Name: TabButton
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &2356082699321362940
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7729491783646672551}
|
||||
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: 8065352563668446013}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: -36}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0, y: 1}
|
||||
--- !u!114 &3182475191728020799
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 7729491783646672551}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Padding:
|
||||
m_Left: 0
|
||||
m_Right: 0
|
||||
m_Top: 0
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 0
|
||||
m_Spacing: 0
|
||||
m_ChildForceExpandWidth: 1
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildControlWidth: 0
|
||||
m_ChildControlHeight: 0
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!1 &8183298300838906344
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -956,6 +807,142 @@ RectTransform:
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: -20, y: -20}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!1 &9059355695897963546
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 666676363614517562}
|
||||
- component: {fileID: 7965459624692700836}
|
||||
- component: {fileID: 7484838650388706672}
|
||||
m_Layer: 5
|
||||
m_Name: EntityName
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &666676363614517562
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9059355695897963546}
|
||||
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: 8065352563668446013}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 152, y: -41}
|
||||
m_SizeDelta: {x: 296, y: 20}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &7965459624692700836
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9059355695897963546}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &7484838650388706672
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 9059355695897963546}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_text: New Text
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 4c27cf40bc2401749a123f8482e9481c, type: 2}
|
||||
m_sharedMaterial: {fileID: -7219741691839801200, guid: 4c27cf40bc2401749a123f8482e9481c, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
m_fontMaterials: []
|
||||
m_fontColor32:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_enableVertexGradient: 0
|
||||
m_colorMode: 3
|
||||
m_fontColorGradient:
|
||||
topLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
topRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
|
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_fontColorGradientPreset: {fileID: 0}
|
||||
m_spriteAsset: {fileID: 0}
|
||||
m_tintAllSprites: 0
|
||||
m_StyleSheet: {fileID: 0}
|
||||
m_TextStyleHashCode: -1183493901
|
||||
m_overrideHtmlColors: 0
|
||||
m_faceColor:
|
||||
serializedVersion: 2
|
||||
rgba: 4294967295
|
||||
m_fontSize: 14
|
||||
m_fontSizeBase: 14
|
||||
m_fontWeight: 400
|
||||
m_enableAutoSizing: 0
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 1
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
m_wordSpacing: 0
|
||||
m_lineSpacing: 0
|
||||
m_lineSpacingMax: 0
|
||||
m_paragraphSpacing: 0
|
||||
m_charWidthMaxAdj: 0
|
||||
m_TextWrappingMode: 1
|
||||
m_wordWrappingRatios: 0.4
|
||||
m_overflowMode: 0
|
||||
m_linkedTextComponent: {fileID: 0}
|
||||
parentLinkedComponent: {fileID: 0}
|
||||
m_enableKerning: 0
|
||||
m_ActiveFontFeatures: 6e72656b
|
||||
m_enableExtraPadding: 0
|
||||
checkPaddingRequired: 0
|
||||
m_isRichText: 1
|
||||
m_EmojiFallbackSupport: 1
|
||||
m_parseCtrlCharacters: 1
|
||||
m_isOrthographic: 1
|
||||
m_isCullingEnabled: 0
|
||||
m_horizontalMapping: 0
|
||||
m_verticalMapping: 0
|
||||
m_uvLineOffset: 0
|
||||
m_geometrySortingOrder: 0
|
||||
m_IsTextObjectScaleStatic: 0
|
||||
m_VertexBufferAutoSizeReduction: 0
|
||||
m_useMaxVisibleDescender: 1
|
||||
m_pageToDisplay: 1
|
||||
m_margin: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_isUsingLegacyAnimationComponent: 0
|
||||
m_isVolumetricText: 0
|
||||
m_hasFontAssetChanged: 0
|
||||
m_baseMaterial: {fileID: 0}
|
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
|
||||
--- !u!1 &9121451219229106185
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -991,10 +978,10 @@ RectTransform:
|
||||
- {fileID: 2173520677932010222}
|
||||
m_Father: {fileID: 8065352563668446013}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: -40}
|
||||
m_SizeDelta: {x: 0, y: -40}
|
||||
m_AnchorMin: {x: 0, y: 1}
|
||||
m_AnchorMax: {x: 0, y: 1}
|
||||
m_AnchoredPosition: {x: 4, y: -52}
|
||||
m_SizeDelta: {x: 296, y: 948}
|
||||
m_Pivot: {x: 0, y: 1}
|
||||
--- !u!114 &407164550142461589
|
||||
MonoBehaviour:
|
||||
|
||||
@@ -30,7 +30,7 @@ RectTransform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 6948320696978959352}
|
||||
m_Father: {fileID: 5584966427811880162}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
@@ -235,7 +235,7 @@ MonoBehaviour:
|
||||
m_fontSizeMin: 18
|
||||
m_fontSizeMax: 72
|
||||
m_fontStyle: 0
|
||||
m_HorizontalAlignment: 1
|
||||
m_HorizontalAlignment: 4
|
||||
m_VerticalAlignment: 512
|
||||
m_textAlignment: 65535
|
||||
m_characterSpacing: 0
|
||||
@@ -303,7 +303,7 @@ RectTransform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 6948320696978959352}
|
||||
m_Father: {fileID: 5584966427811880162}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
@@ -432,8 +432,8 @@ GameObject:
|
||||
- component: {fileID: 6948320696978959352}
|
||||
- component: {fileID: 4253558289765446409}
|
||||
- component: {fileID: 1001481568101346305}
|
||||
- component: {fileID: 1283532448571143673}
|
||||
- component: {fileID: 8169199501776635067}
|
||||
- component: {fileID: 3768747238768808699}
|
||||
m_Layer: 5
|
||||
m_Name: LabelPropertyUI
|
||||
m_TagString: Untagged
|
||||
@@ -453,8 +453,7 @@ RectTransform:
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1356120985410992881}
|
||||
- {fileID: 4879897783975719760}
|
||||
- {fileID: 5584966427811880162}
|
||||
- {fileID: 6020519455540207131}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
@@ -495,7 +494,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 266dd70132eff3d4eb32c995c009634a, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!114 &1283532448571143673
|
||||
--- !u!114 &8169199501776635067
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@@ -504,6 +503,85 @@ MonoBehaviour:
|
||||
m_GameObject: {fileID: 2484066679782419758}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a5bffbcbfc3cc8640851dadcc462cfe3, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::UVC.UI.Window.PropertyWindow.UI.LabelPropertyUI
|
||||
_nameLabel: {fileID: 7734407643640775980}
|
||||
_descriptionLabel: {fileID: 2134895009375913828}
|
||||
_valueLabel: {fileID: 4280685791673950716}
|
||||
--- !u!114 &3768747238768808699
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2484066679782419758}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.HorizontalLayoutGroup
|
||||
m_Padding:
|
||||
m_Left: 0
|
||||
m_Right: 16
|
||||
m_Top: 0
|
||||
m_Bottom: 0
|
||||
m_ChildAlignment: 3
|
||||
m_Spacing: 0
|
||||
m_ChildForceExpandWidth: 1
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildControlWidth: 1
|
||||
m_ChildControlHeight: 0
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!1 &8339854047593615139
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 5584966427811880162}
|
||||
- component: {fileID: 3079212287028168853}
|
||||
m_Layer: 5
|
||||
m_Name: GameObject
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &5584966427811880162
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8339854047593615139}
|
||||
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:
|
||||
- {fileID: 1356120985410992881}
|
||||
- {fileID: 4879897783975719760}
|
||||
m_Father: {fileID: 6948320696978959352}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 16}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!114 &3079212287028168853
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 8339854047593615139}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.HorizontalLayoutGroup
|
||||
@@ -521,18 +599,3 @@ MonoBehaviour:
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!114 &8169199501776635067
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2484066679782419758}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a5bffbcbfc3cc8640851dadcc462cfe3, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::UVC.UI.Window.PropertyWindow.UI.LabelPropertyUI
|
||||
_nameLabel: {fileID: 7734407643640775980}
|
||||
_descriptionLabel: {fileID: 2134895009375913828}
|
||||
_valueLabel: {fileID: 4280685791673950716}
|
||||
|
||||
@@ -12,7 +12,18 @@ namespace UVC.Entity
|
||||
/// <summary>
|
||||
/// 프로세서의 고유 ID
|
||||
/// </summary>
|
||||
string ProcessorId { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 프로세스가 현재 실행 중인지 여부
|
||||
/// </summary>
|
||||
bool IsRunning { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 프로세스가 완료되었는지 여부
|
||||
/// </summary>
|
||||
bool IsCompleted { get; }
|
||||
string ProcessorId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 프로세서를 초기화합니다.
|
||||
@@ -24,6 +35,17 @@ namespace UVC.Entity
|
||||
/// <summary>
|
||||
/// 프로세서의 주요 작업을 실행합니다.
|
||||
/// </summary>
|
||||
UniTask Execute();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 프로세스를 취소합니다.
|
||||
/// </summary>
|
||||
void Cancel();
|
||||
|
||||
/// <summary>
|
||||
/// 프로세스를 초기 상태로 되돌립니다.
|
||||
/// </summary>
|
||||
void Reset();
|
||||
UniTask Execute();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,25 @@ namespace UVC.Entity.Processors
|
||||
public class TwinAgentAutoProcessor : IEntityProcessor
|
||||
{
|
||||
private Entity _entity;
|
||||
|
||||
private System.Threading.CancellationTokenSource _cancellationTokenSource;
|
||||
private bool _isRunning = false;
|
||||
private bool _isCompleted = false;
|
||||
private bool _isCanceled = false;
|
||||
private Dictionary<string, IPropertyItem> _propertyItems;
|
||||
|
||||
public string ProcessorId => "twin_agent_auto";
|
||||
/// <summary>
|
||||
/// 완료된 단계들의 상태 (PropertyId -> (Value, Color))
|
||||
/// UI 복원 시 사용됩니다.
|
||||
/// </summary>
|
||||
private Dictionary<string, (string value, Color? color, bool isVisible)> _stepStates
|
||||
= new Dictionary<string, (string, Color?, bool)>();
|
||||
|
||||
|
||||
|
||||
public bool IsRunning => _isRunning;
|
||||
public bool IsCompleted => _isCompleted;
|
||||
public string ProcessorId => "twin_agent_auto";
|
||||
|
||||
public void Initialize(Entity entity, Dictionary<string, IPropertyItem> propertyItems)
|
||||
{
|
||||
@@ -22,17 +38,61 @@ namespace UVC.Entity.Processors
|
||||
_propertyItems = propertyItems;
|
||||
}
|
||||
|
||||
public async UniTask Execute()
|
||||
public async UniTask Execute()
|
||||
{
|
||||
// 이미 실행 중이면 무시
|
||||
if (_isRunning)
|
||||
{
|
||||
Debug.LogWarning("[TwinAgentAutoProcessor] 이미 프로세스가 실행 중입니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 완료되었거나 취소된 프로세스를 다시 실행하면 초기화
|
||||
if (_isCompleted || _isCanceled)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
_isRunning = true;
|
||||
_isCompleted = false;
|
||||
_isCanceled = false;
|
||||
_cancellationTokenSource = new System.Threading.CancellationTokenSource();
|
||||
|
||||
Debug.Log("[TwinAgentAutoProcessor] Auto 프로세스 시작");
|
||||
|
||||
// 0. Read Entity
|
||||
await RunReadEntity();
|
||||
try
|
||||
{
|
||||
// 0. Read Entity
|
||||
await RunReadEntity();
|
||||
|
||||
// 1. Connection
|
||||
await RunConnection();
|
||||
// 취소 체크
|
||||
if (_cancellationTokenSource.Token.IsCancellationRequested)
|
||||
{
|
||||
Debug.Log("[TwinAgentAutoProcessor] 프로세스 취소됨");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("[TwinAgentAutoProcessor] Auto 프로세스 완료");
|
||||
// 1. Connection
|
||||
await RunConnection();
|
||||
|
||||
// 취소 체크
|
||||
if (_cancellationTokenSource.Token.IsCancellationRequested)
|
||||
{
|
||||
Debug.Log("[TwinAgentAutoProcessor] 프로세스 취소됨");
|
||||
return;
|
||||
}
|
||||
|
||||
_isCompleted = true;
|
||||
Debug.Log("[TwinAgentAutoProcessor] Auto 프로세스 완료");
|
||||
}
|
||||
catch (System.OperationCanceledException)
|
||||
{
|
||||
Debug.Log("[TwinAgentAutoProcessor] 프로세스 취소됨");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
#region 0. Read Entity
|
||||
@@ -207,16 +267,21 @@ namespace UVC.Entity.Processors
|
||||
{
|
||||
string partial = statusText.Substring(0, i);
|
||||
item.SetValue(partial);
|
||||
await UniTask.Delay(30); // 30ms마다 한 글자
|
||||
await UniTask.Delay(15, cancellationToken: _cancellationTokenSource.Token); // 취소 가능
|
||||
}
|
||||
|
||||
// 2. "Done"이면 텍스트 색상 초록색으로 변경
|
||||
Color? color = null;
|
||||
if (statusText == "Done" && item is LabelProperty labelProp)
|
||||
{
|
||||
labelProp.TextColor = Color.green;
|
||||
item.SetValue(statusText); // 색상 적용을 위해 다시 설정
|
||||
color = Color.green;
|
||||
}
|
||||
|
||||
// 3. 진행 상태 저장 (UI 복원용)
|
||||
_stepStates[propertyId] = (statusText, color, item.IsVisible);
|
||||
|
||||
Debug.Log($"[TwinAgentAutoProcessor] {propertyId}: {statusText}");
|
||||
}
|
||||
|
||||
@@ -228,15 +293,145 @@ namespace UVC.Entity.Processors
|
||||
if (_propertyItems.TryGetValue(nextPropertyId, out var nextItem))
|
||||
{
|
||||
nextItem.IsVisible = true;
|
||||
|
||||
// 가시성 상태 저장
|
||||
if (_stepStates.ContainsKey(nextPropertyId))
|
||||
{
|
||||
var state = _stepStates[nextPropertyId];
|
||||
_stepStates[nextPropertyId] = (state.value, state.color, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_stepStates[nextPropertyId] = ("-", null, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 무작위 시간 대기 (1~3초) + 점 애니메이션
|
||||
/// </summary>
|
||||
private async UniTask RandomDelay()
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cancel and Reset
|
||||
|
||||
/// <summary>
|
||||
/// 프로세스를 취소합니다.
|
||||
/// </summary>
|
||||
public void Cancel()
|
||||
{
|
||||
float delay = Random.Range(1f, 3f);
|
||||
if (_isRunning && _cancellationTokenSource != null)
|
||||
{
|
||||
_isCanceled = true;
|
||||
_cancellationTokenSource.Cancel();
|
||||
|
||||
// 현재 진행 중인 항목 찾기 (마지막으로 업데이트된 항목)
|
||||
string canceledPropertyId = null;
|
||||
foreach (var kvp in _propertyItems)
|
||||
{
|
||||
var value = kvp.Value.GetValue();
|
||||
if (value != null && value.ToString() != "-" && !value.ToString().EndsWith("Done") && value.ToString() != "Canceled")
|
||||
{
|
||||
canceledPropertyId = kvp.Key;
|
||||
|
||||
// 현재 진행 중인 항목을 "Canceled"로 변경
|
||||
kvp.Value.SetValue("Canceled");
|
||||
|
||||
if (kvp.Value is LabelProperty labelProp)
|
||||
{
|
||||
labelProp.TextColor = new UnityEngine.Color(1f, 0.647f, 0f); // 주황색 (Orange)
|
||||
// 색상 적용을 위해 다시 SetValue 호출
|
||||
kvp.Value.SetValue("Canceled");
|
||||
}
|
||||
|
||||
// 취소 상태 저장
|
||||
_stepStates[kvp.Key] = ("Canceled", new UnityEngine.Color(1f, 0.647f, 0f), kvp.Value.IsVisible);
|
||||
|
||||
break; // 첫 번째 항목만 처리
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"[TwinAgentAutoProcessor] 취소 요청 (항목: {canceledPropertyId})");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 프로세스를 초기 상태로 되돌립니다.
|
||||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
_isRunning = false;
|
||||
_isCompleted = false;
|
||||
_isCanceled = false;
|
||||
|
||||
if (_cancellationTokenSource != null)
|
||||
{
|
||||
_cancellationTokenSource.Dispose();
|
||||
_cancellationTokenSource = null;
|
||||
}
|
||||
|
||||
// 진행 상태 초기화
|
||||
_stepStates.Clear();
|
||||
|
||||
// 모든 PropertyItem 값을 초기화
|
||||
foreach (var kvp in _propertyItems)
|
||||
{
|
||||
kvp.Value.SetValue("-");
|
||||
kvp.Value.IsVisible = false;
|
||||
|
||||
// 색상 초기화 (LabelProperty인 경우)
|
||||
if (kvp.Value is LabelProperty labelProp)
|
||||
{
|
||||
labelProp.TextColor = UnityEngine.Color.white;
|
||||
}
|
||||
}
|
||||
|
||||
// 첫 번째 항목만 표시
|
||||
if (_propertyItems.ContainsKey("get_entity_info_status"))
|
||||
{
|
||||
_propertyItems["get_entity_info_status"].IsVisible = true;
|
||||
_stepStates["get_entity_info_status"] = ("-", null, true);
|
||||
}
|
||||
|
||||
Debug.Log("[TwinAgentAutoProcessor] 초기화 완료");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 저장된 진행 상태를 새로운 PropertyItem들에 복원합니다.
|
||||
/// PropertyWindow가 다시 열릴 때 호출됩니다.
|
||||
/// </summary>
|
||||
public void RestoreUIState(Dictionary<string, IPropertyItem> newPropertyItems)
|
||||
{
|
||||
_propertyItems = newPropertyItems;
|
||||
|
||||
// 저장된 상태를 새 PropertyItem들에 복원
|
||||
foreach (var kvp in _stepStates)
|
||||
{
|
||||
string propertyId = kvp.Key;
|
||||
var (value, color, isVisible) = kvp.Value;
|
||||
|
||||
if (_propertyItems.TryGetValue(propertyId, out var item))
|
||||
{
|
||||
item.SetValue(value);
|
||||
item.IsVisible = isVisible;
|
||||
|
||||
if (color.HasValue && item is LabelProperty labelProp)
|
||||
{
|
||||
labelProp.TextColor = color.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"[TwinAgentAutoProcessor] UI 상태 복원 완료 (IsRunning: {_isRunning}, IsCompleted: {_isCompleted})");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods (Existing)
|
||||
private async UniTask RandomDelay()
|
||||
{
|
||||
float delay = Random.Range(1f, 2f);
|
||||
int totalMs = (int)(delay * 1000);
|
||||
int dotInterval = 300; // 300ms마다 점 추가
|
||||
int elapsed = 0;
|
||||
@@ -267,7 +462,7 @@ namespace UVC.Entity.Processors
|
||||
currentItem.SetValue(baseText + dots);
|
||||
|
||||
dotCount = (dotCount % 3) + 1;
|
||||
await UniTask.Delay(dotInterval);
|
||||
await UniTask.Delay(dotInterval, cancellationToken: _cancellationTokenSource.Token); // 취소 가능
|
||||
elapsed += dotInterval;
|
||||
}
|
||||
|
||||
@@ -276,7 +471,7 @@ namespace UVC.Entity.Processors
|
||||
}
|
||||
else
|
||||
{
|
||||
await UniTask.Delay(totalMs);
|
||||
await UniTask.Delay(totalMs, cancellationToken: _cancellationTokenSource.Token); // 취소 가능
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,8 +91,8 @@ namespace UVC.Studio.Manager
|
||||
return;
|
||||
}
|
||||
|
||||
// RTScene을 사용한 레이캐스트 (Collider 없이 MeshRenderer로 감지)
|
||||
//ToDo -> pickobject 레이어 설정 영민 프로 작업하셈
|
||||
// RTScene을 사용한 레이캠스트 (Collider 없이 MeshRenderer로 감지)
|
||||
//ToDo -> pickobject 레이어 설정 영민 프로 작업하션
|
||||
var pickedObject = PickObject();
|
||||
Debug.Log($"[SelectionInputHandler] Picked Object: {(pickedObject != null ? pickedObject.name : "None")}");
|
||||
|
||||
@@ -107,12 +107,13 @@ namespace UVC.Studio.Manager
|
||||
// 빈 공간 클릭 시 선택 해제
|
||||
// Shift/Ctrl 키를 누르고 있지 않으면 선택 해제
|
||||
// 단, 기즈모 드래그 직후에는 선택 해제하지 않음
|
||||
// PropertyWindow는 유지 (clearPropertyWindow: false)
|
||||
if (!addToSelection)
|
||||
{
|
||||
var gizmoUndoBridge = GizmoUndoBridge.Instance;
|
||||
if (gizmoUndoBridge == null || !gizmoUndoBridge.IsDraggingOrJustEnded)
|
||||
{
|
||||
_selectionManager.DeselectAll();
|
||||
_selectionManager.DeselectAll(clearPropertyWindow: false);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -183,9 +183,10 @@ namespace UVC.Studio.Manager
|
||||
}
|
||||
|
||||
// 다중 선택이 아니면 기존 선택 해제
|
||||
// PropertyWindow는 Select 내에서 Open()을 호출하여 자동으로 갱신되므로 clearPropertyWindow: false
|
||||
if (!addToSelection)
|
||||
{
|
||||
DeselectAll(clearHierarchySelection);
|
||||
DeselectAll(clearHierarchySelection, clearPropertyWindow: false);
|
||||
}
|
||||
|
||||
// 이미 선택되어 있으면 무시
|
||||
@@ -229,7 +230,8 @@ namespace UVC.Studio.Manager
|
||||
/// 객체 선택을 해제합니다
|
||||
/// </summary>
|
||||
/// <param name="stageObject">선택 해제할 객체</param>
|
||||
public void Deselect(StageObjectManager.StageObject stageObject)
|
||||
/// <param name="clearPropertyWindow">PropertyWindow를 정리할지 여부 (기본값: true)</param>
|
||||
public void Deselect(StageObjectManager.StageObject stageObject, bool clearPropertyWindow = true)
|
||||
{
|
||||
if (stageObject == null)
|
||||
{
|
||||
@@ -250,12 +252,12 @@ namespace UVC.Studio.Manager
|
||||
// 미리보기 색상 원복 및 클리어
|
||||
ClearPreviewColor();
|
||||
|
||||
// PropertyWindow 항목 모두 제거
|
||||
if (_propertyWindow != null)
|
||||
// PropertyWindow 정리 (clearPropertyWindow가 true일 때만)
|
||||
if (clearPropertyWindow && _propertyWindow != null)
|
||||
{
|
||||
_propertyWindow.Clear();
|
||||
_currentDisplayedObject = null;
|
||||
}
|
||||
_currentDisplayedObject = null;
|
||||
_gizmoTargetObjects.Clear();
|
||||
}
|
||||
|
||||
@@ -281,12 +283,13 @@ namespace UVC.Studio.Manager
|
||||
/// 모든 선택을 해제합니다
|
||||
/// </summary>
|
||||
/// <param name="clearHierarchySelection">HierarchyWindow 선택도 해제할지 여부 (기본값: true)</param>
|
||||
public void DeselectAll(bool clearHierarchySelection = true)
|
||||
/// <param name="clearPropertyWindow">PropertyWindow를 정리할지 여부 (기본값: true)</param>
|
||||
public void DeselectAll(bool clearHierarchySelection = true, bool clearPropertyWindow = true)
|
||||
{
|
||||
var objectsToDeselect = new List<StageObjectManager.StageObject>(_selectedObjects);
|
||||
foreach (var obj in objectsToDeselect)
|
||||
{
|
||||
Deselect(obj);
|
||||
Deselect(obj, clearPropertyWindow);
|
||||
}
|
||||
//// HierarchyWindow(TreeList) 선택도 해제
|
||||
//// HierarchyWindow에서 선택 처리 중일 때는 TreeList가 자체적으로 선택을 관리하므로 생략
|
||||
|
||||
@@ -230,15 +230,56 @@ private static EntityTabData? CreateNetworkTab(StageObjectManager.StageObject st
|
||||
// Twin Agent 진행 상태 PropertyItem들 생성
|
||||
CreateTwinAgentProgressItems(properties, propertyDict, ref orderIndex, stageObject);
|
||||
|
||||
// Processor 생성 및 등록
|
||||
var processor = new TwinAgentAutoProcessor();
|
||||
processor.Initialize(stageObject, propertyDict);
|
||||
stageObject.RegisterProcessor(processor);
|
||||
// Processor 재사용 또는 생성 (Entity마다 독립적으로 유지)
|
||||
var processor = stageObject.GetProcessor<TwinAgentAutoProcessor>();
|
||||
if (processor == null)
|
||||
{
|
||||
// 새로 생성
|
||||
processor = new TwinAgentAutoProcessor();
|
||||
processor.Initialize(stageObject, propertyDict);
|
||||
stageObject.RegisterProcessor(processor);
|
||||
Debug.Log("[EntityPropertyAdapter] TwinAgentAutoProcessor 생성 및 등록");
|
||||
|
||||
// Auto 버튼 클릭 시 Processor 실행
|
||||
autoButton.ButtonText = "Run";
|
||||
}
|
||||
else
|
||||
{
|
||||
// 재사용 - 저장된 상태를 새 PropertyItem들에 복원
|
||||
Debug.Log($"[EntityPropertyAdapter] 기존 TwinAgentAutoProcessor 재사용 (IsRunning: {processor.IsRunning}, IsCompleted: {processor.IsCompleted})");
|
||||
|
||||
// UI 상태 복원 (실행 중이거나 완료된 경우)
|
||||
if (processor.IsRunning || processor.IsCompleted)
|
||||
{
|
||||
processor.RestoreUIState(propertyDict);
|
||||
|
||||
// 버튼 텍스트 설정
|
||||
autoButton.ButtonText = processor.IsRunning ? "Cancel" : "Run";
|
||||
}
|
||||
else
|
||||
{
|
||||
// 대기 중: PropertyItems만 업데이트
|
||||
processor.Initialize(stageObject, propertyDict);
|
||||
autoButton.ButtonText = "Run";
|
||||
}
|
||||
}
|
||||
|
||||
// Auto 버튼 클릭 시 Run/Cancel 토글
|
||||
autoButton.Clicked += async () =>
|
||||
{
|
||||
if (processor.IsRunning)
|
||||
{
|
||||
// Cancel 실행
|
||||
processor.Cancel();
|
||||
autoButton.ButtonText = "Run";
|
||||
Debug.Log("[EntityPropertyAdapter] 프로세스 취소");
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute 실행
|
||||
autoButton.ButtonText = "Cancel";
|
||||
await processor.Execute();
|
||||
autoButton.ButtonText = "Run";
|
||||
Debug.Log("[EntityPropertyAdapter] 프로세스 완료 또는 취소됨");
|
||||
};
|
||||
|
||||
// ========================================
|
||||
|
||||
@@ -404,10 +404,28 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
{
|
||||
public override PropertyType PropertyType => PropertyType.Button;
|
||||
|
||||
private string _buttonText;
|
||||
|
||||
/// <summary>
|
||||
/// 버튼에 표시될 텍스트입니다.
|
||||
/// </summary>
|
||||
public string ButtonText { get; set; }
|
||||
public string ButtonText
|
||||
{
|
||||
get => _buttonText;
|
||||
set
|
||||
{
|
||||
if (_buttonText != value)
|
||||
{
|
||||
_buttonText = value;
|
||||
ButtonTextChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 버튼 텍스트가 변경되었을 때 발생하는 이벤트입니다.
|
||||
/// </summary>
|
||||
public event Action<string> ButtonTextChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 버튼이 클릭되었을 때 발생하는 이벤트입니다.
|
||||
@@ -416,7 +434,7 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
|
||||
public ButtonProperty(string id, string name, string buttonText = "Execute") : base(id, name, null)
|
||||
{
|
||||
ButtonText = buttonText;
|
||||
_buttonText = buttonText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -48,6 +48,17 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
/// </summary>
|
||||
private string? _currentTabId = null;
|
||||
|
||||
/// <summary>
|
||||
/// 현재 표시 중인 Entity (같은 Entity 재선택 시 탭 유지용)
|
||||
/// </summary>
|
||||
private UVC.Entity.Entity? _currentEntity = null;
|
||||
|
||||
/// <summary>
|
||||
/// PropertyItem별 이벤트 핸들러 참조 (구독 해제용)
|
||||
/// </summary>
|
||||
private readonly Dictionary<string, (Action<bool> visibilityHandler, Action<object, object> valueHandler)> _eventHandlers
|
||||
= new Dictionary<string, (Action<bool>, Action<object, object>)>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Properties
|
||||
@@ -154,9 +165,14 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
/// 모든 아이템이 flat하게 표시됩니다.
|
||||
/// </summary>
|
||||
/// <param name="items">표시할 속성 항목들의 목록</param>
|
||||
/// <summary>
|
||||
/// [기존 방식] 그룹 없이 속성 목록을 로드합니다.
|
||||
/// 모든 아이템이 flat하게 표시됩니다.
|
||||
/// </summary>
|
||||
/// <param name="items">표시할 속성 항목들의 목록</param>
|
||||
public void LoadProperties(List<IPropertyItem> items)
|
||||
{
|
||||
Clear();
|
||||
ClearEntries(); // _currentEntity를 유지하면서 엔트리만 제거
|
||||
if (items != null)
|
||||
{
|
||||
foreach (var item in items)
|
||||
@@ -172,9 +188,13 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
/// [그룹 방식] 그룹화된 속성 목록을 로드합니다.
|
||||
/// </summary>
|
||||
/// <param name="groups">표시할 속성 그룹들의 목록</param>
|
||||
/// <summary>
|
||||
/// [그룹 방식] 그룹화된 속성 목록을 로드합니다.
|
||||
/// </summary>
|
||||
/// <param name="groups">표시할 속성 그룹들의 목록</param>
|
||||
public void LoadGroupedProperties(List<IPropertyGroup> groups)
|
||||
{
|
||||
Clear();
|
||||
ClearEntries(); // _currentEntity를 유지하면서 엔트리만 제거
|
||||
if (groups != null)
|
||||
{
|
||||
foreach (var group in groups)
|
||||
@@ -189,9 +209,13 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
/// [혼용 방식] 그룹과 개별 아이템을 함께 로드합니다.
|
||||
/// </summary>
|
||||
/// <param name="entries">표시할 엔트리들의 목록 (그룹 또는 아이템)</param>
|
||||
/// <summary>
|
||||
/// [혼용 방식] 그룹과 개별 아이템을 함께 로드합니다.
|
||||
/// </summary>
|
||||
/// <param name="entries">표시할 엔트리들의 목록 (그룹 또는 아이템)</param>
|
||||
public void LoadMixedProperties(List<IPropertyEntry> entries)
|
||||
{
|
||||
Clear();
|
||||
ClearEntries(); // _currentEntity를 유지하면서 엔트리만 제거
|
||||
if (entries != null)
|
||||
{
|
||||
foreach (var entry in entries)
|
||||
@@ -618,6 +642,7 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
/// <summary>
|
||||
/// 엔티티를 기반으로 PropertyWindow를 열고 탭을 구성합니다.
|
||||
/// EntityPropertyAdapter를 통해 엔티티의 탭 데이터를 가져옵니다.
|
||||
/// 같은 엔티티를 다시 열 때는 현재 선택된 탭을 유지합니다.
|
||||
/// </summary>
|
||||
/// <param name="entity">표시할 엔티티</param>
|
||||
public void Open(UVC.Entity.Entity entity)
|
||||
@@ -628,19 +653,44 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
return;
|
||||
}
|
||||
|
||||
// 기존 탭 클리어
|
||||
ClearTabs();
|
||||
// 같은 엔티티를 다시 열 때는 탭을 유지
|
||||
bool isSameEntity = _currentEntity != null && _currentEntity == entity;
|
||||
|
||||
if (isSameEntity)
|
||||
{
|
||||
Debug.Log($"[PropertyWindow] Same entity opened: {entity.Name} - 탭 유지");
|
||||
// Window만 표시
|
||||
Show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Adapter를 통해 Entity → 탭 데이터 변환
|
||||
// 다른 엔티티를 열 때는 이전 엔티티 정리
|
||||
var previousEntity = _currentEntity;
|
||||
|
||||
// 1. 먼저 Clear()를 호출하여 이전 PropertyItem들의 이벤트 구독 해제
|
||||
// Clear()는 _currentEntity를 null로 만들믰로 미리 저장해둔 previousEntity 사용
|
||||
Clear();
|
||||
|
||||
// 2. 이전 엔티티의 프로세서는 취소하지 않음 (백그라운드에서 계속 실행)
|
||||
// 다시 해당 엔티티를 선택하면 진행 상태가 복원됨
|
||||
if (previousEntity != null)
|
||||
{
|
||||
Debug.Log($"[PropertyWindow] 이전 엔티티 ({previousEntity.Name})의 프로세서는 백그라운드에서 계속 실행");
|
||||
}
|
||||
|
||||
// 3. 새 엔티티 설정
|
||||
_currentEntity = entity;
|
||||
|
||||
// 4. Adapter를 통해 Entity → 탭 데이터 변환
|
||||
var tabsData = EntityPropertyAdapter.GetTabsForEntity(entity);
|
||||
|
||||
// 탭 생성
|
||||
// 5. 탭 생성
|
||||
foreach (var tabData in tabsData)
|
||||
{
|
||||
AddTab(tabData.TabId, tabData.TabName, tabData.Properties, tabData.Order);
|
||||
}
|
||||
|
||||
// Window 표시
|
||||
// 6. Window 표시
|
||||
Show();
|
||||
|
||||
Debug.Log($"[PropertyWindow] Opened for entity: {entity.Name} (탭 개수: {Tabs.Count})");
|
||||
@@ -658,8 +708,26 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
/// <summary>
|
||||
/// 모든 엔트리를 제거합니다.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 모든 엔트리를 제거합니다 (_currentEntity는 유지).
|
||||
/// LoadProperties 등에서 사용되며, 엔티티 컨텍스트를 유지합니다.
|
||||
/// </summary>
|
||||
private void ClearEntries()
|
||||
{
|
||||
// 모든 PropertyItem의 이벤트 구독 명시적으로 해제
|
||||
foreach (var kvp in _itemIndex)
|
||||
{
|
||||
var item = kvp.Value;
|
||||
if (_eventHandlers.TryGetValue(item.Id, out var handlers))
|
||||
{
|
||||
item.IsVisibleChanged -= handlers.visibilityHandler;
|
||||
item.ValueChangedObject -= handlers.valueHandler;
|
||||
}
|
||||
}
|
||||
_eventHandlers.Clear();
|
||||
|
||||
foreach (var group in _groupIndex.Values)
|
||||
{
|
||||
group.Clear();
|
||||
@@ -667,6 +735,43 @@ namespace UVC.UI.Window.PropertyWindow
|
||||
_entries.Clear();
|
||||
_groupIndex.Clear();
|
||||
_itemIndex.Clear();
|
||||
|
||||
// _currentEntity는 유지 (엔티티 컨텍스트 보존)
|
||||
|
||||
EntriesCleared?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
// View 갱신하여 UI에서도 항목 제거
|
||||
Refresh();
|
||||
}
|
||||
public void Clear()
|
||||
{
|
||||
// 모든 PropertyItem의 이벤트 구독 명시적으로 해제
|
||||
foreach (var kvp in _itemIndex)
|
||||
{
|
||||
var item = kvp.Value;
|
||||
if (_eventHandlers.TryGetValue(item.Id, out var handlers))
|
||||
{
|
||||
item.IsVisibleChanged -= handlers.visibilityHandler;
|
||||
item.ValueChangedObject -= handlers.valueHandler;
|
||||
}
|
||||
}
|
||||
_eventHandlers.Clear();
|
||||
|
||||
foreach (var group in _groupIndex.Values)
|
||||
{
|
||||
group.Clear();
|
||||
}
|
||||
_entries.Clear();
|
||||
_groupIndex.Clear();
|
||||
_itemIndex.Clear();
|
||||
|
||||
// 탭도 함께 제거 (중복 탭 방지)
|
||||
_tabs.Clear();
|
||||
_currentTabId = null;
|
||||
|
||||
// 현재 표시 중인 엔티티 초기화 (윈도우 닫혀도 프로세스는 계속 실행)
|
||||
_currentEntity = null;
|
||||
|
||||
EntriesCleared?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
// View 갱신하여 UI에서도 항목 제거
|
||||
@@ -779,20 +884,25 @@ private void AddEntryInternal(IPropertyEntry entry)
|
||||
{
|
||||
_itemIndex[item.Id] = item;
|
||||
|
||||
// IsVisibleChanged 이벤트 등록 (재귀 방지)
|
||||
item.IsVisibleChanged += (visible) =>
|
||||
// 이벤트 핸들러 생성 및 저장 (구독 해제를 위해)
|
||||
Action<bool> visibilityHandler = (visible) =>
|
||||
{
|
||||
SetPropertyVisibility(item.Id, visible);
|
||||
};
|
||||
|
||||
// ValueChangedObject 이벤트 등록 (UI 갱신)
|
||||
item.ValueChangedObject += (oldValue, newValue) =>
|
||||
Action<object, object> valueHandler = (oldValue, newValue) =>
|
||||
{
|
||||
if (_view != null)
|
||||
{
|
||||
_view.UpdatePropertyValue(item.Id, newValue);
|
||||
}
|
||||
};
|
||||
|
||||
_eventHandlers[item.Id] = (visibilityHandler, valueHandler);
|
||||
|
||||
// 이벤트 구독
|
||||
item.IsVisibleChanged += visibilityHandler;
|
||||
item.ValueChangedObject += valueHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -802,14 +912,13 @@ private void AddEntryInternal(IPropertyEntry entry)
|
||||
{
|
||||
_itemIndex[item.Id] = item;
|
||||
|
||||
// IsVisibleChanged 이벤트 등록 (재귀 방지)
|
||||
item.IsVisibleChanged += (visible) =>
|
||||
// 이벤트 핸들러 생성 및 저장 (구독 해제를 위해)
|
||||
Action<bool> visibilityHandler = (visible) =>
|
||||
{
|
||||
SetPropertyVisibility(item.Id, visible);
|
||||
};
|
||||
|
||||
// ValueChangedObject 이벤트 등록 (UI 갱신)
|
||||
item.ValueChangedObject += (oldValue, newValue) =>
|
||||
Action<object, object> valueHandler = (oldValue, newValue) =>
|
||||
{
|
||||
if (_view != null)
|
||||
{
|
||||
@@ -817,6 +926,12 @@ private void AddEntryInternal(IPropertyEntry entry)
|
||||
}
|
||||
};
|
||||
|
||||
_eventHandlers[item.Id] = (visibilityHandler, valueHandler);
|
||||
|
||||
// 이벤트 구독
|
||||
item.IsVisibleChanged += visibilityHandler;
|
||||
item.ValueChangedObject += valueHandler;
|
||||
|
||||
if (item.GroupId == null)
|
||||
{
|
||||
_entries.Add(item);
|
||||
|
||||
@@ -86,7 +86,11 @@ namespace UVC.UI.Window.PropertyWindow.UI
|
||||
|
||||
// --- 이벤트 리스너 등록 ---
|
||||
_button.onClick.RemoveAllListeners();
|
||||
_button.onClick.AddListener(OnButtonClicked);
|
||||
|
||||
|
||||
// ButtonText 변경 이벤트 구독
|
||||
_propertyItem.ButtonTextChanged += OnButtonTextChanged;
|
||||
_button.onClick.AddListener(OnButtonClicked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +105,17 @@ namespace UVC.UI.Window.PropertyWindow.UI
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 버튼 텍스트가 변경되었을 때 호출됩니다.
|
||||
/// </summary>
|
||||
private void OnButtonTextChanged(string newText)
|
||||
{
|
||||
if (_buttonText != null)
|
||||
{
|
||||
_buttonText.text = newText;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UI의 읽기 전용 상태를 설정합니다.
|
||||
/// </summary>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -10951,14 +10951,6 @@ PrefabInstance:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 1843229927}
|
||||
m_Modifications:
|
||||
- target: {fileID: 384444075044174943, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_Size
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 384444075044174943, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_Value
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1053757332962301994, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_AnchorMax.x
|
||||
value: 0
|
||||
@@ -10967,42 +10959,22 @@ PrefabInstance:
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1053757332962301994, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1602519165350808158, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: PropertyWindow
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1602519165350808158, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_IsActive
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4618630843252738151, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4618630843252738151, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_AnchorMin.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4618630843252738151, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_AnchoredPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4618630843252738151, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7125265927081152491, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_SizeDelta.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7125265927081152491, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 7952136475300671546, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: _labelPropertyPrefab
|
||||
value:
|
||||
objectReference: {fileID: 2484066679782419758, guid: 93f804cf7d904534fb648912390f4b22, type: 3}
|
||||
- target: {fileID: 7952136475300671546, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: _buttonPropertyPrefab
|
||||
value:
|
||||
objectReference: {fileID: 7250795714712263932, guid: 44a8f48a35bd63d4f81a2448c6f70d96, type: 3}
|
||||
- target: {fileID: 8065352563668446013, guid: 4b98d7ee8b805ff42be384e91f3bf8a4, type: 3}
|
||||
propertyPath: m_Pivot.x
|
||||
value: 1
|
||||
|
||||
@@ -24,7 +24,7 @@ MonoBehaviour:
|
||||
m_missingGlyphCharacter: 0
|
||||
m_ClearDynamicDataOnBuild: 1
|
||||
m_warningsDisabled: 0
|
||||
m_defaultFontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
|
||||
m_defaultFontAsset: {fileID: 11400000, guid: 2ec62c2b5b163f64e92dc4988250c9c8, type: 2}
|
||||
m_defaultFontAssetPath: Fonts & Materials/
|
||||
m_defaultFontSize: 36
|
||||
m_defaultAutoSizeMinRatio: 0.5
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"com.coplaydev.unity-mcp": "https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#main",
|
||||
"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask",
|
||||
"com.unity.2d.sprite": "1.0.0",
|
||||
"com.unity.cloud.gltfast": "6.16.0",
|
||||
"com.unity.ide.rider": "3.0.38",
|
||||
"com.unity.ide.visualstudio": "2.0.26",
|
||||
"com.unity.inputsystem": "1.17.0",
|
||||
"com.unity.multiplayer.center": "1.0.1",
|
||||
"com.unity.nuget.newtonsoft-json": "3.2.2",
|
||||
"com.unity.render-pipelines.universal": "17.2.0",
|
||||
"com.unity.timeline": "1.8.9",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"com.coplaydev.unity-mcp": {
|
||||
"version": "https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#main",
|
||||
"depth": 0,
|
||||
"source": "git",
|
||||
"dependencies": {
|
||||
"com.unity.nuget.newtonsoft-json": "3.0.2"
|
||||
},
|
||||
"hash": "286d0c6df1b8987820e2bce7c9281957c6c9e35f"
|
||||
},
|
||||
"com.cysharp.unitask": {
|
||||
"version": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask",
|
||||
"depth": 0,
|
||||
@@ -78,19 +87,10 @@
|
||||
},
|
||||
"com.unity.ext.nunit": {
|
||||
"version": "2.0.5",
|
||||
"depth": 1,
|
||||
"depth": 2,
|
||||
"source": "builtin",
|
||||
"dependencies": {}
|
||||
},
|
||||
"com.unity.ide.rider": {
|
||||
"version": "3.0.38",
|
||||
"depth": 0,
|
||||
"source": "registry",
|
||||
"dependencies": {
|
||||
"com.unity.ext.nunit": "1.0.6"
|
||||
},
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.ide.visualstudio": {
|
||||
"version": "2.0.26",
|
||||
"depth": 0,
|
||||
@@ -116,14 +116,6 @@
|
||||
"dependencies": {},
|
||||
"url": "https://packages.unity.com"
|
||||
},
|
||||
"com.unity.multiplayer.center": {
|
||||
"version": "1.0.0",
|
||||
"depth": 0,
|
||||
"source": "builtin",
|
||||
"dependencies": {
|
||||
"com.unity.modules.uielements": "1.0.0"
|
||||
}
|
||||
},
|
||||
"com.unity.nuget.mono-cecil": {
|
||||
"version": "1.11.5",
|
||||
"depth": 2,
|
||||
|
||||
Reference in New Issue
Block a user