using Assets.Scripts.Apis; using Assets.Scripts.Apis.Models; using System; using System.Linq; using System.Collections; using System.Collections.Generic; using UnityEngine.Networking; using Assets.Scenes.Ride.Scripts.Model; using Assets.Scenes.Ride.Scripts.Model.CyclingModels; using Assets.Scenes.Ride.Scripts; using Mapbox.Unity.Map; using UnityEngine; using GeoJSON.Net.Geometry; using TurfCS; using Mapbox.Utils; using Assets.Scripts; using System.Threading.Tasks; using UnityEngine.EventSystems; using UnityEngine.Events; public class CyclingController : DeviceServiceMonoBase { public AbstractMap map; public GameObject player; public GameObject UIObject; public RouteResultParam selectParamModel; public RouteResult routeResult; public int preticks; #region 参数 private MapRoute mapRoute;//当前路书数据 private MapDataModel mapData;//当前路书数据 private Route route;//当前路书综合数据 public List mapRouteRankingList; private Vector2d coordiantes;//当前地图中心 public bool isStart;//当前游戏是否开始 public CyclingModel cyclingModel;//当前骑行模式 public BaseCycling cyclingController { get; set; } private int routeId; private MapApi mapApi; public DateTime startTime; public DateTime endTime; public bool isQuit; public bool isPause; #endregion GameObject loadingcanvas; LoadingController loadingController; private async Task Login() { var result = await new UserApi().Login("13115011550", "laozhong", ""); App.CurrentUser = result.data; } GameObject miniMap; GameObject resultPanel; void Awake() { #if UNITY_EDITOR if (App.CurrentUser == null) { Login(); } #endif //获取路书信息 mapApi = ConfigHelper.mapApi; routeId = App.RouteIdParam > 0? App.RouteIdParam : 2633; //mapRoute = mapApi.GetById(routeId).data; //miniMap = transform.Find("MiniMap").gameObject;//小地图 resultPanel = transform.Find("SingleUI/Panel/ResultPanel").gameObject; } Transform target; private void Start() { UIManager.Instance.MainPanel = this.transform.Find("SingleUI/Panel").GetComponent(); UIManager.Instance.ModalsPanel = this.transform.Find("SingleUI/ModalPanel").GetComponent(); target = transform.Find("Target"); //进入倒计时 singleUIManager = UIObject.GetComponent(); loadingController = FindObjectOfType(); loadingController.InjectController(this); //开始loading StartCoroutine(Init()); } public void SetUIManager(PFUIPanel mainPanel, PFUIPanel model) { UIManager.Instance.MainPanel = mainPanel;//this.transform.Find("SingleUI/Panel").GetComponent(); UIManager.Instance.ModalsPanel = model;// this.transform.Find("SingleUI/ModalPanel").GetComponent(); } public void ReSetUIManager() { UIManager.Instance.MainPanel = this.transform.Find("SingleUI/Panel").GetComponent(); UIManager.Instance.ModalsPanel = this.transform.Find("SingleUI/ModalPanel").GetComponent(); } public void AddEvent(GameObject sender, EventTriggerType eventType,UnityAction unityAction) { UIManager.AddEvent(sender, eventType, unityAction); } public void ShowDevice(PFUIPanel pFUIPanel) { UIManager.Show(UIManager.Instance.DevicePanel, pFUIPanel); } public Texture GetCountryImageByCode(string code) { return UIManager.Instance.loginRegOptions.GetCountryImage(code); } public Texture GetCountryImageByName(string name) { return UIManager.Instance.loginRegOptions.GetCountryImageByName(name); } private IEnumerator Init() { yield return new WaitForSeconds(1); mapRoute = mapApi.GetById(routeId).data; miniMap = transform.Find("MiniMap").gameObject;//小地图 loadingController.Init(mapRoute);//初始化loading页面 loadingController.AddProcess(10); InitData();//初始化数据 InitGameObject();//初始化场景 MapUDPService.Init();//初始化TCP loadingController.AddProcess(10); } //初始化数据 private void InitData() { mapData = mapApi.GetData(routeId);//获取路书地理数据 route = new Route(mapData, mapRoute); loadingController.AddProcess(10); #region 其他场景传参处理 //骑行结果 if (App.routeResult != null ) { routeResult = App.routeResult; selectParamModel = App.routeResult.ContinueCyclingParam;//继续骑行 preticks = App.routeResult.Ticks; } if (selectParamModel == null) { selectParamModel = new RouteResultParam { CompetitionId = 0, ContinueIndex = 0, ContinueMark = "", GlobalContinue = false, EndDistance = 0, RankingsId = new List(), OnlineUserId = 0, RouteId = App.RouteIdParam }; } App.routeResult = null; #endregion //异步请求mapbox画出当前路书路线图 loadingController.DrawMapRoute(mapData); //计算上次骑行距离调整地图中心点 double endDistance = selectParamModel.EndDistance; coordiantes = Along(endDistance); loadingController.AddProcess(10); //查询排行榜 var list = mapApi.GetRouteRanking(App.RouteIdParam, "1", 0, 10, ""); if (list.result) { mapRouteRankingList = list.data.list; loadingController.CreateRankingList(mapRouteRankingList); loadingController.AddProcess(10); } } //加载人物和地图以及UI界面 private void InitGameObject() { map.gameObject.SetActive(true); player.SetActive(true); UIObject.SetActive(true); miniMap.SetActive(true); map.OnTileFinished += Map_OnTileFinished; } //private void Map_OnTileFinished(Mapbox.Unity.MeshGeneration.Data.UnityTile obj) //{ // var playerController = player.GetComponent(); // player.transform.position = map.GeoToWorldPosition(playerController.Currentlatlong); //} //设置骑行模式 public void SetCyclingModel(CyclingModel mode) { this.cyclingModel = mode; switch (cyclingModel) { case CyclingModel.Single: cyclingController = new SingleModel(route, selectParamModel); break; case CyclingModel.Review: cyclingController = new ReviewModel(route, selectParamModel); break; } AutoStart(); InitPlayer(); } //初始化人物位置角度 private void InitPlayer() { lockView = true; TrailRenderer trail = player.GetComponent(); PlayerController playerController = player.GetComponent(); Vector2d lastLatLon = Along(recorderData.EndDistance); Vector3 currentPos = map.GeoToWorldPosition(lastLatLon); currentPos.y += 1f; player.transform.position = currentPos; playerController.currentPos = currentPos; trail.Clear(); Vector2d nextLatLon = Along(recorderData.EndDistance + 0.1); //设定人物方向 var s = map.GeoToWorldPosition(lastLatLon); var e = map.GeoToWorldPosition(nextLatLon); Quaternion neededRotation = Quaternion.LookRotation(s - e); player.transform.rotation = Quaternion.Euler(0, neededRotation.eulerAngles.y, 0); playerController.currentRotation = neededRotation; } SingleUIManager singleUIManager; public void AutoStart() { singleUIManager.StartRide(null); } public void GoContinueRide() { singleUIManager.ContinueRide(); } #region public bool Is3dView; public void ChangeMapImageStyle(GameObject arrowGameObj) { var playerController = player.GetComponent(); var trailRenderer = player.GetComponent(); trailRenderer.time = 0; StartCoroutine(EnableTrailRenderer(trailRenderer)); if (!Is3dView) { //地图属性变更 map.Terrain.ExaggerationFactor = 1.5f; map.Terrain.SetElevationType(ElevationLayerType.TerrainWithElevation); map.ImageLayer.SetLayerSource(ImagerySourceType.Custom); map.SetCenterLatitudeLongitude(playerController.Currentlatlong); //人物属性变更 var pos = map.GeoToWorldPosition(playerController.Currentlatlong); playerController.currentPos = pos; target.position = pos; player.transform.localScale = new Vector3(3f, 3f, 3f); player.transform.position = pos; arrowGameObj.SetActive(false); Is3dView = true; } else { //地图属性变更 map.ImageLayer.SetLayerSource(ImagerySourceType.JuzeTest); map.Terrain.ExaggerationFactor = 0f; map.Terrain.SetElevationType(ElevationLayerType.FlatTerrain); map.SetCenterLatitudeLongitude(playerController.Currentlatlong); //人物属性变更 var pos = map.GeoToWorldPosition(playerController.Currentlatlong); player.transform.position = pos; player.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); target.position = pos; playerController.currentPos = Vector3.zero; arrowGameObj.SetActive(true); Is3dView = false; } } private bool lockView = false; private void Map_OnTileFinished(Mapbox.Unity.MeshGeneration.Data.UnityTile obj) { if (!lockView) { var playerController = player.GetComponent(); player.transform.localScale = new Vector3(3f, 3f, 3f); var locations = playerController.Currentlatlong == null ? playerController.Currentlatlong : new Vector2d(mapData.List[0].Point[0], mapData.List[0].Point[1]); player.transform.position = map.GeoToWorldPosition(locations); if (recorderData != null) { var lastLatLon = Along(recorderData.EndDistance); var nextLatLon = Along(recorderData.EndDistance+0.1); player.transform.position = map.GeoToWorldPosition(lastLatLon); //设定人物方向 var s = map.GeoToWorldPosition(lastLatLon); var e = map.GeoToWorldPosition(nextLatLon); Quaternion neededRotation = Quaternion.LookRotation(s - e); player.transform.rotation = Quaternion.Euler(0, neededRotation.eulerAngles.y, 0); } } } IEnumerator EnableTrailRenderer(TrailRenderer trailRenderer) { yield return new WaitForSeconds(2f); trailRenderer.Clear(); trailRenderer.time = 30; } #endregion #region 游戏状态控制 //开始骑行 public void SetStart() { if (!isPause || DateTime.MinValue == startTime) { isStart = true; startTime = DateTime.Now; } else { SetContinue(); } } //继续骑行 public void SetContinue() { isStart = true; isPause = false; } //暂停骑行 public void SetPause() { isStart = false; isPause = true; } //退出或者完成骑行 public void SetQuit() { isStart = false; isQuit = true; } #endregion #region 数据处理 /// /// 当前骑行数据的记录器 /// private RecorderDataModel recorderData { get { return cyclingController?.recorderData; } } public Route GetRoute() { return route; } public MapDataModel GetMapData() { return mapData; } public void Save(double totalDistance) { isQuit = true; isStart = false; string recordId = Guid.NewGuid().ToString(); var path = Helper.GetDataDir("MapWorkoutRecords/"+ recordId); string imageFileName = path +"/"+ Guid.NewGuid().ToString() + ".png"; CaptureCamera(Camera.main, new Rect(Screen.width * 0f, Screen.height * 0f, Screen.width * 0.5f, Screen.height * 0.5f), imageFileName); cyclingController.recorderData.StartTime = startTime; cyclingController.recorderData.IsCompleted = totalDistance == mapData.TotalDistance; cyclingController.recorderData.EndDistance = totalDistance; cyclingController.recorderData.AntModelId = AntModelId; cyclingController.recorderData.ManufacturerId = ManufacturerId; cyclingController.recorderData.DeviceNumber = DeviceNumber; //显示骑行结果 resultPanel.SetActive(true); var rs = resultPanel.GetComponent(); rs.InjectController(this); rs.SetDataSource(cyclingController.recorderData); cyclingController.recorderData.SaveLocal(cyclingModel, selectParamModel, imageFileName, recordId); } protected void CaptureCamera(Camera camera, Rect rect,string fileName) { // 创建一个RenderTexture对象 RenderTexture rt = new RenderTexture((int)rect.width, (int)rect.height, 0); // 临时设置相关相机的targetTexture为rt, 并手动渲染相关相机 camera.targetTexture = rt; camera.Render(); //ps: --- 如果这样加上第二个相机,可以实现只截图某几个指定的相机一起看到的图像。 //ps: camera2.targetTexture = rt; //ps: camera2.Render(); //ps: ------------------------------------------------------------------- // 激活这个rt, 并从中中读取像素。 RenderTexture.active = rt; Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false); screenShot.ReadPixels(rect, 0, 0);// 注:这个时候,它是从RenderTexture.active中读取像素 screenShot.Apply(); // 重置相关参数,以使用camera继续在屏幕上显示 camera.targetTexture = null; //ps: camera2.targetTexture = null; RenderTexture.active = null; // JC: added to avoid errors GameObject.Destroy(rt); // 最后将这些纹理数据,成一个图片文件 byte[] bytes = screenShot.EncodeToPNG(); //var path = Helper.GetDataDir("MapWorkoutRecords/images"); //string filename = path + "/" + Guid.NewGuid().ToString() + ".png"; System.IO.File.WriteAllBytes(fileName, bytes); //Debug.Log(string.Format("截屏了一张照片: {0}", filename)); } public Vector2d GetCenterCoordinate() { return coordiantes; } public Vector2d Along(double endDistance) { if (mapData != null) { var list = mapData.List.Select(p => new GeoJSON.Net.Geometry.GeographicPosition(p.Point[0], p.Point[1])); LineString lineString = new LineString(list); var pt1 = Turf.Along(lineString, endDistance); var ll = ((GeographicPosition)((GeoJSON.Net.Geometry.Point)pt1.Geometry).Coordinates); return new Vector2d(ll.Latitude, ll.Longitude); } else { return new Vector2d(0,0); } } /// /// 海拔图数据 /// public float[] GetRealTimeLineChartData(int index) { List dist = new List(); var list = mapData.List.Select(c => (float) c.Elevation ).ToArray(); var count = list.Count(); for (int i = 0; i < count; i++) { if (i > index) { dist.Add(list[i]); } } return dist.ToArray(); } public float[] GetLineChartData() { var list = mapData.List.Select(c => (float)c.Elevation).ToArray(); return list; } #endregion }