using DG.Tweening; using RenderHeads.Media.AVProVideo; using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Linq; using UnityEngine; using System.IO; using Assets.Scripts.Scenes.VideoRide; using System.Reflection; using UnityEngine.UI; using Assets.Scripts; using FluffyUnderware.Curvy; using FluffyUnderware.Curvy.Controllers; using Mapbox.Utils; using Mapbox.Unity.Map; using Assets.Scripts.Apis.Models; using Mapbox.Unity.MeshGeneration.Data; public class TestVideoController : MonoBehaviour { public Transform Player; public GameObject QuitBtn; public GameObject PauseBtn; public GameObject CancelBtn; public Transform Quad; public Transform Light; public Transform FrameContent; public GameObject FrameBtnPrefab; public GameObject PreviewBtn; public GameObject SaveBtn; public GameObject ResetBtn; public GameObject DeleteBtn; public MediaPlayer mediaPlayer; public Text Frametext; public TrailRenderer trailRenderer; private Dictionary list = new Dictionary(); Vector3 originPos = new Vector3(0, -1, 3); Vector3 originRotation = Vector3.zero; // Start is called before the first frame update void Start() { lightRotation = new Vector3(50f,-45,0); InitConfig(); UIManager.AddEvent(QuitBtn, UnityEngine.EventSystems.EventTriggerType.PointerClick, (e) => { Application.Quit(); }); UIManager.AddEvent(PauseBtn, UnityEngine.EventSystems.EventTriggerType.PointerClick, (e) => { PlayOrPause(); }); UIManager.AddEvent(PreviewBtn, UnityEngine.EventSystems.EventTriggerType.PointerClick, (e) => { BuildList(); isPlay = true; mediaPlayer.Control.SeekFast(0); mediaPlayer.Play(); }); UIManager.AddEvent(slider.gameObject, UnityEngine.EventSystems.EventTriggerType.Drag, (e) => { OnTimeSliderDrag(); }); UIManager.AddEvent(SaveBtn, UnityEngine.EventSystems.EventTriggerType.PointerClick, (e) => { Vector3[] TrailRecorded = new Vector3[trailRenderer.positionCount]; trailRenderer.GetPositions(TrailRecorded); var curvy = CurvySpline.Create(); curvy.Interpolation = CurvyInterpolation.Bezier; foreach (var item in TrailRecorded) { curvy.Add(item); } DoRecord(); }); UIManager.AddEvent(ResetBtn, UnityEngine.EventSystems.EventTriggerType.PointerClick, (e) => { Player.DOMove(originPos,0); Player.DORotate(originRotation, 0); }); UIManager.AddEvent(CancelBtn, UnityEngine.EventSystems.EventTriggerType.PointerClick, (e) => { var k = mockRange.Where(c => c.KeyFrame == currentFrame).FirstOrDefault(); if (k != null) { Player.DOMove(new Vector3(k.PositionX, k.PositionY, k.PositionZ), 0); Player.DORotate(new Vector3(0, k.RotationY, k.RotationZ), 0); } }); UIManager.AddEvent(DeleteBtn, UnityEngine.EventSystems.EventTriggerType.PointerClick, (e) => { DeleteFrame(currentFrame); }); //默认轨迹1 switcher = FindObjectOfType(); var curve = switcher.GetDefaultController(); //控制轨迹根据当前运动员旋转 controller = Controller.GetComponent(); controller.Spline = curve; onlineController = onlinePlayer.GetComponent(); } SplineSwitcher switcher; public GameObject Controller; CurvySpline c { get; set; } List vlist = new List(); public Vector2d GetCenterCoordinate() { return new Vector2d(mapData.List[0].Point[0], mapData.List[0].Point[1]); } MapDataModel mapData; GameObject tracker; SplineController controller; public GameObject onlinePlayer; SplineController onlineController; public Text PlayBtnText; public Transform target; float timer = 0; // Update is called once per frame void Update() { Frametext.text = $"当前视频帧数:{GetCurrentFrame()}"; //视频播放时间 TimeRange timelineRange = GetTimelineRange(); double time = mediaPlayer.Control.GetCurrentTime(); sliderText.text = $"{ Assets.Scenes.Ride.Scripts.Helper.FormatTicks((int)Math.Floor(time))}/{Assets.Scenes.Ride.Scripts.Helper.FormatTicks((int)Math.Floor(timelineRange.duration))}"; if (timelineRange.duration != 0) { slider.value = (float)(time / timelineRange.duration); } timer -= Time.deltaTime; while (timer<0 && isPlay) { //controller.Position += 0.007f; timer += 1f; } //controller.Position += 0.0001f; ///(GetCurrentFrame() / 41225f)* 47.9f; if (controller.Position >= 1) { controller.Spline = switcher.Next(); controller.Position = 0; onlineController.Position = 0; onlineController.Spline = controller.Spline; } onlineController.Position = controller.Position + 0.015f; //轨迹运动 //tracker.transform.DOLocalMoveZ(Player.localPosition.z-3f, 0f); //轨迹旋转 //tracker.transform.DORotate(new Vector3(0, 0, 1), 1f); //键盘输入 CharacterControl(); //计算当前帧数在哪个区段 ComputeCurrentFrame(); //人物控制 if (isPlay) { Turn(); } //暂停或播放 var isPause = mediaPlayer.Control.IsPaused(); ResetBtn.SetActive(isPause); if (!isPause) { CancelBtn.SetActive(false); DeleteBtn.SetActive(false); } PlayBtnText.text = isPause ? "播放" : "暂停"; } public int currentFrame { get; set; } public void PlayToFrame(int frame) { var config = mockRange.Where(c => c.KeyFrame == frame).FirstOrDefault(); if (config != null) { CancelBtn.SetActive(true); DeleteBtn.SetActive(true); currentFrame = frame; SeekToFrame(frame); mediaPlayer.Pause(); isPlay = false; var rotation = new Vector3(0, config.RotationY, config.RotationZ); Player.DORotate(rotation, 0); var pos = new Vector3(config.PositionX, config.PositionY, config.PositionZ); //Player.DOMove(pos, 0); } } private string ConfigPath = Application.streamingAssetsPath + "/newdirection.txt"; //初始化配置 private void InitConfig() { var text = File.ReadAllText(ConfigPath); var arr = text.Replace("\r\n", " ").Split(' '); foreach (var item in arr) { if (!string.IsNullOrEmpty(item)) { int key = Convert.ToInt32(item.Split(':')[0]); list.Add(key, item); } } BuildList(); if (mockRange.Count > 0) { pre = mockRange[0]; next = mockRange[0]; } } private void DeleteFrame(int frame) { //删除当前帧数 var s = mockRange.Where(c => c.KeyFrame == frame).FirstOrDefault(); if (s != null) { mockRange.Remove(s); } if (list.ContainsKey(frame)) { list.Remove(frame); } //回到上一帧 var l = mockRange.OrderBy(c => c.KeyFrame).ToList(); var btnList = FindObjectsOfType(); var needRemove = btnList.Where(c => c.Frame == frame).FirstOrDefault(); if (needRemove != null) { needRemove.Destroy(); } var nextFrame = 0; foreach (var item in l) { if (item.KeyFrame < frame) { nextFrame = item.KeyFrame; } else { break; } } var btn = btnList.Where(c => c.Frame == nextFrame).FirstOrDefault(); if (btn != null) { btn.SelectFrame(nextFrame); } //同步到txt Save(); } TestVideoFrameButton[] btnList; private void BuildList() { var l = list.OrderBy(c => c.Key); mockRange.Clear(); Utils.DestroyChildren(FrameContent); foreach (var item in l) { mockRange.Add(CustomRange.Read(item.Value)); var btn = Instantiate(FrameBtnPrefab, FrameContent); btn.SetActive(true); btn.GetComponent().SetInfo(item.Key); } btnList = FindObjectsOfType(); } private bool isPlay { get; set; } = true; private List mockRange = new List(); private CustomRange pre; private CustomRange next; private void ComputeCurrentFrame() { var currentFrame = GetCurrentFrame(); var config = mockRange; if (config.Count == 0) return; for (int i = 0; i < config.Count; i++) { if (config[i].KeyFrame >= currentFrame) { pre = i > 0 ? config[i - 1] : config[i]; next = config[i]; break; } } if (mediaPlayer.Control.IsPlaying()) { foreach (var item in btnList) { item.SetBg(item.Frame == pre.KeyFrame); } } } private void Turn() { var currentFrame = GetCurrentFrame(); //控制人物的转向 var p = new Vector3(0, pre.RotationY, pre.RotationZ); var q = new Vector3(0, next.RotationY, next.RotationZ); var t = next.KeyFrame - pre.KeyFrame == 0? 1 : (float)(currentFrame - pre.KeyFrame) / (float)(next.KeyFrame - pre.KeyFrame); var rt = Vector3.Lerp(p, q, t); //Player.DORotate(rt, 0, RotateMode.Fast); //控制人物的前后左右上下 var l = new Vector3(pre.PositionX, pre.PositionY, pre.PositionZ); var s = new Vector3(next.PositionX, next.PositionY, next.PositionZ); var pos = Vector3.Lerp(l, s, t); //Player.DOMove(pos, 0); //控制光线 var z = new Vector3(50, pre.LightY, 0); var c = new Vector3(50, next.LightY, 0); var zc = Vector3.Lerp(z, c, t); //Light.DORotate(zc, 0); } public Slider slider; public Text sliderText; private void OnTimeSliderDrag() { if (mediaPlayer && mediaPlayer.Control != null) { TimeRange timelineRange = GetTimelineRange(); double time = timelineRange.startTime + ( slider.value*timelineRange.duration); mediaPlayer.Control.Seek(time); } } private TimeRange GetTimelineRange() { if (mediaPlayer.Info != null) { return Helper.GetTimelineRange(mediaPlayer.Info.GetDuration(), mediaPlayer.Control.GetSeekableTimes()); } return new TimeRange(); } private void SeekToFrame(int frame) { mediaPlayer.Control.SeekToFrame(frame); } private int GetCurrentFrame() { return mediaPlayer.Control.GetCurrentTimeFrames(); } private int GetPreFrame(int frame) { return mediaPlayer.Control.GetCurrentTimeFrames(); } private Vector3 rotation = Vector3.zero; private Vector3 lightRotation; private void CharacterControl() { var delta = 0.2f; var zdelta = 0.1f; //控制太阳 if (Input.GetKey(KeyCode.Z)) { //lightRotation.x -= delta; lightRotation.y += zdelta; Light.DORotate(lightRotation, 0); isPlay = false; } if (Input.GetKey(KeyCode.C)) { // lightRotation.x += delta; lightRotation.y -= zdelta; Light.DORotate(lightRotation, 0); isPlay = false; } //控制人物方向 if (Input.GetKey(KeyCode.Q)) { rotation.y -= delta; Player.DORotate(rotation, 0); Player.parent.DORotate(rotation, 0); isPlay = false; } if (Input.GetKey(KeyCode.E)) { rotation.y += delta; Player.DORotate(rotation, 0); Player.parent.DORotate(rotation, 0); isPlay = false; } //控制人物左右倾斜 if (Input.GetKey(KeyCode.J)) { rotation.z += zdelta; Player.DORotate(rotation, 0); Player.parent.DORotate(rotation, 0); isPlay = false; } if (Input.GetKey(KeyCode.K)) { rotation.z -= zdelta; Player.DORotate(rotation, 0); Player.parent.DORotate(rotation, 0); isPlay = false; } //空格键记录当前人物数据 if (Input.GetKeyDown(KeyCode.Space)) { PlayOrPause(); } //人物前后左右 if (Input.GetKey(KeyCode.S)) { setHeroState(HERO_DOWN); //下 } else if (Input.GetKey(KeyCode.W)) { setHeroState(HERO_UP); //上 } if (Input.GetKey(KeyCode.D)) { setHeroState(HERO_RIGHT); //右 } else if (Input.GetKey(KeyCode.A)) { setHeroState(HERO_LEFT); //左 } //控制视频播放进度 if (Input.GetKey(KeyCode.LeftArrow)) { var frame = GetCurrentFrame()-1; SeekToFrame(frame); } if (Input.GetKey(KeyCode.RightArrow)) { var frame = GetCurrentFrame() + 1; SeekToFrame(frame); } //控制人物上下 if (Input.GetKey(KeyCode.UpArrow)) { setHeroState(UP); } if (Input.GetKey(KeyCode.DownArrow)) { setHeroState(DOWN); } } private void PlayOrPause() { if (mediaPlayer.Control.IsPaused()) { isPlay = true; mediaPlayer.Play(); } else { isPlay = false; mediaPlayer.Pause(); } } private void DoRecord() { Save(); BuildList(); //回到上一个节点 if (pre != null) { mediaPlayer.Control.SeekToFrame(pre.KeyFrame); } isPlay = true; mediaPlayer.Play(); } private void Save() { var key = GetCurrentFrame(); //获取人物inpector面板的rotation值 Vector3 vect3 = Vector3.zero; Vector3 vect = Vector3.zero; MethodInfo mth = typeof(Transform).GetMethod("GetLocalEulerAngles", BindingFlags.Instance | BindingFlags.NonPublic); PropertyInfo pi = typeof(Transform).GetProperty("rotationOrder", BindingFlags.Instance | BindingFlags.NonPublic); object rotationOrder = null; object lightRotationOrder = null; if (pi != null) { rotationOrder = pi.GetValue(Player, null); lightRotationOrder= pi.GetValue(Light, null); } if (mth != null) { object retVector3 = mth.Invoke(Player, new object[] { rotationOrder }); vect3 = (Vector3)retVector3; object retVector = mth.Invoke(Light, new object[] { lightRotationOrder }); vect = (Vector3)retVector; } //保存记录 var s = $"{key}:{ Math.Round(vect3.y, 3)},{ Math.Round(vect3.z, 3)},{Math.Round(Player.position.x,3)},{Math.Round(Player.position.y,3)},{Math.Round(Player.position.z,3)},{Math.Round(vect.y,3)}"; if (list.ContainsKey(key)) { list[key] = s; } else { list.Add(key, s); } var coll = list.OrderBy(c => c.Key); StringBuilder sb = new StringBuilder(); foreach (var item in coll) { sb.AppendLine(item.Value); } File.WriteAllText(ConfigPath, sb.ToString()); } //人物状态 public const int HERO_UP = 0; public const int HERO_RIGHT = 1; public const int HERO_DOWN = 2; public const int HERO_LEFT = 3; public const int UP = 4; public const int DOWN = 5; //人物当前行走的方向状态 public int state = 0; //人物移动速度 public int moveSpeed = 2; void setHeroState(int newState) { isPlay = false; //根据当前人物方向与上一次备份的方向计算出模型旋转的角度 Vector3 transformValue = new Vector3(); //模型移动的位置数值 switch (newState) { case HERO_UP: transformValue = Vector3.forward * Time.deltaTime; break; case HERO_DOWN: transformValue = (-Vector3.forward) * Time.deltaTime; break; case HERO_LEFT: transformValue = Vector3.left * Time.deltaTime; break; case HERO_RIGHT: transformValue = (-Vector3.left) * Time.deltaTime; break; case UP: transformValue = (Vector3.up) * Time.deltaTime; break; case DOWN: transformValue = (Vector3.down) * Time.deltaTime; break; } ////移动人物 Player.Translate(transformValue * moveSpeed, Space.World); Player.parent.Translate(transformValue * moveSpeed, Space.World); state = newState; } public class CustomRange { public int KeyFrame { get; set; }//帧数 public int Start { get; set; }//起始帧 public int End { get; set; }//结束帧 public float PositionX { get; set; } public float PositionY { get; set; } public float PositionZ { get; set; } public float RotationY { get; set; } public float RotationZ { get; set; } public float LightY { get; set; } private const float defaultRotationY = 0; private const float defaultRotationZ = 0; private const float defaultPositionX = 0; private const float defaultPositionY = -1; private const float defaultPositionZ = 3; private const float defaultLightY = 0; public static CustomRange Read(string s) { // - 代表默认值 //KeyFrame:RotationY,RotationZ,PositionX,PositionY,PositionZ,LightY var result = s.Split(':'); var v = result[1].Split(','); CustomRange r = new CustomRange() { KeyFrame = Convert.ToInt32(result[0]), RotationY = v[0].Equals("-") ? defaultRotationY : (float)Convert.ToDouble(v[0]), RotationZ = v[1].Equals("-") ? defaultRotationZ : (float)Convert.ToDouble(v[1]), PositionX = v[2].Equals("-") ? defaultPositionX : (float)Convert.ToDouble(v[2]), PositionY = v[3].Equals("-") ? defaultPositionY : (float)Convert.ToDouble(v[3]), PositionZ = v[4].Equals("-") ? defaultPositionZ : (float)Convert.ToDouble(v[4]), LightY = v[5].Equals("-") ? defaultLightY : (float)Convert.ToDouble(v[5]), }; return r; } } }