void Init(GameObject target) { TargetObject = target; TargetTrans = target.transform; var pos = TargetTrans.position; TargetObjOldPosX = pos.x; TargetObjOldPosY = pos.y; var scale = TargetTrans.localScale; TargetObjOldScaleX = scale.x; TargetObjOldScaleY = scale.y; Bounds = UGUIMath.CalculateAbsoluteBounds(TargetTrans.GetComponent <RectTransform>()); }
/// <summary> /// Determine the distance from the mouse position to the screen space rectangle specified by the 4 points. /// </summary> static public float DistanceToRectangle(Vector2[] screenPoints, Vector2 mousePos) { bool oddNodes = false; int j = 4; for (int i = 0; i < 5; i++) { Vector3 v0 = screenPoints[UGUIMath.RepeatIndex(i, 4)]; Vector3 v1 = screenPoints[UGUIMath.RepeatIndex(j, 4)]; if ((v0.y > mousePos.y) != (v1.y > mousePos.y)) { if (mousePos.x < (v1.x - v0.x) * (mousePos.y - v0.y) / (v1.y - v0.y) + v0.x) { oddNodes = !oddNodes; } } j = i; } if (!oddNodes) { float dist, closestDist = -1f; for (int i = 0; i < 4; i++) { Vector3 v0 = screenPoints[i]; Vector3 v1 = screenPoints[UGUIMath.RepeatIndex(i + 1, 4)]; dist = DistancePointToLineSegment(mousePos, v0, v1); if (dist < closestDist || closestDist < 0f) { closestDist = dist; } } return(closestDist); } else { return(0f); } }
/// <summary> /// Target的位置发生变化时,更新引导的箭头 /// </summary> private void CheckTargetObjPosChange() { var new_pos = TargetTrans.position; var new_scale = TargetTrans.localScale; if (Mathf.Abs(new_pos.x - TargetObjOldPosX) < MIN_DIFF && Mathf.Abs(new_pos.y - TargetObjOldPosY) <= MIN_DIFF && Mathf.Abs(new_scale.x - TargetObjOldScaleX) < MIN_DIFF && Mathf.Abs(new_scale.y - TargetObjOldScaleY) <= MIN_DIFF) { return; } Bounds = UGUIMath.CalculateAbsoluteBounds(TargetTrans.GetComponent <RectTransform>()); TargetObjOldPosX = new_pos.x; TargetObjOldPosY = new_pos.y; TargetObjOldScaleX = new_scale.x; TargetObjOldScaleY = new_scale.y; if (CopyObj != null) { // 可能traget_trans的父亲节点有缩放 var rect_corner = new Vector3[4]; CopyTrans.GetComponent <RectTransform>().GetWorldCorners(rect_corner); float copy_rect_size_x = rect_corner[2].x - rect_corner[0].x; TargetTrans.GetComponent <RectTransform>().GetWorldCorners(rect_corner); float target_size_x = rect_corner[2].x - rect_corner[0].x; float scale = 1; if (copy_rect_size_x != 0) { scale = target_size_x / copy_rect_size_x; } Vector3 ori_scale = CopyTrans.localScale; CopyTrans.localScale = new Vector3(ori_scale.x * scale, ori_scale.y * scale, ori_scale.z * scale); } Wnd.ResetArrowTips(); }
/// <summary> /// 拷贝指引的目标控件 /// </summary> public void CopyTargetObj() { if (TargetObject == null) { return; } CopyObj = UnityEngine.GameObject.Instantiate(TargetObject) as GameObject; var toggle = CopyObj.GetComponent <Toggle>(); if (toggle != null) { toggle.group = null; } CopyTrans = CopyObj.transform; // 需要特殊处理的MonoBehaviour var spec_list = SGameEngine.Pool <MonoBehaviour> .List.New(); // 把非UI控件的MonoBehaviour销毁掉 var remove_list = SGameEngine.Pool <MonoBehaviour> .List.New(); var db_guide_copy_behavior = DBManager.Instance.GetDB <DBGuideCopyBehavior>(); foreach (var com in CopyObj.GetComponentsInChildren <MonoBehaviour>(true)) { // 处理特殊的组件 TargetModelInfo target_model_info = com as TargetModelInfo; if (target_model_info != null) { spec_list.Add(target_model_info); continue; } // 因为UIItemNewSlot采用了延迟加载图标,直接拷贝会图标丢失,需要把UIItemNewSlot也拷贝进来并进行加载工作 UIItemNewSlot slot = com as UIItemNewSlot; if (slot != null) { UIItemNewSlot source_slot = TargetObject.GetComponentInChildren <UIItemNewSlot>(); if (source_slot != null) { slot.ItemInfo = source_slot.ItemInfo; slot.SetUI(); if (slot.ItemInfo != null && GoodsHelper.GetGoodsType(slot.ItemInfo.type_idx) == GameConst.GIVE_TYPE_SOUL) { slot.CanShowCircleBkg = true; slot.SetColor(false); slot.SetBgImageVisiable(false); slot.SetEffectRootVisiable(false); } } continue; } // ui控件的基类 if (com == null || com is ICanvasElement || com is Selectable) { continue; } // 其他需要添加的组件 string class_name = com.GetType().Name; if (db_guide_copy_behavior.ContainType(class_name)) { continue; } //有Alpha渐变时直接设为不透明 TweenAlpha tween = com as TweenAlpha; if (tween != null) { tween.value = 1; } // 剩余的组件添加到remove_list remove_list.Add(com); } for (int i = remove_list.Count - 1; i >= 0; i--) { //包含序列帧特效的GameObject直接删掉,因为有特效重叠不同步的问题,物品除外 if (remove_list[i] is UGUIFrameAnimation) { if (remove_list[i].transform.parent != null && remove_list[i].transform.parent.parent != null) { if (remove_list[i].transform.parent.parent.GetComponent <UIItemNewSlot>() == null) { UnityEngine.Object.DestroyImmediate(remove_list[i].gameObject); } } } else { UnityEngine.Object.DestroyImmediate(remove_list[i]); } } SGameEngine.Pool <MonoBehaviour> .List.Free(remove_list); var canvas = CopyObj.GetComponent <Canvas>(); if (canvas != null) { UnityEngine.Object.DestroyImmediate(canvas); } CopyObj.SetActive(false); CopyTrans.SetParent(Wnd.TargetTmpRoot); var local_pos = CopyTrans.localPosition; local_pos.z = 0f; CopyTrans.localPosition = local_pos; RectTransform copy_trans = CopyTrans.GetComponent <RectTransform>(); RectTransform traget_trans = TargetObject.GetComponent <RectTransform>(); UGUIMath.SetWidgetSize(copy_trans, traget_trans); CopyObj.SetActive(true); // 可能traget_trans的父亲节点有缩放 var rect_corner = new Vector3[4]; copy_trans.GetWorldCorners(rect_corner); float copy_rect_size_x = rect_corner[2].x - rect_corner[0].x; traget_trans.GetWorldCorners(rect_corner); float target_size_x = rect_corner[2].x - rect_corner[0].x; float scale = 1; if (copy_rect_size_x != 0) { scale = target_size_x / copy_rect_size_x; } Vector3 ori_scale = CopyTrans.localScale; CopyTrans.localScale = new Vector3(ori_scale.x * scale, ori_scale.y * scale, ori_scale.z * scale); for (int i = spec_list.Count - 1; i >= 0; i--) { var com = spec_list[i]; //StartLoadModel 函数中播放模型动作在object隐藏时会不生效,需延后调用 TargetModelInfo target_model_info = com as TargetModelInfo; if (target_model_info != null) { target_model_info.StartLoadModel(); } } SGameEngine.Pool <MonoBehaviour> .List.Free(spec_list); }
private void CheckTargetObjVisibility() { var visible = true; if (TargetCanbeHit) { var current_camera = UIMainCtrl.MainCam; if (current_camera == null) { visible = false; } var screen_pos = current_camera.WorldToScreenPoint(Bounds.center); if (pointerData == null) { pointerData = new PointerEventData(EventSystem.current); } var hit_obj = UGUIMath.GetRaycastObj(screen_pos, pointerData); if (hit_obj == Wnd.EventMask) { visible = false; } else if (hit_obj == null) { visible = false; } else { if (CopyObj != null) { if (!UGUIMath.ContainWidget(CopyObj, hit_obj)) { visible = false; } } else if (TargetObject != null) { if (!UGUIMath.ContainWidget(TargetObject, hit_obj)) { visible = false; } } } } else { visible = TargetObject.activeInHierarchy; } if (!visible)// 因为UGUI的Layout有可能并不是在当前帧完成排版,因此对于强制指引,不可见时需要等待一会儿再重置 { if (m_StartInvisible == false) { m_InvisibleTime = Time.time; m_StartInvisible = true; } if (CopyObj == null || Time.time - m_InvisibleTime > m_CloseDelayTime) { Wnd.ResetGuideStep(); Wnd.Close(); } } }
public void ResetArrowTips() { if (m_GuideStep == null) { return; } ShowSkipButton(m_GuideStep.IsCanSkip); if (m_GuideStep.DisplayType == Guide.EDisplayType.Arrow || m_GuideStep.DisplayType == Guide.EDisplayType.Model)// 箭头引导类型/模型引导类型 { if (m_GuideArrow == null) { GameDebug.LogError("UIGuideWindow:ResetArrowTips m_GuideArrow is null"); return; } if (m_GuideObject != null) { // 计算目标物体的Bounds var guide_gameobject = m_GuideObject as GuideGameObject; m_GuideObject.Bounds = UGUIMath.CalculateAbsoluteBounds(guide_gameobject.TargetObject.GetComponent <RectTransform>()); var bounds = m_GuideObject.Bounds; // 设置debug min max点的位置 m_RectMin.SetActive(true); m_RectMax.SetActive(true); m_RectMin.transform.position = bounds.min; Vector3 local_pos = m_RectMin.transform.localPosition; m_RectMin.transform.localPosition = new Vector3(local_pos.x, local_pos.y, 0); m_RectMax.transform.position = bounds.max; local_pos = m_RectMax.transform.localPosition; m_RectMax.transform.localPosition = new Vector3(local_pos.x, local_pos.y, 0); // 显示箭头 m_GuideArrow.SetActive(true); m_GuideArrow.transform.localRotation = Quaternion.identity; // 获取箭头在世界坐标下的Bounds if (m_ArrowWorldWidth < 0) { Bounds arrow_bound = UGUIMath.CalculateAbsoluteBounds(m_GuideArrow.GetComponent <RectTransform>()); m_ArrowWorldWidth = arrow_bound.size.x; m_ArrowWorldHeight = arrow_bound.size.y; } float neighbour_width = 0; float neighbour_height = 0; float model_x_offset = m_GuideStep.Offset_X; // 模型预览组件在x方向的偏移 // 引导箭头的控件 if (m_GuideStep.DisplayType == Guide.EDisplayType.Arrow) { m_GuideDesc.gameObject.SetActive(true); m_GuideDescObject.gameObject.SetActive(true); // 设置引导文本的显示 m_GuideDesc.text = m_GuideStep.IconDesc; neighbour_width = m_GuideDesc.rectTransform.sizeDelta.x; neighbour_height = m_GuideDesc.preferredHeight; } else// 引导模型的控件 { m_PreviewCamera.SetActive(true); m_GuideModel.gameObject.SetActive(true); m_GuideModelDesc.text = m_GuideStep.IconDesc; neighbour_width = m_GuideModel.rectTransform.sizeDelta.x; neighbour_height = m_GuideModel.rectTransform.sizeDelta.y; } Vector3 center_local_pos = (m_RectMaxTrans.localPosition + m_RectMinTrans.localPosition) * 0.5f; Vector3 neighbour_pos = Vector3.zero; Vector3 arrow_rot = Vector3.zero; switch (m_GuideStep.IconDir) { case Guide.EGuideIconDir.Bottom: { m_GuideArrow.transform.position = new Vector3(bounds.min.x + bounds.size.x * 0.5f, bounds.max.y + m_ArrowWorldWidth * 0.5f, bounds.center.z); neighbour_pos = m_GuideArrow.transform.TransformPoint(0, ImageWidth(m_GuideArrow) * 0.5f + neighbour_height, 0f); model_x_offset += m_GuideModel.rectTransform.sizeDelta.x * 0.5f; if (center_local_pos.x > 0) // 如果指引中心点在右边,则模型显示在左边 { model_x_offset = -model_x_offset; } arrow_rot = new Vector3(0f, 0f, 90f); break; } case Guide.EGuideIconDir.Top: { m_GuideArrow.transform.position = new Vector3(bounds.min.x + bounds.size.x * 0.5f, bounds.min.y - m_ArrowWorldWidth * 0.5f, bounds.center.z); neighbour_pos = m_GuideArrow.transform.TransformPoint(0, -ImageWidth(m_GuideArrow) * 0.5f - neighbour_height, 0f); model_x_offset += m_GuideModel.rectTransform.sizeDelta.x * 0.5f; if (center_local_pos.x > 0) // 如果指引中心点在右边,则模型显示在左边 { model_x_offset = -model_x_offset; } arrow_rot = new Vector3(0f, 0f, -90f); break; } case Guide.EGuideIconDir.Left: { m_GuideArrow.transform.position = new Vector3(bounds.max.x + m_ArrowWorldWidth * 0.5f, bounds.min.y + bounds.size.y * 0.5f, bounds.center.z); neighbour_pos = m_GuideArrow.transform.TransformPoint(ImageWidth(m_GuideArrow) * 0.5f + neighbour_width * 0.5f, 0f, 0f); arrow_rot = Vector3.zero; break; } case Guide.EGuideIconDir.Right: { m_GuideArrow.transform.position = new Vector3(bounds.min.x - m_ArrowWorldWidth * 0.5f, bounds.min.y + bounds.size.y * 0.5f, bounds.center.z); neighbour_pos = m_GuideArrow.transform.TransformPoint(-ImageWidth(m_GuideArrow) * 0.5f - neighbour_width * 0.5f, 0f, 0f); arrow_rot = new Vector3(0f, 0f, 180f); break; } } if (m_GuideStep.DisplayType == Guide.EDisplayType.Arrow) { m_GuideDesc.transform.position = neighbour_pos; local_pos = m_GuideDesc.transform.localPosition; m_GuideDesc.transform.localPosition = new Vector3(local_pos.x, local_pos.y, 0); } else { m_GuideModel.transform.position = neighbour_pos; local_pos = m_GuideModel.transform.localPosition; m_GuideModel.transform.localPosition = new Vector3(local_pos.x + model_x_offset, m_GuideModel.rectTransform.sizeDelta.y * 0.5f, 0); } m_GuideArrow.transform.Rotate(arrow_rot, Space.Self); local_pos = m_GuideArrow.transform.localPosition; m_GuideArrow.transform.localPosition = new Vector3(local_pos.x, local_pos.y, 0f); } } else if (m_GuideStep.DisplayType == Guide.EDisplayType.Picture) { m_GuidePicture.SetActive(true); // 暂时屏蔽,引导图片改成RawImage了 //m_GuidePicture.GetComponent<Image>().sprite = LoadSprite(m_GuideStep.PicName); } else if (m_GuideStep.DisplayType == Guide.EDisplayType.Text)// 居中显示模型和文本 { m_PreviewCamera.SetActive(true); m_GuideModelDesc.text = m_GuideStep.IconDesc; m_GuideModel.transform.localPosition = new Vector3(m_GuideStep.Offset_X, m_GuideModel.rectTransform.sizeDelta.y * 0.5f, 0); m_GuideModel.gameObject.SetActive(true); } else if (m_GuideStep.DisplayType == Guide.EDisplayType.Region)// 高亮一块区域并居中显示模型和文本 { // 显示模型 m_PreviewCamera.SetActive(true); m_GuideModelDesc.text = m_GuideStep.IconDesc; m_GuideModel.transform.localPosition = new Vector3(m_GuideStep.Offset_X, m_GuideModel.rectTransform.sizeDelta.y * 0.5f, 0); m_GuideModel.gameObject.SetActive(true); if (m_GuideObject != null) { // 计算目标物体的Bounds var guide_gameobject = m_GuideObject as GuideGameObject; m_GuideObject.Bounds = UGUIMath.CalculateAbsoluteBounds(guide_gameobject.TargetObject.GetComponent <RectTransform>()); // 显示高亮区域 mHollowRegion.SetActive(true); var bounds = m_GuideObject.Bounds; // 设置 min max点的位置 mHollowRectMin.position = bounds.min; Vector3 local_pos = mHollowRectMin.localPosition; mHollowRectMin.localPosition = new Vector3(local_pos.x, local_pos.y, 0); mHollowRectMax.position = bounds.max; local_pos = mHollowRectMax.localPosition; mHollowRectMax.localPosition = new Vector3(local_pos.x, local_pos.y, 0); } } }