Bladeren bron

1.修改校准流程,infrared demo 国际化

slambb 11 maanden geleden
bovenliggende
commit
f65bfa2cd0

+ 99 - 29
Assets/BowArrow/InfraredCamera/InfraredDemo.cs

@@ -59,7 +59,7 @@ public class InfraredDemo : JCUnityLib.ViewBase
         }
         else {
             mBtnSee.interactable = false;
-            mBtnSee.transform.Find("Text").GetComponent<Text>().text = "等待初始化..";
+            mBtnSee.transform.Find("Text").GetComponent<Text>().text = TextAutoLanguage2.GetTextByKey("WaitingForInitialization"); // "等待初始化..";
         }
 
         //直接初始化一次
@@ -101,9 +101,19 @@ public class InfraredDemo : JCUnityLib.ViewBase
         {
             mBtnSee.gameObject.SetActive(value);
         }
-        mBtnSee.GetComponentInChildren<Text>().text = value ? "隐藏界面" : "调试红外";
+        updateBtnSee();
+        Action<Text> onApplyToNext = (t) => {
+            updateBtnSee();
+        };
+        mBtnSee.GetComponentInChildren<TextAutoLanguage2>().onApplyToNext += onApplyToNext;
         //if (value) InitInfraredCamera();
 
+        //刷新翻译的Dropdown
+        if (value) {
+            UpdateLanguage(); 
+            updateDropdownResolution2();
+        }
+
         if (!hasCalled && value)
         {
             hasCalled = true;
@@ -112,6 +122,10 @@ public class InfraredDemo : JCUnityLib.ViewBase
             Debug.Log("[InfraredDemo] SetVisiable Function!");
         }
     }
+    void updateBtnSee() {
+        mBtnSee.GetComponentInChildren<Text>().text = _visiable ? TextAutoLanguage2.GetTextByKey("HideInterface") : TextAutoLanguage2.GetTextByKey("DebugInfrared");//"隐藏界面" : "调试红外";
+    }
+    
 
     Text _spText;
     Vector2 _screenPoint;
@@ -164,7 +178,7 @@ public class InfraredDemo : JCUnityLib.ViewBase
     [SerializeField] Dropdown _dropdownResolution2;
 
     [SerializeField] Slider _sliderLineWidth;
-
+    [SerializeField] Slider _fanWidth;
     //红外线阈值
     [SerializeField] Slider _infraredFilter;
 
@@ -189,7 +203,7 @@ public class InfraredDemo : JCUnityLib.ViewBase
     public ParamFloatValue resoutionNew = new ParamFloatValue("ic_resoutionNew", 10);
     //摄像机分辨率 -只处理高低分辨率情况
     public ParamFloatValue resoution = new ParamFloatValue("ic_resoution", 0);
-    string[] resolutions = { "高分辨率", "低分辨率" };
+    //string[] resolutions = { "高分辨率", "低分辨率" };
 #endif
 
     //抖动过滤值 - 6.0
@@ -199,7 +213,9 @@ public class InfraredDemo : JCUnityLib.ViewBase
 
 
     //线段宽度阈值
-    public ParamFloatValue lineWidth = new ParamFloatValue("ic_lineWidth", 10.0f);
+    public ParamFloatValue lineWidth = new ParamFloatValue("ic_lineWidth", 4.0f);
+    //扇形宽度
+    public ParamFloatValue fanWidth = new ParamFloatValue("ic_fanWidth", 90.0f);
 
     public ParamFloatValue captureValue = new ParamFloatValue("ic_captureValue", 30.0f);
     public ParamFloatValue delayValue = new ParamFloatValue("ic_delayValue", 30.0f);
@@ -263,6 +279,21 @@ public class InfraredDemo : JCUnityLib.ViewBase
         if (currentCameraInfo != null) return;
         currentCameraInfo = cameraInfo;
 
+        string[] sliderNameArrayKey = new string[] {
+            "AutoExposureMode",          // "自动曝光模式"
+            "ExposureTimeAbsolute",      // "曝光时间(绝对)"
+            "Brightness",                // "亮度"
+            "Contrast",                  // "对比度"
+            "Hue",                       // "色调"
+            "Saturation",                // "饱和度"
+            "Sharpness",                 // "锐度"
+            "Gamma",                     // "伽玛"
+            "BacklightCompensation",     // "背光补偿"
+            "Gain"                       // "增益"
+        };
+
+
+
         for (int i = 0; i < sliderStrArray.Length; i++)
         {
             string typeStr = sliderStrArray[i];
@@ -280,7 +311,9 @@ public class InfraredDemo : JCUnityLib.ViewBase
                 toggleObject.name = typeStr;
 
                 Text labelObj = toggleObject.transform.Find("Label").GetComponent<Text>();
-                labelObj.text = sliderNameArray[i];
+                //labelObj.text = sliderNameArray[i];
+                labelObj.gameObject.AddComponent<TextAutoLanguage2>().SetTextKey(sliderNameArrayKey[i]);
+
                 Toggle toggle = toggleObject.GetComponent<Toggle>();
                 CTRLAEToggle = toggle;
 
@@ -320,7 +353,8 @@ public class InfraredDemo : JCUnityLib.ViewBase
 
                 Text textObj = sliderObject.transform.Find("text").GetComponent<Text>();
                 Text titleTextObj = sliderObject.transform.Find("title").GetComponent<Text>();
-                titleTextObj.text = sliderNameArray[i];//类型名字
+                //titleTextObj.text = sliderNameArray[i];//类型名字
+                titleTextObj.gameObject.AddComponent<TextAutoLanguage2>().SetTextKey(sliderNameArrayKey[i]);
                 if (slider != null)
                 {
 
@@ -467,6 +501,9 @@ public class InfraredDemo : JCUnityLib.ViewBase
     string[] sliderNameArrayPC = new string[]{
         "亮度",
         "对比度",};
+    string[] sliderNameArrayPCKey = new string[]{
+        "Brightness",
+        "Contrast",};
     string[] sliderStrArrayPC = new string[]{
         "PU_BRIGHTNESS",
         "PU_CONTRAST"};
@@ -485,7 +522,8 @@ public class InfraredDemo : JCUnityLib.ViewBase
             Slider slider = sliderObject.GetComponent<Slider>();
             Text textObj = sliderObject.transform.Find("text").GetComponent<Text>();
             Text titleTextObj = sliderObject.transform.Find("title").GetComponent<Text>();
-            titleTextObj.text = sliderNameArrayPC[i];//类型名字
+            //titleTextObj.text = TextAutoLanguage2.GetTextByKey(sliderNameArrayPCKey[i]);// sliderNameArrayPC[i];//类型名字
+            titleTextObj.gameObject.AddComponent<TextAutoLanguage2>().SetTextKey(sliderNameArrayPCKey[i]);
             if (slider != null)
             {
                 slider.minValue = -1;
@@ -600,7 +638,8 @@ public class InfraredDemo : JCUnityLib.ViewBase
                 Debug.Log("初始化摄像机!");
                 //可以操作按钮
                 mBtnSee.interactable = true;
-                mBtnSee.transform.Find("Text").GetComponent<Text>().text = "调试红外";
+                //mBtnSee.transform.Find("Text").GetComponent<Text>().text = "调试红外";
+                updateBtnSee();
                 //延迟重新设置一次分辨率
                 StartCoroutine(delayInitOhterInfo(camera));
 
@@ -622,6 +661,18 @@ public class InfraredDemo : JCUnityLib.ViewBase
             };
         }
     }
+
+    private void updateDropdownResolution2()
+    {
+        string[] resolutions = {
+            TextAutoLanguage2.GetTextByKey("HighResolution"),
+            TextAutoLanguage2.GetTextByKey("LowResolution")
+        };
+        // 清除默认选项
+        _dropdownResolution2.ClearOptions();
+        // 将分辨率字符串数组转换为 Dropdown 选项
+        _dropdownResolution2.AddOptions(new List<string>(resolutions));
+    }
     /// <summary>
     /// 初始化一些游戏配置
     /// </summary>
@@ -634,11 +685,9 @@ public class InfraredDemo : JCUnityLib.ViewBase
         initSlider(camera);
 
         camera.GetResolutionsStrs();
-        // 清除默认选项
-        _dropdownResolution2.ClearOptions();
-        // 将分辨率字符串数组转换为 Dropdown 选项
-        _dropdownResolution2.AddOptions(new List<string>(resolutions));
+
         // 默认设置
+        updateDropdownResolution2();
         int index = (int)resoution.Get();
         _dropdownResolution2.value = index;
         _dropdownResolution2.RefreshShownValue();
@@ -675,6 +724,9 @@ public class InfraredDemo : JCUnityLib.ViewBase
         SetLineWidth(lineWidth.Get());
         _sliderLineWidth.onValueChanged.AddListener(SetLineWidth);
 
+        SetFanWidth(fanWidth.Get());
+        _fanWidth.onValueChanged.AddListener(SetFanWidth);
+
         //检测红外亮度阈值
         SetInfraredFilterValue(infraredFileterValue.Get());
         _infraredFilter.onValueChanged.AddListener(SetInfraredFilterValue);
@@ -933,9 +985,12 @@ public class InfraredDemo : JCUnityLib.ViewBase
         //{
         //    options.Add($"Quad {i + 1}");
         //}
-        options.Add("自动识别");
-        options.Add("半自动识别");
-        options.Add("手动识别");
+        //options.Add("自动识别");
+        //options.Add("半自动识别");
+        //options.Add("手动识别");
+        options.Add(TextAutoLanguage2.GetTextByKey("AutoRecognition"));    // "自动识别"
+        options.Add(TextAutoLanguage2.GetTextByKey("SemiAutoRecognition")); // "半自动识别"
+        options.Add(TextAutoLanguage2.GetTextByKey("ManualRecognition"));   // "手动识别"
         dropdown.AddOptions(options);
 
         // 添加监听器来处理选择事件
@@ -1081,20 +1136,26 @@ public class InfraredDemo : JCUnityLib.ViewBase
     // 按钮用于导出所有纹理
     public Button exportAllButton;
     // 定义纹理名称
-    string[] textureNames = {
-            "A屏幕原图",
-            "B半自动识别线段",
-            "C黑白色差",
-            "D识别结果",
-            "E色差叠加识别结果",
-            "F半自动备选线段"
+    string[] textureNames;
+    /// <summary>
+    /// 更新一下菜单
+    /// </summary>
+    public void UpdateLanguage() {
+        string[] _textureNames = {
+            TextAutoLanguage2.GetTextByKey("ScreenAOriginal"), // "A屏幕原图"
+            TextAutoLanguage2.GetTextByKey("SemiAutoSegmentB"), // "B半自动识别线段"
+            TextAutoLanguage2.GetTextByKey("BlackWhiteContrastC"), // "C黑白色差"
+            TextAutoLanguage2.GetTextByKey("RecognitionResultD"), // "D识别结果"
+            TextAutoLanguage2.GetTextByKey("ColorContrastOverlayE"), // "E色差叠加识别结果"
+            TextAutoLanguage2.GetTextByKey("SemiAutoAlternativeF") // "F半自动备选线段"
         };
-    void initExport() {
-     
+        textureNames = _textureNames;
         // 设置下拉菜单的选项
         textureDropdown.ClearOptions();
         textureDropdown.AddOptions(new System.Collections.Generic.List<string>(textureNames));
-
+    }
+    void initExport() {
+        UpdateLanguage();
         // 添加导出选中纹理的按钮点击事件
         exportSelectedButton.onClick.AddListener(() => SaveTextureToLocal(textureDropdown.value));
 
@@ -1341,8 +1402,9 @@ public class InfraredDemo : JCUnityLib.ViewBase
         //选择下标+1
         int v = optionIndex + 1;
         duckHunterLevel.Set(v);
-        _sliderLineWidth.SetValueWithoutNotify(duckHunterLevel.Get());
-        _sliderLineWidth.transform.Find("Value").GetComponent<Text>().text = duckHunterLevel.Get().ToString("f1");
+        int defLevel = (int)duckHunterLevel.Get() - 1 < 0 ? 0 : (int)duckHunterLevel.Get() - 1;
+        _duckLevelDropdown.SetValueWithoutNotify(defLevel);
+        //_duckLevelDropdown.transform.Find("Value").GetComponent<Text>().text = defLevel+"";
     }
 
     void OnClick_Reset()
@@ -1352,7 +1414,8 @@ public class InfraredDemo : JCUnityLib.ViewBase
         //SetContrast(1);
 
         SetShakeFilterValue(6);
-        SetLineWidth(10);
+        SetLineWidth(4);
+        SetFanWidth(90);
         SetInfraredFilterValue(0.8f);
         SetCaptureValue(30.0f);
         SetDelayValue(30.0f);
@@ -1588,6 +1651,13 @@ public class InfraredDemo : JCUnityLib.ViewBase
         _sliderLineWidth.SetValueWithoutNotify(lineWidth.Get());
         _sliderLineWidth.transform.Find("Value").GetComponent<Text>().text = lineWidth.Get().ToString("f1");
     }
+    public void SetFanWidth(float v)
+    {
+        fanWidth.Set(v);
+        _fanWidth.SetValueWithoutNotify(fanWidth.Get());
+        _fanWidth.transform.Find("Value").GetComponent<Text>().text = fanWidth.Get().ToString("f1");
+    }
+    
 #endregion
 #region 亮度检测部分
     public void SetInfraredFilterValue(float v)

File diff suppressed because it is too large
+ 605 - 27
Assets/BowArrow/InfraredCamera/Resources/InfraredDemo.prefab


+ 2 - 2
Assets/BowArrow/Modules/InfraredGuider/InfraredLightGuider2.prefab

@@ -475,7 +475,7 @@ RectTransform:
   m_AnchorMin: {x: 0.5, y: 1}
   m_AnchorMax: {x: 0.5, y: 1}
   m_AnchoredPosition: {x: 716, y: -275}
-  m_SizeDelta: {x: 160, y: 50}
+  m_SizeDelta: {x: 400, y: 50}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!222 &5225210364050453330
 CanvasRenderer:
@@ -2119,7 +2119,7 @@ RectTransform:
   m_AnchorMin: {x: 0.5, y: 1}
   m_AnchorMax: {x: 0.5, y: 1}
   m_AnchoredPosition: {x: 734, y: -279}
-  m_SizeDelta: {x: 160, y: 50}
+  m_SizeDelta: {x: 400, y: 50}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!222 &5623726213436862701
 CanvasRenderer:

+ 336 - 12
Assets/BowArrow/Resources/Prefabs/Views/Home/DeviceViewInfrared.prefab

@@ -77,7 +77,7 @@ RectTransform:
   m_ConstrainProportionsScale: 0
   m_Children:
   - {fileID: 3319966071402702626}
-  - {fileID: 5368886303976252795}
+  - {fileID: 9195925919553701895}
   m_Father: {fileID: 2624584339530074265}
   m_RootOrder: 2
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@@ -520,6 +520,7 @@ MonoBehaviour:
   - {fileID: 21300000, guid: 4083f8e1ca929ce4bb6ec7d9c29c9365, type: 3}
   _TextAutoLanguage2: {fileID: 4288816417670544630}
   deviceIndex: 0
+  omitText: {fileID: 5895775015745707182}
 --- !u!1 &1049268609651015207
 GameObject:
   m_ObjectHideFlags: 0
@@ -1310,6 +1311,7 @@ MonoBehaviour:
   - {fileID: 21300000, guid: 4083f8e1ca929ce4bb6ec7d9c29c9365, type: 3}
   _TextAutoLanguage2: {fileID: 2040204180109477403}
   deviceIndex: 1
+  omitText: {fileID: 8172346654568656097}
 --- !u!1 &1805942828472048259
 GameObject:
   m_ObjectHideFlags: 0
@@ -2866,6 +2868,71 @@ MonoBehaviour:
   m_FillOrigin: 0
   m_UseSpriteMesh: 0
   m_PixelsPerUnitMultiplier: 1
+--- !u!1 &3663055746462982435
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 9195925919553701895}
+  - component: {fileID: 5424964691604017367}
+  m_Layer: 5
+  m_Name: statusParent
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &9195925919553701895
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3663055746462982435}
+  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: 5368886303976252795}
+  - {fileID: 6540119674589221142}
+  m_Father: {fileID: 8809921120636371870}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 1}
+  m_AnchorMax: {x: 0, y: 1}
+  m_AnchoredPosition: {x: 310, y: -131.5}
+  m_SizeDelta: {x: 600, y: 45}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &5424964691604017367
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 3663055746462982435}
+  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: 4
+  m_Spacing: 0
+  m_ChildForceExpandWidth: 0
+  m_ChildForceExpandHeight: 0
+  m_ChildControlWidth: 0
+  m_ChildControlHeight: 0
+  m_ChildScaleWidth: 0
+  m_ChildScaleHeight: 0
+  m_ReverseArrangement: 0
 --- !u!1 &3975078034313454886
 GameObject:
   m_ObjectHideFlags: 0
@@ -5419,7 +5486,7 @@ RectTransform:
   m_ConstrainProportionsScale: 0
   m_Children:
   - {fileID: 5756235976269569222}
-  - {fileID: 5224722728605276788}
+  - {fileID: 2942170420610414968}
   m_Father: {fileID: 8359389633136827950}
   m_RootOrder: 2
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@@ -5608,6 +5675,102 @@ MonoBehaviour:
   m_FillOrigin: 0
   m_UseSpriteMesh: 0
   m_PixelsPerUnitMultiplier: 1
+--- !u!1 &7830343383463296454
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 5016398519639811147}
+  - component: {fileID: 2108338989013650304}
+  - component: {fileID: 8172346654568656097}
+  - component: {fileID: 3584349997327841576}
+  m_Layer: 5
+  m_Name: omit
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &5016398519639811147
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 7830343383463296454}
+  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: 2942170420610414968}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 1}
+  m_AnchorMax: {x: 0, y: 1}
+  m_AnchoredPosition: {x: 500, y: -22.5}
+  m_SizeDelta: {x: 200, y: 45}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &2108338989013650304
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 7830343383463296454}
+  m_CullTransparentMesh: 1
+--- !u!114 &8172346654568656097
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 7830343383463296454}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, 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_FontData:
+    m_Font: {fileID: 12800000, guid: 6b6cc7ab59ef00947950b61fdca2d042, type: 3}
+    m_FontSize: 45
+    m_FontStyle: 1
+    m_BestFit: 0
+    m_MinSize: 1
+    m_MaxSize: 45
+    m_Alignment: 3
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 1
+    m_VerticalOverflow: 1
+    m_LineSpacing: 1
+  m_Text: ...
+--- !u!114 &3584349997327841576
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 7830343383463296454}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 0f4efe98aab6c6b41a7ee1f4c49df27b, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  textKey: Connect_BLE_Connect
+  layoutRebuildObject: {fileID: 0}
+  languageFontSizes: []
 --- !u!1 &7867030853648936596
 GameObject:
   m_ObjectHideFlags: 0
@@ -5892,13 +6055,13 @@ RectTransform:
   m_LocalScale: {x: 1, y: 1, z: 1}
   m_ConstrainProportionsScale: 0
   m_Children: []
-  m_Father: {fileID: 8809921120636371870}
-  m_RootOrder: 1
+  m_Father: {fileID: 9195925919553701895}
+  m_RootOrder: 0
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_AnchorMin: {x: 0, y: 1}
   m_AnchorMax: {x: 0, y: 1}
-  m_AnchoredPosition: {x: 310, y: -131.5}
-  m_SizeDelta: {x: 285, y: 45}
+  m_AnchoredPosition: {x: 200, y: -22.5}
+  m_SizeDelta: {x: 400, y: 45}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!222 &2148228175767830763
 CanvasRenderer:
@@ -5935,7 +6098,7 @@ MonoBehaviour:
     m_BestFit: 0
     m_MinSize: 1
     m_MaxSize: 50
-    m_Alignment: 4
+    m_Alignment: 5
     m_AlignByGeometry: 0
     m_RichText: 1
     m_HorizontalOverflow: 1
@@ -7361,13 +7524,13 @@ RectTransform:
   m_LocalScale: {x: 1, y: 1, z: 1}
   m_ConstrainProportionsScale: 0
   m_Children: []
-  m_Father: {fileID: 3115437585392817648}
-  m_RootOrder: 1
+  m_Father: {fileID: 2942170420610414968}
+  m_RootOrder: 0
   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
   m_AnchorMin: {x: 0, y: 1}
   m_AnchorMax: {x: 0, y: 1}
-  m_AnchoredPosition: {x: 310, y: -131.5}
-  m_SizeDelta: {x: 285, y: 45}
+  m_AnchoredPosition: {x: 200, y: -22.5}
+  m_SizeDelta: {x: 400, y: 45}
   m_Pivot: {x: 0.5, y: 0.5}
 --- !u!222 &49497840751108719
 CanvasRenderer:
@@ -7404,7 +7567,7 @@ MonoBehaviour:
     m_BestFit: 0
     m_MinSize: 1
     m_MaxSize: 45
-    m_Alignment: 4
+    m_Alignment: 5
     m_AlignByGeometry: 0
     m_RichText: 1
     m_HorizontalOverflow: 1
@@ -7801,6 +7964,167 @@ MonoBehaviour:
     m_VerticalOverflow: 1
     m_LineSpacing: 1
   m_Text: "\u672A\u8FDE\u63A5"
+--- !u!1 &9031970122640690138
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2942170420610414968}
+  - component: {fileID: 8667097138556066916}
+  m_Layer: 5
+  m_Name: statusParent
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &2942170420610414968
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 9031970122640690138}
+  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: 5224722728605276788}
+  - {fileID: 5016398519639811147}
+  m_Father: {fileID: 3115437585392817648}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 1}
+  m_AnchorMax: {x: 0, y: 1}
+  m_AnchoredPosition: {x: 310, y: -131.5}
+  m_SizeDelta: {x: 600, y: 45}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!114 &8667097138556066916
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 9031970122640690138}
+  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: 0
+  m_ChildForceExpandHeight: 0
+  m_ChildControlWidth: 0
+  m_ChildControlHeight: 0
+  m_ChildScaleWidth: 0
+  m_ChildScaleHeight: 0
+  m_ReverseArrangement: 0
+--- !u!1 &9143769868297749396
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 6540119674589221142}
+  - component: {fileID: 4561199668158207216}
+  - component: {fileID: 5895775015745707182}
+  - component: {fileID: 1955914322198322870}
+  m_Layer: 5
+  m_Name: omit
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &6540119674589221142
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 9143769868297749396}
+  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: 9195925919553701895}
+  m_RootOrder: 1
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 1}
+  m_AnchorMax: {x: 0, y: 1}
+  m_AnchoredPosition: {x: 500, y: -22.5}
+  m_SizeDelta: {x: 200, y: 45}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &4561199668158207216
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 9143769868297749396}
+  m_CullTransparentMesh: 1
+--- !u!114 &5895775015745707182
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 9143769868297749396}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, 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_FontData:
+    m_Font: {fileID: 12800000, guid: 6b6cc7ab59ef00947950b61fdca2d042, type: 3}
+    m_FontSize: 45
+    m_FontStyle: 1
+    m_BestFit: 0
+    m_MinSize: 1
+    m_MaxSize: 50
+    m_Alignment: 3
+    m_AlignByGeometry: 0
+    m_RichText: 1
+    m_HorizontalOverflow: 1
+    m_VerticalOverflow: 1
+    m_LineSpacing: 1
+  m_Text: ...
+--- !u!114 &1955914322198322870
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 9143769868297749396}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 0f4efe98aab6c6b41a7ee1f4c49df27b, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  textKey: Connect_BLE_Connect
+  layoutRebuildObject: {fileID: 0}
+  languageFontSizes: []
 --- !u!1 &9222168600980044169
 GameObject:
   m_ObjectHideFlags: 0

+ 52 - 1
Assets/BowArrow/Scripts/Components/TextAutoLanguage2/Resources/TextAutoLanguage2/cn.json

@@ -554,6 +554,7 @@
   "TitleTip1": "调整激光定位器的角度和位置,\n使整个电视屏幕完整地位于梯形框内",
   "TitleTipHasData": "如定位白框与电视屏幕匹配,可点击“确认”按键,跳过定位流程否则调整激光定位器的角度和位置,使整个电视屏幕完整地位于梯形框内,点击“自动”按键",
   "TitleTip2": "如自动识别不准确,可调整激光定位器或调整图像对比度,使屏幕\n边缘更清晰后,再次自动识别;\n如多次自动识别不成功,可点击手动功能,并用手指拖动定位区域\n四个角进行调整,点击确认进入下一步。",
+  "TitleTipManual": "用手动拖动白色线条框来标记出电视屏幕的显示区域",
   "Withdrawal": "撤销",
   "Automatic": "自动",
   "Manual": "手动",
@@ -578,6 +579,7 @@
   "TipAutoEnd": "① 如无法识别出屏幕,需屏蔽环境干扰光源后,点击“自动”按键重新识别\n② 如白框与电视屏幕匹配,点击“确认”按键,跳过定位流程 \n③ 如白框与电视屏幕不匹配,点击“环境测光”按键,继续定位流程",
   "TipLightCtrl": "操作设备对准电视,将光点位于梯形框中电视屏幕,红色十字会在光点上,并随光点移动;如没有,需要找出干扰光源关闭它、调整激光定位器位置或调小亮度和对比度",
 
+
   "ScreenPositioningSuccessful-title": "\u3000\u3000请用手指点击选择最合适的屏幕区域结果。如未发现明显差异,请任选其一。如识别到的屏幕区域不合适,请点击“返回”重新识别。",
   "FirstResult": "结果一",
   "SecondResult": "结果二",
@@ -632,6 +634,55 @@
   "BulletTip": "请更换弹夹!",
 
   //偏移量
-  "CalibrationOffset": "校准"
+  "CalibrationOffset": "校准",
+
+  /**
+  Infrared Demo 界面字段
+  **/
+  "ManualPositioning": "手动定位",
+  "AutomaticPositioning": "自动定位",
+  "QuasiCenterOffset": "准心偏移量",
+  "Export": "导出",
+  "ExportAll": "导出全部",
+  "AdjustUVCParameters": "调整UVC参数",
+  "CaptureValue": "Capture 值",
+  "DelayValue": "Delay 值",
+  "CameraResolution": "摄像机分辨率",
+  "LineSegmentWidth": "绘制线段宽度",
+  "FanOuterRadius": "扇形半径",
+  "JitterFilterValue": "抖动过滤值",
+  "BrightnessDetectionThreshold": "检测亮度的阈值",
+  "ResetParameters": "重置参数",
+  "ClearAllData": "清空所有数据",
+  "DuckHuntLevelSelection": "野鸭开始关卡选择",
+  "ZoomOut": "缩小",
+  "AutoCalibrationFixedResolution": "自动校准的固定分辨率",
+  "CurrentCameraRenderedResolution": "当前摄像机渲染的分辨率",
+  "ScreenAOriginal": "A屏幕原图",
+  "SemiAutoSegmentB": "B半自动识别线段",
+  "BlackWhiteContrastC": "C黑白色差",
+  "RecognitionResultD": "D识别结果",
+  "ColorContrastOverlayE": "E色差叠加识别结果",
+  "SemiAutoAlternativeF": "F半自动备选线段",
+  "AutoRecognition": "自动识别",
+  "SemiAutoRecognition": "半自动识别",
+  "ManualRecognition": "手动识别",
+  "HideInterface": "隐藏界面",
+  "DebugInfrared": "调试红外",
+  "Close": "关闭",
+  "WaitingForInitialization": "等待初始化..",
+  "CurrentRenderingWhite": "当前渲染(白)",
+  "AutomaticYellow": "自动(黄)",
+  "SemiAutomaticRed": "半自动(红)",
+  "ManualGreen": "手动(绿)",
+
+  "AutoExposureMode": "自动曝光模式",
+  "ExposureTimeAbsolute": "曝光时间(绝对)",
+  "Hue": "色调",
+  "Saturation": "饱和度",
+  "Sharpness": "锐度",
+  "Gamma": "伽玛",
+  "BacklightCompensation": "背光补偿",
+  "Gain": "增益"
 
 }

+ 52 - 1
Assets/BowArrow/Scripts/Components/TextAutoLanguage2/Resources/TextAutoLanguage2/en.json

@@ -604,6 +604,7 @@
   "TitleTipHasData": "If the white positioning frame matches the TV screen, you can click the 'Confirm' button to skip the positioning process; otherwise, adjust the angle and position of the laser locator so that the entire TV screen fits completely within the trapezoidal frame, then click the 'Auto' button.",
 
   "TitleTip2": "If the automatic recognition is not accurate, you can adjust the laser locator or adjust the \nimage contrast to make the screen edge clearer and then automatically recognize it again; \n If automatic recognition fails multiple times, click the manual function and drag the four \ncorners of the positioning area with your finger to adjust. Click OK to proceed to the next step. ",
+  "TitleTipManual": "Manually drag the white line frame to mark the display area of the TV screen.",
   "Withdrawal": "Revoke",
   "Automatic": "Automatic",
   "Manual": "Manual",
@@ -685,5 +686,55 @@
   **/
   "BulletTip": "Please replace the magazine!",
   //偏移量
-  "CalibrationOffset": "Calibration"
+  "CalibrationOffset": "Calibration",
+
+  /**
+  Infrared Demo 界面字段
+  **/
+  "ManualPositioning": "Manual Positioning",
+  "AutomaticPositioning": "Automatic Positioning",
+  "QuasiCenterOffset": "Quasi Center Offset",
+  "Export": "Export",
+  "ExportAll": "Export All",
+  "AdjustUVCParameters": "Adjust UVC Parameters",
+  "CaptureValue": "Capture Value",
+  "DelayValue": "Delay Value",
+  "CameraResolution": "Camera Resolution",
+  "LineSegmentWidth": "Line Segment Width",
+  "FanOuterRadius": "Fan Outer Radius",
+  "JitterFilterValue": "Jitter Filter Value",
+  "BrightnessDetectionThreshold": "Brightness Detection Threshold",
+  "ResetParameters": "Reset Parameters",
+  "ClearAllData": "Clear All Data",
+  "DuckHuntLevelSelection": "Duck Hunt Level Selection",
+  "ZoomOut": "Zoom Out",
+  "AutoCalibrationFixedResolution": "Auto Calibration Fixed Resolution",
+  "CurrentCameraRenderedResolution": "Current Camera Rendered Resolution",
+  "ScreenAOriginal": "Screen A Original",
+  "SemiAutoSegmentB": "Semi Auto Segment B",
+  "BlackWhiteContrastC": "Black White Contrast C",
+  "RecognitionResultD": "Recognition Result D",
+  "ColorContrastOverlayE": "Color Contrast Overlay E",
+  "SemiAutoAlternativeF": "Semi Auto Alternative F",
+  "AutoRecognition": "Auto Recognition",
+  "SemiAutoRecognition": "Semi Auto Recognition",
+  "ManualRecognition": "Manual Recognition",
+  "HideInterface": "Hide Interface",
+  "DebugInfrared": "Debug Infrared",
+  "Close": "Close",
+  "WaitingForInitialization": "Waiting For Initialization..",
+  "CurrentRenderingWhite": "Current Rendering (White)",
+  "AutomaticYellow": "Automatic (Yellow)",
+  "SemiAutomaticRed": "Semi Automatic (Red)",
+  "ManualGreen": "Manual (Green)",
+
+  "AutoExposureMode": "Auto Exposure Mode",
+  "ExposureTimeAbsolute": "Exposure Time (Absolute)",
+  "Hue": "Hue",
+  "Saturation": "Saturation",
+  "Sharpness": "Sharpness",
+  "Gamma": "Gamma",
+  "BacklightCompensation": "Backlight Compensation",
+  "Gain": "Gain"
+
 }

+ 47 - 0
Assets/BowArrow/Scripts/View/Home/DeviceView_ItemShow.cs

@@ -47,6 +47,13 @@ public class DeviceView_ItemShow : MonoBehaviour
     bool bShowInfo = false;
     // Start is called before the first frame update
     // bool bProcess = false;
+
+
+    [SerializeField] Text omitText;
+    private int dotCount = 0;
+    private float interval = 0.5f; // 标点更新间隔
+    private float timer = 0f;
+
     private void Awake()
     {
         AimHandler.ins.aimDeviceInfoChangeEvent += onShowDeviceInfo;
@@ -252,6 +259,26 @@ public class DeviceView_ItemShow : MonoBehaviour
         }
     }
 
+    void UpdateLoadingText()
+    {
+        timer += Time.deltaTime;
+
+        // 每隔 `interval` 秒更新一次标点符号
+        if (timer >= interval)
+        {
+            dotCount = (dotCount + 1) % 4; // 标点数量从 0 到 3 循环
+            omitText.text = new string('.', dotCount); // 添加相应数量的点
+            timer = 0f; // 重置计时器
+        }
+    }
+
+    // 停止加载效果
+    public void StopLoading()
+    {
+        dotCount = 0;
+        omitText.text = ""; // 停止时恢复为基础文本
+    }
+
     void RequestBatteryForBow()
     {
         try
@@ -337,6 +364,16 @@ public class DeviceView_ItemShow : MonoBehaviour
             string name = BluetoothStatus.GetStatusTextKey(BluetoothAim.ins.status);
             if (name != _TextAutoLanguage2.GetTextKey())
                 _TextAutoLanguage2.SetTextKey(name);
+
+            if (BluetoothAim.ins.status == BluetoothStatusEnum.Connecting)
+            {
+                omitText.gameObject.SetActive(true);
+                UpdateLoadingText();
+            }
+            else
+            {
+                StopLoading();
+            }
         }
         else if (bluetoothPlayer == BluetoothPlayer.SECONDE_PLAYER)
         {
@@ -346,6 +383,16 @@ public class DeviceView_ItemShow : MonoBehaviour
             if (name != _TextAutoLanguage2.GetTextKey())
                 _TextAutoLanguage2.SetTextKey(name);
 
+            if (smartBowHelper.GetBluetoothStatus() == SmartBowSDK.BluetoothStatusEnum.Connecting)
+            {
+                omitText.gameObject.SetActive(true);
+                UpdateLoadingText();
+            }
+            else
+            {
+                StopLoading();
+            }
+
         }
 
     }

File diff suppressed because it is too large
+ 726 - 65
Assets/SmartBow/Resources/SmartBow/Prefabs/Views/Home/InfraredScreenPositioningView.prefab


+ 119 - 4
Assets/SmartBow/Resources/SmartBow/Prefabs/ZIM/LineGenerator.cs

@@ -21,6 +21,14 @@ namespace ZIM
         [Tooltip("是否每次绘制两点之间的线段")]
         public bool DrawTwoPointsAtATime = false;
 
+        //控制扇形角绘制
+        [Header("扇形角绘制")]
+        [SerializeField] private bool bDrawFan = false;
+        [SerializeField] private Color fanColor = Color.white;
+        [SerializeField] private int fanSegments = 20; // 扇形的平滑度
+        [SerializeField] private float fanOuterRadius = 150f; // 扇形的半径
+        private float fanInnerRadius = 0f;
+
         [SerializeField]
         private Vector2[] _points;
         /// <summary>
@@ -88,6 +96,7 @@ namespace ZIM
                         DrawLine(vh, start, end, LineThickness);
                     }
                 }
+
             }
             else
             {
@@ -110,6 +119,8 @@ namespace ZIM
                     }
                 }
             }
+
+            if (bDrawFan) DrawFansAtCorners(vh);
         }
 
         private void DrawLine(VertexHelper vh, Vector2 start, Vector2 end, float thickness)
@@ -144,10 +155,114 @@ namespace ZIM
                 drawnLength += currentDashLength + gapLength;
             }
         }
-        //void Update()
-        //{
-        //    //SetVerticesDirty();
-        //}
+        /// <summary>
+        /// 1. 计算角度方向:
+        /// 使用 Vector2.Angle 可以得到两个向量之间的夹角大小,但它不能确定角度的方向。为此,我们需要使用 Mathf.Atan2 来计算相对坐标的角度。Atan2 可以返回一个在 -π 到 π 之间的角度值,并且考虑了顺时针和逆时针的方向。
+        /// 2. 从 X 轴正方向为 0 计算角度:
+        /// 将角度计算为相对于 x 轴正方向的角度,并根据 Atan2 结果进行调整。
+        /// </summary>
+        /// <param name="vh"></param>
+        private void DrawFansAtCorners(VertexHelper vh)
+        {
+            List<Vector2> _Points = new List<Vector2>(Points);
+            if (Loop)
+            {
+                _Points.Add(Points[0]);
+                _Points.Add(Points[1]);
+            }
+
+            float width = rectTransform.rect.width / 2;
+            float height = rectTransform.rect.height / 2;
+            float pivotX = rectTransform.pivot.x * rectTransform.rect.width - width;
+            float pivotY = rectTransform.pivot.y * rectTransform.rect.height - height;
+
+            //比如现在是6个点,实际从第二个点开始绘制
+            for (int i = 1; i < _Points.Count - 1; i++)
+            {
+                Vector2 pre = _Points[i - 1];
+                Vector2 start = _Points[i];
+                Vector2 end = _Points[i + 1];
+
+                Vector2 previousPos = new Vector2(pre.x * width - pivotX, pre.y * height - pivotY);
+                Vector2 currentPos = new Vector2(start.x * width - pivotX, start.y * height - pivotY);
+                Vector2 nextPos = new Vector2(end.x * width - pivotX, end.y * height - pivotY);
+
+  
+                // 计算当前点到前一点的方向
+                Vector2 prevDir = (currentPos - previousPos).normalized;
+                // 计算当前点到下一点的方向
+                Vector2 currentDir = (nextPos - currentPos).normalized;
+
+                // 使用 Atan2 计算方向相对于 x 轴的角度
+                float prevAngle = Mathf.Atan2(prevDir.y, prevDir.x) * Mathf.Rad2Deg; // 前一个方向相对于 x 轴的角度
+                float currentAngle = Mathf.Atan2(currentDir.y, currentDir.x) * Mathf.Rad2Deg; // 当前方向相对于 x 轴的角度
+
+                // 计算两个方向之间的角度差
+                float angleBetween = Vector2.Angle(prevDir, currentDir);
+
+                // 判断旋转方向
+                float cross = prevDir.x * currentDir.y - prevDir.y * currentDir.x;
+                if (cross < 0)
+                {
+                    // 逆时针旋转
+                    angleBetween = 360f - angleBetween;
+                }
+
+                // 内角的计算(补充180度)
+                float innerAngle = 180f - angleBetween;
+
+                // 计算开始角度,这里用的是 x 轴为起始点来计算
+                float startAngle = currentAngle;
+
+                //Debug.Log($"Index {i}: startAngle = {startAngle}, innerAngle = {innerAngle}");
+
+                // 根据当前角的位置调整内角和起始角
+                DrawFanAtCorner(vh, currentPos, startAngle, innerAngle, fanInnerRadius, fanOuterRadius, fanSegments, fanColor);
+
+            }
+        }
+        private void DrawFanAtCorner(VertexHelper vh, Vector2 center, float startAngle, float angleDegree, float innerRadius, float outerRadius, int segments, Color color)
+        {
+            UIVertex vert = UIVertex.simpleVert;
+            vert.color = color;
+
+            float angleRad = Mathf.Deg2Rad * angleDegree;        // 将绘制角度转换为弧度
+            float startAngleRad = Mathf.Deg2Rad * startAngle;    // 将起始角度转换为弧度
+            float angleStep = angleRad / segments;               // 每个扇形段的角度步长
+
+            int initialVertCount = vh.currentVertCount;          // 记录当前顶点数量
+
+            // 添加中心点顶点
+            vert.position = center;
+            vert.uv0 = new Vector2(0.5f, 0.5f);                  // 中心UV值
+            vh.AddVert(vert);
+
+            // 绘制外圈和内圈的顶点
+            for (int i = 0; i <= segments; i++)
+            {
+                float currentAngle = startAngleRad + i * angleStep;
+                float cosA = Mathf.Cos(currentAngle);
+                float sinA = Mathf.Sin(currentAngle);
+
+                // 外圈顶点
+                vert.position = center + new Vector2(cosA * outerRadius, sinA * outerRadius);
+                vert.uv0 = new Vector2(0.5f + cosA * 0.5f, 0.5f + sinA * 0.5f);
+                vh.AddVert(vert);
+
+                // 内圈顶点
+                vert.position = center + new Vector2(cosA * innerRadius, sinA * innerRadius);
+                vert.uv0 = new Vector2(0.5f + cosA * innerRadius / outerRadius * 0.5f, 0.5f + sinA * innerRadius / outerRadius * 0.5f);
+                vh.AddVert(vert);
+            }
+
+            // 创建三角形索引来绘制扇形
+            for (int i = 1; i <= segments; i++)
+            {
+                int baseIndex = initialVertCount + (i - 1) * 2;
+                vh.AddTriangle(initialVertCount, baseIndex + 1, baseIndex + 3);  // 中心点连接外圈
+                vh.AddTriangle(baseIndex + 1, baseIndex + 2, baseIndex + 3);    // 内圈连接外圈
+            }
+        }
 
     }
 }

+ 99 - 17
Assets/SmartBow/Scripts/Views/InfraredViewParts/InfraredScreenPositioningView.cs

@@ -18,6 +18,7 @@ public enum ScreenPositioningStep {
   Start,//开始界面
   AutoEnd,//自动定位结束后界面
   Marker,//进行标记界面
+  Manual,//手动界面
   LightCtrl,//灯光调整界面
   Successful,//结果选择界面
 }
@@ -108,6 +109,14 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
     [Header("AutoEnd Layout Group")]
     [SerializeField]
     GameObject LayoutAutoEnd;
+
+    [Header("LightCtrl Layout Group")]
+    [SerializeField]
+    GameObject LayoutLightCtrl;
+    [SerializeField] Slider sliderContrast;
+    //亮度
+    [SerializeField] Slider sliderBrightness;
+
     [Header("Marker Layout Group")]
     [SerializeField]
     GameObject LayoutMarker;
@@ -115,13 +124,17 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
     RectTransform crosshairSmall;
     [Tooltip("标记页面标题提示")]
     [SerializeField] TextAutoLanguage2 markerTextAutoLanguage2;
+    [SerializeField]
+    RectTransform markerPointsParent;
+    [SerializeField]
+    List<RectTransform> markerPosList;
+    [SerializeField]
+    Line markerPointsLine;
 
-    [Header("LightCtrl Layout Group")]
+    [Header("Manual Layout Group")]
     [SerializeField]
-    GameObject LayoutLightCtrl;
-    [SerializeField] Slider sliderContrast;
-    //亮度
-    [SerializeField] Slider sliderBrightness;
+    GameObject LayoutManual;
+
 
     [Header("Successful Layout Group")]
     [SerializeField]
@@ -143,7 +156,8 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
     RawImage CameraSecondImage; //第二个结果屏幕
     [SerializeField] LineGenerator FirstUILineGenerator;//第一个结果屏幕线条
     [SerializeField] LineGenerator SecondUILineGenerator;//第二个结果屏幕线条
-
+    bool bMarkerFinish = false;
+    ScreenPositioningStep perStepView = ScreenPositioningStep.None;//最后一次进入LayoutSuccessful的页面
 
     //标记当前页面情况
     ScreenPositioningStep curStepView = ScreenPositioningStep.Start;//设置一个开始页面 
@@ -261,7 +275,11 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
 
 
 
-            offset = line.MyThickness = infraredDemo.lineWidth.Get();
+            offset = line.MyThickness = markerPointsLine.MyThickness  = infraredDemo.lineWidth.Get();
+            //LineGenerator 比 line 宽少了大概2倍 
+            CurrentUILineGenerator.LineThickness = infraredDemo.lineWidth.Get() * 2;
+            //扇形宽
+            markerPointsLine.MyFanWidth = line.MyFanWidth = infraredDemo.fanWidth.Get();
 
 
             ZIM.Unity.QuadrilateralInCamera screen = ScreenLocate.Main.ScreenIdentification.Screen.QuadInCamera;
@@ -446,20 +464,33 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
                 pointsParent.gameObject.SetActive(false);
                 CurrentUILineGenerator.enabled = true;
                 break;
+            case ScreenPositioningStep.LightCtrl:
+                maskLine.SetDrawMask(false);
+                LayoutLightCtrl.SetActive(true);
+                CurrentUILineGenerator.enabled = true;
+                pointsParent.gameObject.SetActive(false);
+                //setPointsLocation(ScreenLocate.quadUnityVectorList, pointsParent.gameObject, true);
+                break;
             case ScreenPositioningStep.Marker:
+                perStepView = ScreenPositioningStep.Marker;
+                bMarkerFinish = false;
                 maskLine.SetDrawMask(true);
                 LayoutMarker.SetActive(true);
                 CurrentUILineGenerator.enabled = false;
                 pointsParent.gameObject.SetActive(false);
-                setPointsLocation(ScreenLocate.quadUnityVectorList, pointsParent.gameObject, true);
+                SyncQuadUnityVectorListToMarkerPointesPos();
+                //setPointsLocation(ScreenLocate.quadUnityVectorList, pointsParent.gameObject, true);
                 break;
-            case ScreenPositioningStep.LightCtrl:
-                maskLine.SetDrawMask(false);
-                LayoutLightCtrl.SetActive(true);
-                CurrentUILineGenerator.enabled = false;
-                pointsParent.gameObject.SetActive(true);
-                setPointsLocation(ScreenLocate.quadUnityVectorList, pointsParent.gameObject, true);
+            case ScreenPositioningStep.Manual:
+                perStepView = ScreenPositioningStep.Manual;
+                bMarkerFinish = false;
+                LayoutManual.SetActive(true);
+                bAuto = false;
+                doLocateAuto = false;
+                draggableParent.gameObject.SetActive(true);
+                pointsParent.gameObject.SetActive(false);
                 break;
+         
             case ScreenPositioningStep.Successful:
                 LayoutSuccessful.SetActive(true);
                 pointsParent.gameObject.SetActive(false);
@@ -472,6 +503,7 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
     {
         LayoutStart.SetActive(false);
         LayoutMarker.SetActive(false);
+        LayoutManual.SetActive(false);
         LayoutAutoEnd.SetActive(false);
         LayoutLightCtrl.SetActive(false);
         LayoutSuccessful.SetActive(false);
@@ -524,6 +556,17 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
     public void OnClick_EnterMarker() {
         SetScreenPositioningStepState(ScreenPositioningStep.Marker);
     }
+
+    /// <summary>
+    /// successful 返回页面时候,根据ScreenPositioningStep区分
+    /// </summary>
+    public void OnClick_BackByScreenPositioningStep()
+    {
+        if(perStepView == ScreenPositioningStep.Manual)
+            SetScreenPositioningStepState(ScreenPositioningStep.Manual);
+        else
+            SetScreenPositioningStepState(ScreenPositioningStep.Marker);
+    }
     /// <summary>
     /// 直接进入游戏流程
     /// </summary>
@@ -572,7 +615,13 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
 
      
     }
-
+    /// <summary>
+    /// 进入手动界面
+    /// </summary>
+    public void OnClick_EnterManual()
+    {
+        SetScreenPositioningStepState(ScreenPositioningStep.Manual);
+    }
     /// <summary>
     /// 切换成手动方式
     /// </summary>
@@ -596,13 +645,15 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
         Debug.Log("texSize:" + texSize + " = " + canvasRectTransform.rect);
         SyncQuadUnityVectorListToPos();
         SetRectanglePoints(linePosConversion(pos1.localPosition, pos2.localPosition, pos3.localPosition, pos4.localPosition));
+        SyncQuadUnityVectorListToMarkerPointesPos();
+
         if (curStepView == ScreenPositioningStep.Start || curStepView == ScreenPositioningStep.AutoEnd) {
             //如果是开始页面进行自动定位的
             if(curStepView != ScreenPositioningStep.AutoEnd) SetScreenPositioningStepState(ScreenPositioningStep.AutoEnd);
         }
-        else if (curStepView == ScreenPositioningStep.Marker) {
+        else if (curStepView == ScreenPositioningStep.Marker || curStepView == ScreenPositioningStep.Manual) {
             //显示最后结果
-            SetScreenPositioningStepState(ScreenPositioningStep.Successful);
+            if(bMarkerFinish) SetScreenPositioningStepState(ScreenPositioningStep.Successful);
         }
         //屏幕变化情况下。同步修改对应的line
         //设置两个线段
@@ -860,6 +911,7 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
         //再记录一次最后的点
         SetLinePos();
     }
+
     /// <summary>
     ///  处理新流程,先记录手动,然后到自动识别处理
     /// </summary>
@@ -903,6 +955,13 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
         //自动校准
         InfraredDemo.infraredCameraHelper.EnterScreenLocateManualAuto();
     }
+    /// <summary>
+    /// PointMarker 调用
+    /// </summary>
+    public void onFinishManualToAutomatic() {
+        bMarkerFinish = true;
+        onManualToAutomatic();
+    }
 
     #endregion
 
@@ -1509,4 +1568,27 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
     }
 
     #endregion
+
+
+
+
+    #region marker line 部分渲染
+    /// <summary>
+    /// maker 界面渲染
+    /// </summary>
+    void SyncQuadUnityVectorListToMarkerPointesPos()
+    {
+        Debug.Log("[ScreenLocate] SyncQuadUnityVectorListToMarkerPointesPos quadUnityVectorList:" + ScreenLocate.Main.PrintVector2List(ScreenLocate.quadUnityVectorList));
+        markerPosList[0].anchoredPosition = ScreenLocate.quadUnityVectorList[0].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
+        markerPosList[1].anchoredPosition = ScreenLocate.quadUnityVectorList[1].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
+        markerPosList[2].anchoredPosition = ScreenLocate.quadUnityVectorList[3].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
+        markerPosList[3].anchoredPosition = ScreenLocate.quadUnityVectorList[2].pixelToLocalPosition_AnchorCenter(Vector2.one, canvasRectTransform.rect);
+
+        SetMarkerRectanglePoints(linePosConversion(markerPosList[0].localPosition, markerPosList[1].localPosition, markerPosList[2].localPosition, markerPosList[3].localPosition));
+    }
+    void SetMarkerRectanglePoints(List<Vector2> screenPositions)
+    {
+        markerPointsLine.SetLine(screenPositions);
+    }
+    #endregion
 }

+ 252 - 5
Assets/SmartBow/Scripts/Views/InfraredViewParts/Line.cs

@@ -4,25 +4,63 @@ using UnityEngine.UI;
 
 namespace LineUI
 {
+    // 定义 ArrowInfo 类
+    public class ArrowInfo
+    {
+        public Vector2 Position { get; set; }
+        public Vector2 Direction { get; set; }
+
+        public ArrowInfo(Vector2 position, Vector2 direction)
+        {
+            Position = position;
+            Direction = direction;
+        }
+    }
+
     [RequireComponent(typeof(CanvasRenderer))]
     [RequireComponent(typeof(RectTransform))]
     public class Line : Graphic
     {
+        [Header("绘制线段")]
         [SerializeField] private bool loop = false;
         [SerializeField] private float thickness = 1f;
         [SerializeField] private int roundCount = 0;
-        [SerializeField] private Vector2 quadrilateralSize = new Vector2(100, 100);
-        [SerializeField] private Color quadColor = Color.red;
         [SerializeField] private List<Vector2> screenPositions = new List<Vector2>();
         //获取当前的points
         [HideInInspector]
         public List<Vector2> ScreenPositions => screenPositions;
 
-        [SerializeField] private Color maskColor = Color.red;
+        [Header("绘制内四边形")]
         //是否绘制内四边形
         [SerializeField] bool bDrawQuad = true;
+        [SerializeField] private Vector2 quadrilateralSize = new Vector2(100, 100);
+        [SerializeField] private Color quadColor = Color.red;
+
+        [Header("绘制外围蒙板")]
         //是否绘制外围蒙板
         [SerializeField] bool bDrawMask = false;
+        [SerializeField] private Color maskColor = Color.red;
+        //控制扇形角绘制
+        [Header("扇形角绘制")]
+        [SerializeField] private bool bDrawFan = false; 
+        [SerializeField] private Color fanColor = Color.white;
+        [SerializeField] private int  fanSegments = 20; // 扇形的平滑度
+        [SerializeField] private float fanOuterRadius = 150f; // 扇形的半径
+        private float fanInnerRadius = 0f;
+
+        [Tooltip("扇形指向箭头")]
+        [SerializeField] private bool bDrawArrow = false;
+        [SerializeField] private Color arrowColor = Color.white;
+        [SerializeField] float arrowLength = 50f;
+        [SerializeField] float arrowWidth = 50f; 
+        [SerializeField] float arrowHeadHeight = 30f;
+        [SerializeField] float arrowDis = 100f;
+
+        private List<ArrowInfo> arrowInfos = new List<ArrowInfo>();
+        //获取当前的points
+        [HideInInspector]
+        public List<ArrowInfo> ArrowInfos => arrowInfos;
+
         //[SerializeField] private Color quadTextColor = Color.black;
         //[SerializeField] private int quadFontSize = 14;
 
@@ -41,12 +79,23 @@ namespace LineUI
             get => thickness;
             set
             {
-                if (value >= 10)
+                if (value >= 1)
                 {
                     thickness = value;
                 }
             }
         }
+        public float MyFanWidth
+        {
+            get => fanOuterRadius;
+            set
+            {
+                if (value >= 1)
+                {
+                    fanOuterRadius = value;
+                }
+            }
+        }
 
         public void SetLine(List<Vector2> screenPositions)
         {
@@ -63,9 +112,17 @@ namespace LineUI
             bDrawMask = value;
             SetVerticesDirty();
         }
+
+        public void SetDrawFan(bool value)
+        {
+            bDrawFan = value;
+            SetVerticesDirty();
+        }
+
         protected override void OnPopulateMesh(VertexHelper vh)
         {
             vh.Clear();
+            arrowInfos.Clear();
             //quadsToDraw.Clear();
             //quadTextToDraw.Clear();
 
@@ -79,6 +136,8 @@ namespace LineUI
             if(bDrawQuad) SetQuadrilateralVertices(vh);
 
             if(bDrawMask) DrawMask(vh); // 绘制蒙版
+
+            if (bDrawFan) DrawFansAtCorners(vh); // 在转折角绘制扇形
         }
 
         private void SetLineVertices(VertexHelper vh)
@@ -261,11 +320,199 @@ namespace LineUI
             vert.position = corner4;
             vh.AddVert(vert);
 
-            Debug.Log("vh.currentVertCount:"+ vh.currentVertCount);
+            //Debug.Log("vh.currentVertCount:"+ vh.currentVertCount);
             int startIndex = vh.currentVertCount - 4;
             vh.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
             vh.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
         }
+        /// <summary>
+        /// 1. 计算角度方向:
+        /// 使用 Vector2.Angle 可以得到两个向量之间的夹角大小,但它不能确定角度的方向。为此,我们需要使用 Mathf.Atan2 来计算相对坐标的角度。Atan2 可以返回一个在 -π 到 π 之间的角度值,并且考虑了顺时针和逆时针的方向。
+        /// 2. 从 X 轴正方向为 0 计算角度:
+        /// 将角度计算为相对于 x 轴正方向的角度,并根据 Atan2 结果进行调整。
+        /// </summary>
+        /// <param name="vh"></param>
+        private void DrawFansAtCorners(VertexHelper vh)
+        {
+            List<Vector2> _screenPositions = new List<Vector2>(screenPositions);
+            if (loop)
+            {
+                _screenPositions.Add(screenPositions[0]);
+                _screenPositions.Add(screenPositions[1]);
+            }
+            //比如现在是6个点,实际从第二个点开始绘制
+            for (int i = 1; i < _screenPositions.Count - 1; i++)
+            {
+                Vector2 previousPos = _screenPositions[i - 1];
+                Vector2 currentPos = _screenPositions[i];
+                Vector2 nextPos = _screenPositions[i + 1];
+
+                // 计算当前点到前一点的方向
+                Vector2 prevDir = (currentPos - previousPos).normalized;
+                // 计算当前点到下一点的方向
+                Vector2 currentDir = (nextPos - currentPos).normalized;
+
+                // 使用 Atan2 计算方向相对于 x 轴的角度
+                float prevAngle = Mathf.Atan2(prevDir.y, prevDir.x) * Mathf.Rad2Deg; // 前一个方向相对于 x 轴的角度
+                float currentAngle = Mathf.Atan2(currentDir.y, currentDir.x) * Mathf.Rad2Deg; // 当前方向相对于 x 轴的角度
+
+                // 计算两个方向之间的角度差
+                float angleBetween = Vector2.Angle(prevDir, currentDir);
+
+                // 判断旋转方向
+                float cross = prevDir.x * currentDir.y - prevDir.y * currentDir.x;
+                if (cross < 0)
+                {
+                    // 逆时针旋转
+                    angleBetween = 360f - angleBetween;
+                }
+
+                // 内角的计算(补充180度)
+                float innerAngle = 180f - angleBetween;
+
+                // 计算开始角度,这里用的是 x 轴为起始点来计算
+                float startAngle = currentAngle;
+
+                //Debug.Log($"Index {i}: startAngle = {startAngle}, innerAngle = {innerAngle}");
+
+                // 根据当前角的位置调整内角和起始角
+                DrawFanAtCorner(vh, currentPos, startAngle, innerAngle, fanInnerRadius, fanOuterRadius, fanSegments, fanColor);
+
+
+                // 计算箭头的中心角度,确保角度在 0-360° 范围内
+                float centerAngle = (startAngle + innerAngle / 2) % 360f;
+                float radians = Mathf.Deg2Rad * centerAngle;
+
+                // 计算箭头位置:在扇形外半径的基础上延长一定距离(箭头偏移量)
+                float arrowOffset = fanOuterRadius + arrowDis;
+                Vector2 arrowPosition = currentPos + new Vector2(Mathf.Cos(radians), Mathf.Sin(radians)) * arrowOffset;
+
+                // 箭头方向
+                Vector2 arrowDirection = new Vector2(Mathf.Cos(radians), Mathf.Sin(radians)).normalized;
+
+                // 将箭头信息保存到列表中
+                arrowInfos.Add(new ArrowInfo(arrowPosition, arrowDirection));
+
+                // 在所有扇形处绘制箭头
+                // 在扇形中心绘制箭头
+                if (bDrawArrow)
+                {
+                    // 调试信息
+                    //Debug.Log($"Index {i}: arrowPosition = {arrowPosition}, startAngle = {startAngle}, centerAngle = {centerAngle}, direction = {arrowDirection}");
+                    // 绘制箭头
+                    DrawArrow(vh, arrowPosition, arrowDirection, arrowLength, arrowWidth, arrowHeadHeight);
+                }
+
+
+            }
+        } 
+        private void DrawFanAtCorner(VertexHelper vh, Vector2 center, float startAngle, float angleDegree, float innerRadius, float outerRadius, int segments ,Color color)
+        {
+            UIVertex vert = UIVertex.simpleVert;
+            vert.color = color;
+
+            float angleRad = Mathf.Deg2Rad * angleDegree;        // 将绘制角度转换为弧度
+            float startAngleRad = Mathf.Deg2Rad * startAngle;    // 将起始角度转换为弧度
+            float angleStep = angleRad / segments;               // 每个扇形段的角度步长
+
+            int initialVertCount = vh.currentVertCount;          // 记录当前顶点数量
+
+            // 添加中心点顶点
+            vert.position = center;
+            vert.uv0 = new Vector2(0.5f, 0.5f);                  // 中心UV值
+            vh.AddVert(vert);
+
+            // 绘制外圈和内圈的顶点
+            for (int i = 0; i <= segments; i++)
+            {
+                float currentAngle = startAngleRad + i * angleStep;
+                float cosA = Mathf.Cos(currentAngle);
+                float sinA = Mathf.Sin(currentAngle);
+
+                // 外圈顶点
+                vert.position = center + new Vector2(cosA * outerRadius, sinA * outerRadius);
+                vert.uv0 = new Vector2(0.5f + cosA * 0.5f, 0.5f + sinA * 0.5f);
+                vh.AddVert(vert);
+
+                // 内圈顶点
+                vert.position = center + new Vector2(cosA * innerRadius, sinA * innerRadius);
+                vert.uv0 = new Vector2(0.5f + cosA * innerRadius / outerRadius * 0.5f, 0.5f + sinA * innerRadius / outerRadius * 0.5f);
+                vh.AddVert(vert);
+            }
+
+            // 创建三角形索引来绘制扇形
+            for (int i = 1; i <= segments; i++)
+            {
+                int baseIndex = initialVertCount + (i - 1) * 2;
+                vh.AddTriangle(initialVertCount, baseIndex + 1, baseIndex + 3);  // 中心点连接外圈
+                vh.AddTriangle(baseIndex + 1, baseIndex + 2, baseIndex + 3);    // 内圈连接外圈
+            }
+        }
+
+        // 新增箭头绘制方法
+        private void DrawArrow(VertexHelper vh, Vector2 position, Vector2 direction, float arrowLength, float arrowWidth, float arrowHeadHeight)
+        {
+            // 标准化方向向量
+            direction.Normalize();
+
+            // 反向箭头的方向(箭头指向扇形方向)
+            Vector2 reversedDirection = -direction;
+
+            // 箭头尾部位置
+            Vector2 basePosition = position - reversedDirection * arrowLength;
+
+            // 计算垂直向量用于箭头宽度
+            Vector2 perpendicular = new Vector2(-reversedDirection.y, reversedDirection.x);
+
+            // 让箭头矩形部分的宽度比三角形的底边窄
+            float adjustedArrowWidth = arrowWidth * 0.6f;  // 调整宽度,使矩形比三角形窄
+
+            // 箭头矩形部分的四个顶点
+            Vector2 baseLeft = basePosition + perpendicular * (adjustedArrowWidth / 2);
+            Vector2 baseRight = basePosition - perpendicular * (adjustedArrowWidth / 2);
+            Vector2 headLeft = position + perpendicular * (adjustedArrowWidth / 2);
+            Vector2 headRight = position - perpendicular * (adjustedArrowWidth / 2);
+
+            Vector2 triangleHeadLeft = position + perpendicular * (arrowHeadHeight / 2);
+            Vector2 triangleHeadRight = position - perpendicular * (arrowHeadHeight / 2);
+
+            // 顶点颜色
+            UIVertex vert = UIVertex.simpleVert;
+            vert.color = arrowColor; 
+
+            // 先添加矩形部分的顶点
+            int rectStartIndex = vh.currentVertCount;
+            vert.position = baseLeft;
+            vh.AddVert(vert);
+            vert.position = baseRight;
+            vh.AddVert(vert);
+            vert.position = headLeft;
+            vh.AddVert(vert);
+            vert.position = headRight;
+            vh.AddVert(vert);
+
+            // 添加矩形部分的两条三角形索引
+            vh.AddTriangle(rectStartIndex, rectStartIndex + 1, rectStartIndex + 2);
+            vh.AddTriangle(rectStartIndex + 1, rectStartIndex + 3, rectStartIndex + 2);
+
+            // 然后添加三角形头部的顶点
+            Vector2 headPosition = position + reversedDirection * arrowHeadHeight;
+            int headStartIndex = vh.currentVertCount;
+
+            vert.position = triangleHeadLeft;
+            vh.AddVert(vert);
+            vert.position = triangleHeadRight;
+            vh.AddVert(vert);
+            vert.position = headPosition;  // 添加箭头尖端
+            vh.AddVert(vert);
+
+            // 添加三角形的索引
+            int triangleStartIndex = vh.currentVertCount - 3; // 三角形部分的开始索引
+            vh.AddTriangle(triangleStartIndex, triangleStartIndex + 1, triangleStartIndex + 2);  // 三角形索引
+        }
+
+
+
 
 
 

+ 7 - 5
Assets/SmartBow/Scripts/Views/InfraredViewParts/PointMarker.cs

@@ -205,10 +205,12 @@ public class PointMarker : MonoBehaviour
     }
 
     void UpdateLine() {
-        RectTransform rectTransform = markerParent as RectTransform;
-        Vector2 pivot = rectTransform.pivot; // 获取父物体的 pivot 值
-        Vector2 texSize = rectTransform.rect.size;
-        line.Points = InfraredDemo._ins.ConvertPointsToCoordinates(markedPoints.ToArray(), texSize, pivot);
+        if (line.gameObject.activeSelf) {
+            RectTransform rectTransform = markerParent as RectTransform;
+            Vector2 pivot = rectTransform.pivot; // 获取父物体的 pivot 值
+            Vector2 texSize = rectTransform.rect.size;
+            line.Points = InfraredDemo._ins.ConvertPointsToCoordinates(markedPoints.ToArray(), texSize, pivot);
+        }
     }
 
     void UpdateInstruction()
@@ -245,7 +247,7 @@ public class PointMarker : MonoBehaviour
             int index = i;
             infraredScreenPositioningView.onManualNewPos(3 - index, markerObjects[index].transform.localPosition);
         }
-        infraredScreenPositioningView.onManualToAutomatic();
+        infraredScreenPositioningView.onFinishManualToAutomatic();
 
         ////清空数据
         //currentPointIndex = 0;

Some files were not shown because too many files changed in this diff