Esempio n. 1
0
    public void CreatePositionList(List <CarController> cars)
    {
        DestroyAll();

        float height = cars.Count * positionsInfoPrefab.GetComponent <RectTransform>().rect.height;
        float width  = GetComponent <RectTransform>().rect.width;

        GetComponent <RectTransform>().sizeDelta = new Vector2(GetComponent <RectTransform>().rect.width, height);

        float bestTime          = 0;
        bool  setFinishedCanvas = false;

        for (int i = 0; i < cars.Count; i++)
        {
            for (int j = 0; j < cars.Count; j++)
            {
                if (cars[j].GetPosition() == (i + 1))
                {
                    if (i == 0)
                    {
                        bestTime = cars[j].GetFinishTime();
                    }

                    if (cars[j].humanPlayer != null)
                    {
                        setFinishedCanvas = true;
                        RacingCanvasController.racingCanvas.FinishedCanvas(cars[j]);
                    }

                    GameObject obj = Instantiate(positionsInfoPrefab, transform, true);


                    curObjs.Add(obj);
                    obj.SetActive(true);

                    PositionBar posBar = obj.GetComponent <PositionBar>();

                    posBar.positionText.text = (i + 1).ToString();

                    if (cars[j].humanPlayer != null)
                    {
                        if (cars[j].humanPlayer.name != "")
                        {
                            posBar.nameText.text = cars[j].humanPlayer.name;
                        }
                        else
                        {
                            posBar.nameText.text = "Player";
                        }
                    }
                    else
                    {
                        posBar.nameText.text = cars[j].aIPlayer.name;
                    }

                    int timeM  = (int)(cars[j].GetFinishTime() / 60);
                    int timeS  = (int)(cars[j].GetFinishTime() - timeM * 60);
                    int timeMS = (int)((cars[j].GetFinishTime() - timeM * 60 - timeS) * 100);

                    posBar.totalTimeText.text = timeM.ToString("D2") + ":" + timeS.ToString("D2") + ":" + timeMS.ToString("D2");

                    if (i > 0)
                    {
                        float diffTime = cars[j].GetFinishTime() - bestTime;

                        timeM  = (int)(diffTime / 60);
                        timeS  = (int)(diffTime - timeM * 60);
                        timeMS = (int)((diffTime - timeM * 60 - timeS) * 100);

                        if (timeM != 0)
                        {
                            posBar.diffText.text = "+ " + timeM.ToString() + ":" + timeS.ToString("D2") + ":" + timeMS.ToString("D2");
                        }
                        else if (timeM == 0 && timeS != 0)
                        {
                            posBar.diffText.text = "+ " + timeS.ToString() + ":" + timeMS.ToString("D2");
                        }
                        else if (timeM == 0 && timeS == 0 && timeMS != 0)
                        {
                            posBar.diffText.text = "+ " + timeS.ToString("D1") + ":" + timeMS.ToString("D2");
                        }

                        break;
                    }
                    else
                    {
                        posBar.diffText.text = "";
                    }
                }
            }
        }

        if (!setFinishedCanvas)
        {
            RacingCanvasController.racingCanvas.FinishedCanvas(null);
        }
    }
Esempio n. 2
0
        protected override GeneratorResult ProcessInternal(PreviewGeneratorSettings settings, GeneratorEntry entry)
        {
            entry.State = JobStates.Processing;

            List <string> tempFiles = new List <string>();

            int totalSteps = settings.OverlayScriptPositions ? 5 : 4;
            int stepsDone  = 0;

            try
            {
                _wrapper = new FfmpegWrapper(FfmpegExePath);

                List <string> sectionFileNames = new List <string>();

                if (settings.TimeFrames.Any(tf => tf.IsFactor))
                {
                    VideoInfo info = _wrapper.GetVideoInfo(settings.VideoFile);

                    if (!info.IsGoodEnough())
                    {
                        entry.State    = JobStates.Done;
                        entry.DoneType = JobDoneTypes.Failure;
                        entry.Update("Failed", 1);
                        return(GeneratorResult.Failed());
                    }

                    TimeSpan duration = info.Duration;

                    settings.TimeFrames.ForEach(tf => tf.CalculateStart(duration));
                }

                ClipExtractorArguments clipArguments = new ClipExtractorArguments
                {
                    InputFile = settings.VideoFile,
                    Width     = settings.Width,
                    Height    = settings.Height,
                    Framerate = settings.Framerate,
                    ClipLeft  = settings.ClipLeft,
                    DeLense   = settings.ClipLeft
                };

                VideoInfo clipInfo = null;

                for (int i = 0; i < settings.TimeFrames.Count; i++)
                {
                    string sectionFileName = Path.Combine(Path.GetTempPath(),
                                                          Path.GetFileName(settings.VideoFile) + $"-clip_{i}.mkv");
                    sectionFileNames.Add(sectionFileName);
                    tempFiles.Add(sectionFileName);

                    var timeFrame = settings.TimeFrames[i];

                    clipArguments.Duration      = timeFrame.Duration;
                    clipArguments.StartTimeSpan = timeFrame.StartTimeSpan;
                    clipArguments.OutputFile    = sectionFileName;

                    entry.Update($"Generating GIF ({stepsDone + 1}/{totalSteps}): Clipping Video Section {i + 1}/{settings.TimeFrames.Count}",
                                 (stepsDone / (double)totalSteps) + ((i / (double)settings.TimeFrames.Count)) / totalSteps);

                    if (!_wrapper.Execute(clipArguments))
                    {
                        return(GeneratorResult.Failed());
                    }

                    if (clipInfo == null)
                    {
                        clipInfo = _wrapper.GetVideoInfo(sectionFileName);
                    }

                    if (_canceled)
                    {
                        return(GeneratorResult.Failed());
                    }
                }

                stepsDone++;

                if (settings.OverlayScriptPositions)
                {
                    string script  = ViewModel.GetScriptFile(settings.VideoFile);
                    var    actions = ViewModel.LoadScriptActions(script, null)?.OfType <FunScriptAction>().ToList();

                    Size barSize = new Size(clipInfo.Resolution.Horizontal, 20);

                    if (actions != null && actions.Count > 0)
                    {
                        PositionBar bar = new PositionBar
                        {
                            Width  = barSize.Width,
                            Height = barSize.Height,
                            TotalDisplayedDuration = TimeSpan.FromSeconds(5),
                            Background             = Brushes.Black,
                            Positions = new PositionCollection(actions.Select(a => new TimedPosition()
                            {
                                Position  = a.Position,
                                TimeStamp = a.TimeStamp
                            })),
                            DrawCircles = false,
                            DrawLines   = false,
                        };

                        for (int i = 0; i < settings.TimeFrames.Count; i++)
                        {
                            TimeSpan start = settings.TimeFrames[i].StartTimeSpan;
                            TimeSpan max   = start + settings.TimeFrames[i].Duration;

                            TimeSpan progress = start;

                            string tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
                            Directory.CreateDirectory(tempDir);

                            string overlayFileName = Path.Combine(Path.GetTempPath(),
                                                                  Path.GetFileName(settings.VideoFile) + $"-overlay_{i}.mkv");

                            tempFiles.Add(overlayFileName);

                            int frame = 0;

                            entry.Update($"Generating GIF ({stepsDone + 1}/{totalSteps}): Overlaying Positions {i + 1}/{settings.TimeFrames.Count}",
                                         (stepsDone / (double)totalSteps) + ((i / (double)settings.TimeFrames.Count)) / totalSteps);

                            double expectedFrames = 1 + (settings.TimeFrames[i].Duration.TotalSeconds * clipInfo.FrameRate);

                            while (progress <= max)
                            {
                                progress = start + TimeSpan.FromSeconds(frame / clipInfo.FrameRate);

                                bar.Progress = progress;

                                var bitmap = RenderToBitmap(bar, barSize);

                                PngBitmapEncoder encoder = new PngBitmapEncoder();

                                encoder.Frames.Add(BitmapFrame.Create(bitmap));

                                using (FileStream f = new FileStream(Path.Combine(tempDir, $"frame{frame:0000}.png"),
                                                                     FileMode.CreateNew))
                                    encoder.Save(f);

                                frame++;
                            }

                            FrameMergeArguments frameMergeArguments = new FrameMergeArguments
                            {
                                Framerate  = clipInfo.FrameRate,
                                InputFile  = Path.Combine(tempDir, "frame%04d.png"),
                                OutputFile = overlayFileName
                            };

                            if (!_wrapper.Execute(frameMergeArguments))
                            {
                                return(GeneratorResult.Failed());
                            }

                            var clipInfo2 = _wrapper.GetVideoInfo(overlayFileName);

                            Directory.Delete(tempDir, true);

                            string mergeFileName = Path.Combine(Path.GetTempPath(),
                                                                Path.GetFileName(settings.VideoFile) + $"-merge_{i}.mkv");

                            tempFiles.Add(mergeFileName);

                            VideoOverlayArguments overlayArguments = new VideoOverlayArguments
                            {
                                InputFile  = sectionFileNames[i],
                                Overlay    = overlayFileName,
                                OutputFile = mergeFileName,
                                PosX       = 0,
                                PosY       = clipInfo.Resolution.Vertical - 20
                            };

                            if (!_wrapper.Execute(overlayArguments))
                            {
                                return(GeneratorResult.Failed());
                            }

                            sectionFileNames[i] = mergeFileName;
                        }
                    }

                    stepsDone++;
                }

                entry.Update($"Generating GIF ({stepsDone + 1}/{totalSteps}): Merging Clips", stepsDone / (double)totalSteps);

                string clipFileName;

                if (sectionFileNames.Count == 1)
                {
                    clipFileName = sectionFileNames[0];
                }
                else
                {
                    ClipMergeArguments mergeArguments = new ClipMergeArguments
                    {
                        InputFile  = settings.VideoFile,
                        ClipFiles  = sectionFileNames.ToArray(),
                        OutputFile = Path.Combine(Path.GetTempPath(), Path.GetFileName(settings.VideoFile) + $"-clip.mkv")
                    };

                    clipFileName = mergeArguments.OutputFile;
                    tempFiles.Add(clipFileName);

                    if (!_wrapper.Execute(mergeArguments))
                    {
                        return(GeneratorResult.Failed());
                    }

                    if (_canceled)
                    {
                        return(GeneratorResult.Failed());
                    }
                }

                stepsDone++;

                entry.Update($"Generating GIF ({stepsDone + 1}/{totalSteps}): Extracting Palette", stepsDone / (double)totalSteps);

                string paletteFile = clipFileName + "-palette.png";

                PaletteExtractorArguments paletteArguments = new PaletteExtractorArguments
                {
                    InputFile  = clipFileName,
                    OutputFile = paletteFile
                };

                tempFiles.Add(paletteFile);

                if (!_wrapper.Execute(paletteArguments))
                {
                    return(GeneratorResult.Failed());
                }

                if (_canceled)
                {
                    return(GeneratorResult.Failed());
                }

                stepsDone++;

                entry.Update($"Generating GIF ({stepsDone + 1}/{totalSteps}): Creating GIF", stepsDone / (double)totalSteps);

                string gifFileName = settings.OutputFile;

                GifCreatorArguments gifArguments = new GifCreatorArguments();
                gifArguments.InputFile   = clipFileName;
                gifArguments.PaletteFile = paletteFile;
                gifArguments.OutputFile  = gifFileName;
                gifArguments.Framerate   = settings.Framerate;

                if (!_wrapper.Execute(gifArguments))
                {
                    return(GeneratorResult.Failed());
                }

                if (_canceled)
                {
                    return(GeneratorResult.Failed());
                }

                stepsDone++;

                entry.Update("Done", 1.0);
                bool success = File.Exists(gifFileName);

                if (success)
                {
                    entry.DoneType = JobDoneTypes.Success;
                }
                else
                {
                    entry.DoneType = JobDoneTypes.Failure;
                }

                OnDone(new Tuple <bool, string>(success, gifFileName));

                if (success)
                {
                    return(GeneratorResult.Succeeded(gifFileName));
                }

                return(GeneratorResult.Failed());
            }
            catch (Exception e)
            {
                entry.DoneType = JobDoneTypes.Failure;
                return(GeneratorResult.Failed());
            }
            finally
            {
                entry.State = JobStates.Done;

                if (_canceled)
                {
                    entry.DoneType = JobDoneTypes.Cancelled;
                }

                foreach (string tempFile in tempFiles)
                {
                    if (File.Exists(tempFile))
                    {
                        File.Delete(tempFile);
                    }
                }
            }
        }