|
@@ -15,11 +15,30 @@ namespace GFGGame
|
|
|
private GameObject _sceneObject;
|
|
|
private DressUpObjDataCache equipDataCache;
|
|
|
|
|
|
+ private const string MOVE = "MOVE";
|
|
|
+ private const string SCALE = "SCALE";
|
|
|
+ private const string ROTATION = "ROTATION";
|
|
|
+ private const int MaxTouchCount = 2;
|
|
|
+
|
|
|
+ private GameObject bodyParent;
|
|
|
+ private GameObject bgParent;
|
|
|
+ private GameObject npcParent;
|
|
|
+ private GameObject borderParent;
|
|
|
+ private GameObject sceneParent;
|
|
|
+
|
|
|
private List<int> _listData = null;//当前选择的资源数据
|
|
|
private List<int> _equipRoleData = new List<int>();//当前穿戴的角色数据
|
|
|
private Dictionary<int, List<int>> _equipSceneData = new Dictionary<int, List<int>>();//当前穿戴的场景数据
|
|
|
|
|
|
- private Vector3 distance = Vector3.zero;
|
|
|
+ // private GameObject hitGameObj;//当前选中的物体
|
|
|
+ private GameObject hitParentGameObj;//当前选中的父物体(需要进行移动缩放旋转的物体)
|
|
|
+ private Vector3 distance = Vector3.zero;//点击位置和点击物体原点的距离,用于
|
|
|
+
|
|
|
+ private Vector2 firstTouchLastPos = Vector2.zero;//第一根手指上一次的位置
|
|
|
+ private Vector2 secondTouchLastPos = Vector2.zero;//第二根手指上一次的位置
|
|
|
+
|
|
|
+ private PinchGesture pinchGesture;
|
|
|
+ private RotationGesture rotationGesture;
|
|
|
protected override void OnInit()
|
|
|
{
|
|
|
base.OnInit();
|
|
@@ -32,12 +51,17 @@ namespace GFGGame
|
|
|
_ui.m_btnChoose.onClick.Add(OnClickBtnChoose);
|
|
|
_ui.m_btnBack.onClick.Add(OnClickBtnBack);
|
|
|
|
|
|
- _ui.m_ComSelect.m_list.itemRenderer = RenderListItem;
|
|
|
- _ui.m_ComSelect.m_list.onClickItem.Add(OnListItemClick);
|
|
|
- _ui.m_ComSelect.m_c1.onChanged.Add(OnContorllerChanged);
|
|
|
+ _ui.m_ComSelectRes.m_list.itemRenderer = RenderListItem;
|
|
|
+ _ui.m_ComSelectRes.m_list.onClickItem.Add(OnListItemClick);
|
|
|
+ _ui.m_ComSelectRes.m_c1.onChanged.Add(OnContorllerChanged);
|
|
|
|
|
|
_scenePrefab = GFGAsset.Load<GameObject>(ResPathUtil.GetPrefabPath("ScenePhotograph"));
|
|
|
|
|
|
+ _ui.target.onTouchBegin.Add(OnClickUIBegin);
|
|
|
+ _ui.target.onTouchMove.Add(OnClickUIMove);
|
|
|
+ _ui.target.onTouchEnd.Add(OnClickUIEnd);
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
protected override void OnShown()
|
|
@@ -50,9 +74,18 @@ namespace GFGGame
|
|
|
{
|
|
|
_sceneObject = GameObject.Instantiate(_scenePrefab);
|
|
|
EquipDataCache.cacher.setSceneObj(_sceneObject);
|
|
|
+ bgParent = _sceneObject.transform.Find("Bg").gameObject;
|
|
|
+ bodyParent = _sceneObject.transform.Find("Scene/Role").gameObject;
|
|
|
+ sceneParent = _sceneObject.transform.Find("Scene").gameObject;
|
|
|
+ npcParent = _sceneObject.transform.Find("Scene/Npc").gameObject;
|
|
|
+ borderParent = _sceneObject.transform.Find("Border").gameObject;
|
|
|
}
|
|
|
+ pinchGesture = new PinchGesture(_ui.m_comSelectBox.target);
|
|
|
+ pinchGesture.onAction.Add(OnPinch);
|
|
|
+ rotationGesture = new RotationGesture(_ui.m_comSelectBox.target);
|
|
|
+ rotationGesture.onAction.Add(OnRotate);
|
|
|
|
|
|
- _ui.m_ComSelect.m_c1.selectedIndex = 0;
|
|
|
+ _ui.m_ComSelectRes.m_c1.selectedIndex = 0;
|
|
|
OnClickBtnChoose();
|
|
|
RefreshList(EnumPhotographType.BG);
|
|
|
UpdateEquipData();
|
|
@@ -66,12 +99,12 @@ namespace GFGGame
|
|
|
/************************************************************UI界面*********************************************************/
|
|
|
private void OnContorllerChanged(EventContext context)
|
|
|
{
|
|
|
- int index = _ui.m_ComSelect.m_c1.selectedIndex;
|
|
|
+ int index = _ui.m_ComSelectRes.m_c1.selectedIndex;
|
|
|
RefreshList((EnumPhotographType)index);
|
|
|
}
|
|
|
private void RefreshList(EnumPhotographType index)
|
|
|
{
|
|
|
- _ui.m_ComSelect.m_list.numItems = 0;
|
|
|
+ _ui.m_ComSelectRes.m_list.numItems = 0;
|
|
|
|
|
|
switch (index)
|
|
|
{
|
|
@@ -91,7 +124,7 @@ namespace GFGGame
|
|
|
_listData = PhotographDataManager.Instance.listEffectData;
|
|
|
break;
|
|
|
}
|
|
|
- _ui.m_ComSelect.m_list.numItems = _listData.Count;
|
|
|
+ _ui.m_ComSelectRes.m_list.numItems = _listData.Count;
|
|
|
}
|
|
|
private void RenderListItem(int index, GObject obj)
|
|
|
{
|
|
@@ -105,7 +138,7 @@ namespace GFGGame
|
|
|
private void OnListItemClick(EventContext context)
|
|
|
{
|
|
|
int itemID = (int)((context.data as GObject).data);
|
|
|
- EnumPhotographType type = (EnumPhotographType)_ui.m_ComSelect.m_c1.selectedIndex;
|
|
|
+ EnumPhotographType type = (EnumPhotographType)_ui.m_ComSelectRes.m_c1.selectedIndex;
|
|
|
switch (type)
|
|
|
{
|
|
|
case EnumPhotographType.BG:
|
|
@@ -120,7 +153,7 @@ namespace GFGGame
|
|
|
_equipSceneData.Add(itemID, new List<int>());
|
|
|
}
|
|
|
_equipSceneData[itemID].Add(itemID);
|
|
|
- AddScene(itemID, _equipSceneData[itemID].Count - 1);
|
|
|
+ SceneController.AddScene(_sceneObject, itemID, _equipSceneData[itemID].Count - 1);
|
|
|
|
|
|
break;
|
|
|
case EnumPhotographType.EFFECT:
|
|
@@ -130,123 +163,155 @@ namespace GFGGame
|
|
|
}
|
|
|
/************************************************************场景*********************************************************/
|
|
|
|
|
|
- private void OnTimerListener(object param)
|
|
|
+ private void OnClickUIBegin(EventContext context)
|
|
|
{
|
|
|
- GameObject gameObj = null;
|
|
|
- // Debug.Log("点击鼠标:" + Input.GetMouseButtonDown(0));
|
|
|
- if (Input.GetMouseButtonDown(0))
|
|
|
+ context.CaptureTouch();
|
|
|
+ if (_ui.m_ComSelectRes.target.visible == true) return;
|
|
|
+
|
|
|
+ if (context.inputEvent.touchId == 0)
|
|
|
{
|
|
|
- if (Stage.isTouchOnUI) //点在了UI上
|
|
|
- {
|
|
|
- Debug.Log("点击UI");
|
|
|
- }
|
|
|
- else //没有点在UI上
|
|
|
- {
|
|
|
- Debug.Log("点击场景");
|
|
|
- }
|
|
|
- //从摄像机发出到点击坐标的射线
|
|
|
- RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
|
|
|
- // Vector2 pos = Input.mousePosition;
|
|
|
- // Debug.Log("mousePosition:" + pos);
|
|
|
- if (hit.collider != null)
|
|
|
- {
|
|
|
- //划出射线,只有在scene视图中才能看到
|
|
|
- // Debug.DrawLine(ray.origin, hitInfo.point, Color.red);
|
|
|
- gameObj = hit.collider.gameObject;
|
|
|
- Debug.Log("ClickName:" + gameObj.name);
|
|
|
- // Debug.Log("ClickName:" + gameObj.name + " Pos:" + gameObj.transform.position + " LocalPos:" + gameObj.transform.position);
|
|
|
- // Debug.Log("mousePosition:" + Input.mousePosition);
|
|
|
- // Debug.Log("boxPos:" + _ui.m_comChecked.target.position);
|
|
|
- // //当射线碰撞目标为boot类型的物品,执行拾取操作
|
|
|
- // if (gameObj.tag == "boot")
|
|
|
- // {
|
|
|
- // Debug.Log("pickup!");
|
|
|
- // }
|
|
|
- }
|
|
|
+ firstTouchLastPos = Stage.inst.touchPosition;
|
|
|
+ }
|
|
|
+ else if (context.inputEvent.touchId == 1)
|
|
|
+ {
|
|
|
+ secondTouchLastPos = Stage.inst.touchPosition;
|
|
|
}
|
|
|
- // Vector2 pos = Input.mousePosition;
|
|
|
- // Debug.Log("mousePosition:" + pos);
|
|
|
-
|
|
|
- if (gameObj == null) return;
|
|
|
- GameObject obj = GetMoveObjByHitObj(gameObj);
|
|
|
|
|
|
- if (Input.touchCount <= 0) { return; }
|
|
|
- Debug.Log("触摸屏幕的手指个数:" + Input.touchCount);
|
|
|
- // for (var touch : Touch in Input.touches)
|
|
|
- // {
|
|
|
- if (Input.GetTouch(0).phase == TouchPhase.Began)
|
|
|
+ if (context.inputEvent.touchId != 0) return;
|
|
|
+ RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
|
|
|
+ if (hit.collider != null)
|
|
|
{
|
|
|
- Debug.Log("触摸:" + "Began");
|
|
|
|
|
|
- Vector3 objScreenPos = Camera.main.WorldToScreenPoint(obj.transform.position);
|
|
|
- distance = Input.mousePosition - objScreenPos;
|
|
|
+ hitParentGameObj = hit.collider.name == "BgRes" ? hit.collider.gameObject : hit.collider.transform.parent.gameObject;
|
|
|
+ distance = Input.mousePosition - Camera.main.WorldToScreenPoint(hitParentGameObj.transform.position);
|
|
|
+ Debug.Log("ClickName:" + hitParentGameObj.name);
|
|
|
|
|
|
- }
|
|
|
- if (Input.GetTouch(0).phase == TouchPhase.Moved)
|
|
|
- {
|
|
|
- Debug.Log("触摸:" + "Moved");
|
|
|
- // Vector3 distance =
|
|
|
+ _ui.m_comSelectBox.target.visible = hitParentGameObj.transform.parent.gameObject == bgParent ? false : true;
|
|
|
+ _ui.m_comSelectBox.target.size = SceneController.GetGameObjectSize(hitParentGameObj);
|
|
|
|
|
|
- ControllerObject(obj);
|
|
|
- }
|
|
|
- if (Input.GetTouch(0).phase == TouchPhase.Stationary)
|
|
|
- {
|
|
|
|
|
|
- Debug.Log("触摸:" + "Stationary");
|
|
|
- }
|
|
|
- if (Input.GetTouch(0).phase == TouchPhase.Ended)
|
|
|
- {
|
|
|
- Debug.Log("触摸:" + "Ended");
|
|
|
- distance = Vector3.zero;
|
|
|
+ ControllerSelectBoxPos(hitParentGameObj);
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
- private GameObject GetMoveObjByHitObj(GameObject obj)
|
|
|
+
|
|
|
+ private void OnClickUIMove(EventContext context)
|
|
|
{
|
|
|
- // if (obj == null) return null;
|
|
|
- if (obj.transform.parent == _sceneObject.transform.Find("Bg") || obj.transform.parent == _sceneObject.transform.Find("Npc"))
|
|
|
+ if (hitParentGameObj == null) return;//未选中任何物体
|
|
|
+ if (Stage.inst.touchCount > MaxTouchCount) return;//只监听两根手指
|
|
|
+ string state = GetTransformState();
|
|
|
+ if (state == MOVE)
|
|
|
+ {
|
|
|
+ ControllerObjectPos(hitParentGameObj);
|
|
|
+ ControllerSelectBoxPos(hitParentGameObj);
|
|
|
+ }
|
|
|
+ else if (state == ROTATION)
|
|
|
{
|
|
|
- return obj;//背景和npc拖动物体本身
|
|
|
+ // Vector2 lastTransform = secondTouchLastPos - firstTouchLastPos;
|
|
|
+ // Vector2 curTransform = Stage.inst.GetTouchPosition(1) - Stage.inst.GetTouchPosition(0);
|
|
|
+ // float angle = SceneController.GetRotationAngle(lastTransform, curTransform);
|
|
|
+ // _ui.m_comSelectBox.target.rotation += angle;
|
|
|
+ // hitParentGameObj.transform.rotation = Quaternion.Euler(new Vector3(hitParentGameObj.transform.rotation.x, hitParentGameObj.transform.rotation.y, hitParentGameObj.transform.rotation.z + angle));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- return obj.transform.parent.gameObject;//场景要拖动父物体
|
|
|
+ // Vector2 lastTransform = secondTouchLastPos - firstTouchLastPos;
|
|
|
+ // Vector2 curTransform = Stage.inst.GetTouchPosition(1) - Stage.inst.GetTouchPosition(0);
|
|
|
+ // float scale = curTransform.magnitude / lastTransform.magnitude;
|
|
|
+ // _ui.m_comSelectBox.target.SetScale(scale, scale);
|
|
|
+ // hitParentGameObj.transform.localScale = new Vector3(scale, scale, scale);
|
|
|
}
|
|
|
}
|
|
|
- private void ControllerObject(GameObject obj)
|
|
|
+ private void OnPinch(EventContext context)
|
|
|
+ {
|
|
|
+ GTween.Kill(hitParentGameObj);
|
|
|
+
|
|
|
+ PinchGesture gesture = (PinchGesture)context.sender;
|
|
|
+ float newValue = Mathf.Clamp(hitParentGameObj.transform.localScale.x + gesture.delta, 0.3f, 2);
|
|
|
+ hitParentGameObj.transform.localScale = new Vector3(newValue, newValue, newValue);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void OnRotate(EventContext context)
|
|
|
+ {
|
|
|
+ GTween.Kill(hitParentGameObj.transform);
|
|
|
+
|
|
|
+ RotationGesture gesture = (RotationGesture)context.sender;
|
|
|
+ hitParentGameObj.transform.Rotate(Vector3.forward, -gesture.delta, Space.World);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void OnClickUIEnd(EventContext context)
|
|
|
{
|
|
|
- if (obj.name == "BgRes")
|
|
|
+ hitParentGameObj = null;
|
|
|
+ firstTouchLastPos = Vector3.zero;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //选中物体的位置
|
|
|
+ private void ControllerObjectPos(GameObject hitParentGameObj)
|
|
|
+ {
|
|
|
+ hitParentGameObj.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition - distance);
|
|
|
+ if (hitParentGameObj.name == "BgRes")
|
|
|
{
|
|
|
- Vector2 size = obj.GetComponent<SpriteRenderer>().size;
|
|
|
+ Vector2 size = hitParentGameObj.GetComponent<SpriteRenderer>().size;
|
|
|
Vector2 uiSize = _ui.target.size;
|
|
|
- float deviationWidth = (size.x - uiSize.x) / 2;
|
|
|
- float deviationHeigh = (size.y - uiSize.y) / 2;
|
|
|
- Vector2 pos = obj.transform.position;
|
|
|
+ float deviationWidth = (size.x - uiSize.x / 100) / 2;
|
|
|
+ float deviationHeigh = (size.y - uiSize.y / 100) / 2;
|
|
|
+ Vector2 pos = hitParentGameObj.transform.position;
|
|
|
if (pos.x <= -deviationWidth)
|
|
|
{
|
|
|
- obj.transform.position = new Vector2(-deviationWidth, obj.transform.position.y);
|
|
|
- return;
|
|
|
+ hitParentGameObj.transform.position = new Vector2(-deviationWidth, hitParentGameObj.transform.position.y);
|
|
|
}
|
|
|
if (pos.x >= deviationWidth)
|
|
|
{
|
|
|
- obj.transform.position = new Vector2(deviationWidth, obj.transform.position.y);
|
|
|
- return;
|
|
|
+ hitParentGameObj.transform.position = new Vector2(deviationWidth, hitParentGameObj.transform.position.y);
|
|
|
}
|
|
|
if (pos.y <= -deviationHeigh)
|
|
|
{
|
|
|
- obj.transform.position = new Vector2(obj.transform.position.x, -deviationHeigh);
|
|
|
- return;
|
|
|
+ hitParentGameObj.transform.position = new Vector2(hitParentGameObj.transform.position.x, -deviationHeigh);
|
|
|
}
|
|
|
- if (pos.x >= deviationHeigh)
|
|
|
+ if (pos.y >= deviationHeigh)
|
|
|
{
|
|
|
- obj.transform.position = new Vector2(obj.transform.position.x, deviationHeigh);
|
|
|
- return;
|
|
|
+ hitParentGameObj.transform.position = new Vector2(hitParentGameObj.transform.position.x, deviationHeigh);
|
|
|
}
|
|
|
}
|
|
|
- // obj.transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x - distance.x, Input.mousePosition.y - distance.y));
|
|
|
- obj.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition - distance);
|
|
|
}
|
|
|
+ //选中框的大小位置旋转
|
|
|
+ private void ControllerSelectBoxPos(GameObject hitParentGameObj)
|
|
|
+ {
|
|
|
+ SceneController.SetGameObjectCenter(hitParentGameObj);
|
|
|
+ //位置:角色、道具、npc全用对应父物体的位置
|
|
|
+ Vector2 objScreenPos = Camera.main.WorldToScreenPoint(hitParentGameObj.transform.position);
|
|
|
+ Vector2 localPos = new Vector2(objScreenPos.x, Screen.height - objScreenPos.y);
|
|
|
+ _ui.m_comSelectBox.target.SetXY(localPos.x, localPos.y);
|
|
|
|
|
|
+ }
|
|
|
|
|
|
+ private string GetTransformState()
|
|
|
+ {
|
|
|
+ if (Stage.inst.touchCount == 1) return MOVE;//一根手指只能移动
|
|
|
+
|
|
|
+ Vector2 lastDistance = secondTouchLastPos - firstTouchLastPos;
|
|
|
+ Vector2 curDistance = Stage.inst.GetTouchPosition(1) - Stage.inst.GetTouchPosition(0);
|
|
|
+
|
|
|
+ if (lastDistance == curDistance)
|
|
|
+ {
|
|
|
+ return MOVE;//向量大小和方向都不变是位移
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (lastDistance.magnitude != curDistance.magnitude)
|
|
|
+ {
|
|
|
+ //两指距离有变化是缩放
|
|
|
+ return SCALE;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //两指距离无变化是缩放
|
|
|
+ return ROTATION;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
//背景
|
|
|
private void UpdateBgOrNpcOrBorder(EnumPhotographType type, int itemId)
|
|
|
{
|
|
@@ -259,13 +324,13 @@ namespace GFGGame
|
|
|
{
|
|
|
|
|
|
// int[] equipDatas = equipDataCache.equipDatas;
|
|
|
- SceneController.UpdateRole(_equipRoleData.ToArray(), _sceneObject, false, null, false);
|
|
|
+ SceneController.UpdateRole(_equipRoleData.ToArray(), _sceneObject, false, null, false, bodyParent);
|
|
|
if (equipDataCache.IsSuitPic && equipDataCache.suitId > 0)
|
|
|
{
|
|
|
SuitCfg suitCfg = SuitCfgArray.Instance.GetCfg(equipDataCache.suitId);
|
|
|
- DressUpUtil.UpdateBody(suitCfg.picRes, _sceneObject);
|
|
|
+ DressUpUtil.UpdateBody(suitCfg.picRes, _sceneObject, false, null, false, bodyParent);
|
|
|
}
|
|
|
- GameObject gameObject = _sceneObject.transform.Find("Role/Body").gameObject;
|
|
|
+ GameObject gameObject = _sceneObject.transform.Find("Scene/Role/Body").gameObject;
|
|
|
|
|
|
SceneController.PhotographAddCollider(gameObject);
|
|
|
|
|
@@ -278,23 +343,11 @@ namespace GFGGame
|
|
|
{
|
|
|
for (int i = 0; i < _equipSceneData[key].Count; i++)
|
|
|
{
|
|
|
- AddScene(key, i);
|
|
|
+ SceneController.AddScene(_sceneObject, key, i);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- //场景添加道具
|
|
|
- private void AddScene(int itemId, int index)
|
|
|
- {
|
|
|
- var gameObj = new GameObject(string.Format("{0}_{1}", itemId, index));
|
|
|
- gameObj.transform.SetParent(_sceneObject.transform.Find("Scene"), false);
|
|
|
- // SceneController.UpdateRole(itemId, _sceneObject, false, null, false, gameObj);
|
|
|
- DressUpUtil.AddItem(itemId, _sceneObject, false, false, gameObj);
|
|
|
- for (int i = 0; i < gameObj.transform.childCount; i++)
|
|
|
- {
|
|
|
- SceneController.PhotographAddCollider(gameObj.transform.GetChild(i).gameObject);
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
//滤镜效果
|
|
|
private void UpdateEffect()
|
|
@@ -326,17 +379,14 @@ namespace GFGGame
|
|
|
}
|
|
|
private void OnClickBtnBg()
|
|
|
{
|
|
|
- _ui.m_ComSelect.target.visible = false;
|
|
|
- Timers.inst.Add(0.001f, 0, OnTimerListener);
|
|
|
+ _ui.m_ComSelectRes.target.visible = false;
|
|
|
|
|
|
- // _ui.target.opaque = false;//false表示可穿透
|
|
|
}
|
|
|
private void OnClickBtnChoose()
|
|
|
{
|
|
|
- _ui.m_ComSelect.target.visible = true;
|
|
|
- Timers.inst.Remove(OnTimerListener);
|
|
|
-
|
|
|
- // _ui.target.opaque = true;
|
|
|
+ _ui.m_ComSelectRes.target.visible = true;
|
|
|
+ _ui.m_comSelectBox.target.visible = false;
|
|
|
+ hitParentGameObj = null;
|
|
|
}
|
|
|
private void OnClickBtnBack()
|
|
|
{
|
|
@@ -352,11 +402,15 @@ namespace GFGGame
|
|
|
GameObject.Destroy(_sceneObject);
|
|
|
_sceneObject = null;
|
|
|
}
|
|
|
- Timers.inst.Remove(OnTimerListener);
|
|
|
equipDataCache = null;
|
|
|
_equipRoleData.Clear();
|
|
|
_equipSceneData.Clear();
|
|
|
+ hitParentGameObj = null;
|
|
|
|
|
|
+ pinchGesture.onAction.Remove(OnPinch);
|
|
|
+ rotationGesture.onAction.Remove(OnRotate);
|
|
|
+ pinchGesture = null;
|
|
|
+ rotationGesture = null;
|
|
|
}
|
|
|
public override void Dispose()
|
|
|
{
|