internal void Create(ref TrackElement Element, Dictionary <int, LightDefinition[]> LightDefinitions) { if (Plugin.CurrentRoute.DynamicLighting) { if (currentDynamicLightSet == -1) { // Setting ambient / directional not supported in conjunction with dynamic lighting return; } if (!LightDefinitions.ContainsKey(previousDynamicLightSet) || !LightDefinitions.ContainsKey(currentDynamicLightSet)) { // Light set not available return; } int m = Element.Events.Length; Array.Resize(ref Element.Events, m + 1); Element.Events[m] = new LightingChangeEvent(Plugin.CurrentRoute, LightDefinitions[previousDynamicLightSet], LightDefinitions[currentDynamicLightSet]); } else { int m = Element.Events.Length; Array.Resize(ref Element.Events, m + 1); Element.Events[m] = new LightingChangeEvent(Plugin.CurrentRoute, previousLightDefinition, currentLightDefinition); } }
/// <summary> /// Serializes a track element and writes it to the stream. /// </summary> /// <param name="element">The track element to serialize</param> private void WriteElement(TrackElement element) { writer.Write(element.mystery); writer.Write(GetHeight(element.Y)); writer.Write(element.id); writer.Write((uint)element.rotation); }
/// <summary> /// Reads a track from the provided stream. /// </summary> /// <param name="stream">The stream to read the track from</param> /// <returns>The track as an object</returns> /// <exception cref="InvalidDataException">Thrown when the track file is formatted incorrectly or corrupted.</exception> public Track ReadTrack(Stream stream) { this.stream = stream; var track = new Track(); using (reader = new BinaryReader(this.stream)) { var realFilesize = (int)stream.Length; if (realFilesize < 20) { throw new InvalidDataException("Incorrect filesize, corrupted track!"); } var legoHeader = ReadString(12); var trkVersion = reader.ReadUInt32(); var claimedFilesize = reader.ReadUInt32(); if (claimedFilesize != 65576) { throw new InvalidDataException("TRK file reports incorrect filesize!"); } if (claimedFilesize != realFilesize) { throw new InvalidDataException("Incorrect filesize, corrupted track!"); } track.size = (Track.TrackSize)reader.ReadUInt32(); track.theme = (Track.TrackTheme)reader.ReadUInt32(); track.time = (Track.TrackTime)reader.ReadUInt32(); var iters = 8 * ((int)track.size + 1); var skip = (56 - (int)track.size * 8) * 16; for (var z = 0; z < iters; z++) { for (var x = 0; x < iters; x++) { var element = new TrackElement(); element.mystery = reader.ReadBytes(4); element.pos = new GridPosition(x, ReadHeight(), z); element.SetId(reader.ReadUInt32()); element.rotation = (TrackElement.TrackRotation)reader.ReadUInt32(); track.Add(element); } stream.Seek(skip, SeekOrigin.Current); } stream.Seek(65572, SeekOrigin.Begin); track.playable = reader.ReadUInt32() == 1; } return(track); }
internal void CreateEvent(double StartingDistance, double EndingDistance, ref TrackElement Element) { if (TrackPosition >= StartingDistance & TrackPosition < EndingDistance) { int m = Element.Events.Length; Array.Resize(ref Element.Events, m + 1); Element.Events[m] = new RequestStopEvent(Plugin.CurrentRoute, StationIndex, MaxNumberOfCars, FullSpeed, OnTime, Early, Late); } }
public Track(TrackElement trackElement, bool isLast, bool isSkipAllowed) { Performer = trackElement.Performer; Name = trackElement.Name; Uri = trackElement.Url; Duration = 0; IsLast = isLast; Id = trackElement.Id; IsSkipAllowed = isSkipAllowed; }
private void CreateTrackGrid() { var trackCanvas = new TrackElement(new AudioTrack() { Name = "Track " + this.CenterCanvas.Children.Count }, this.trackHeight); trackCanvas.Width = this.CenterCanvas.ActualWidth; Canvas.SetLeft(trackCanvas, 0); Canvas.SetTop(trackCanvas, this.CenterCanvas.Children.Count * this.trackHeight); this.CenterCanvas.Children.Add(trackCanvas); }
internal void CreateEvent(ref TrackElement Element, double StartingDistance) { if (Type != -1) { int t = SectionIndex; if (t >= 0 & t < Plugin.CurrentRoute.Sections.Length) { int m = Element.Events.Length; Array.Resize(ref Element.Events, m + 1); double dt = TrackPosition - StartingDistance; Element.Events[m] = new TransponderEvent(Plugin.CurrentRoute, dt, Type, Data, t, ClipToFirstRedSection); Type = -1; } } }
internal void CreateEvent(double StartingDistance, double EndingDistance, ref TrackElement Element) { if (StartingPosition >= StartingDistance & StartingPosition < EndingDistance) { int m = Element.Events.Length; Array.Resize(ref Element.Events, m + 1); double d = StartingPosition - StartingDistance; if (Message != null) { Element.Events[m] = new MarkerStartEvent(Plugin.CurrentHost, d, Message); } } if (EndingPosition >= StartingDistance & EndingPosition < EndingDistance) { int m = Element.Events.Length; Array.Resize(ref Element.Events, m + 1); double d = EndingPosition - StartingDistance; if (Message != null) { Element.Events[m] = new MarkerEndEvent(Plugin.CurrentHost, d, Message); } } }
public void SentPrimaryTOWInfoToMediatorTest() { #region Data Setup DeliverableGroup testDeliverableGroup = new DeliverableGroup() { Code = "VID" }; Model.TypeOfWork typeOfWork1 = new Model.TypeOfWork() { Name = "Type Of Work A", Id = 1100 }; Model.TypeOfWork typeOfWork2 = new Model.TypeOfWork() { Name = "Type Of Work B", Id = 1101 }; Channel testChannel = new Channel() { Code = "DC" }; //Radio Disney Guid DeliverableBudgetUniqueID1 = Guid.NewGuid(); Guid DeliverableBudgetUniqueID2 = Guid.NewGuid(); WBSElement wbsElement1 = new WBSElement() { Id = 1, FullWBSNumber = "123456.011.001", TypeOfWorkId = 1100 }; WBSElement wbsElement2 = new WBSElement() { Id = 2, FullWBSNumber = "123456.011.002", TypeOfWorkId = 1101 }; wbsElement1.TypeOfWork = typeOfWork1; wbsElement2.TypeOfWork = typeOfWork2; DeliverableDate FPADate = new DeliverableDate() { Id = 1, DeliverableDateTypeId = 1, DateValue = new DateTime() }; DeliverableDate DueDate = new DeliverableDate() { Id = 2, DeliverableDateTypeId = 9, DateValue = new DateTime() }; List <DeliverableDate> deliverableDateList = new List <DeliverableDate>(); deliverableDateList.Add(FPADate); deliverableDateList.Add(DueDate); ActivityStatus activityStatus = new ActivityStatus() { Id = 39, IsActiveFlag = true, Code = "INPCC", }; TrackElement trk1 = new TrackElement() { Id = 1, ActivityStatusId = 39, HouseNumber = "MRM1403030766624", Name = "Textless Generic", ActualLength = 0.10m, IsActiveFlag = true }; TrackElement trk2 = new TrackElement() { Id = 2, ActivityStatusId = 39, HouseNumber = "MRM1403030766625", Name = "International Textless", ActualLength = 0.10m, IsActiveFlag = true }; DeliverableDate deliverableDate1 = new DeliverableDate() { Id = 1, DeliverableId = 140000 }; DeliverableDate deliverableDate2 = new DeliverableDate() { Id = 2, DeliverableId = 140000 }; DeliverableDateType deliverableDateType1 = new DeliverableDateType() { Id = 1, Code = "FPA" }; DeliverableDateType deliverableDateType2 = new DeliverableDateType() { Id = 2, Code = "DEL" }; FPADate.DeliverableDateType = deliverableDateType1; DueDate.DeliverableDateType = deliverableDateType2; Model.Deliverable testDeliverable = new Model.Deliverable() { Id = 140000, DeliverableTypeId = 94, //Affiliate Marketing ProducingDepartmentId = 84, //MRM Team Name = "Disney Channel Video Deliverable", DeliverableGroupId = 2, //Video DeliverableGroup = testDeliverableGroup, Channel = testChannel, DeliverableStatusId = 3, PlannedLengthId = 10, ClipDeliverMasterVendorId = 418 }; testDeliverable.PrimaryDeliverableBudgetUniqueID = DeliverableBudgetUniqueID1; testDeliverable.DeliverableDate = deliverableDateList; DeliverableStatus deliverableStatus = new DeliverableStatus() { Id = 2, Code = "INPCC", Name = "In Process" }; testDeliverable.DeliverableStatus = deliverableStatus; DeliverableBudget deliverableBud1 = new DeliverableBudget() { Id = 1, DeliverableId = 140000, MasterVendorId = 12 }; deliverableBud1.DeliverableBudgetUniqueID = DeliverableBudgetUniqueID1; deliverableBud1.WBSElement = wbsElement1; DeliverableBudget deliverableBud2 = new DeliverableBudget() { Id = 2, DeliverableId = 140000, MasterVendorId = 25 }; deliverableBud2.DeliverableBudgetUniqueID = DeliverableBudgetUniqueID2; deliverableBud2.WBSElement = wbsElement2; List <DeliverableBudget> deliverableBudgetList = new List <DeliverableBudget>(); deliverableBudgetList.Add(deliverableBud1); deliverableBudgetList.Add(deliverableBud2); testDeliverable.DeliverableBudget = deliverableBudgetList; ProductionMethodType productionMethodType1 = new ProductionMethodType() { Id = 1, Code = "PH", Name = "Post House" }; ProductionMethodType productionMethodType2 = new ProductionMethodType() { Id = 2, Code = "CS", Name = "Creative Services" }; List <ProductionMethodType> productionMethodTypeList = new List <ProductionMethodType>(); productionMethodTypeList.Add(productionMethodType1); productionMethodTypeList.Add(productionMethodType2); List <int> pmoList = new List <int>(); pmoList.Add(productionMethodTypeList.ElementAt(0).Id); pmoList.Add(productionMethodTypeList.ElementAt(1).Id); List <DeliverableDate> deldates = new List <DeliverableDate>(); deldates.Add(FPADate); deldates.Add(DueDate); testDeliverable.DeliverableDate = deldates; List <TrackElement> lstTrk = new List <TrackElement>(); lstTrk.Add(trk1); lstTrk.Add(trk2); testDeliverable.TrackElement = lstTrk; DeliverableBudgetViewModel deliverableBudget1 = new DeliverableBudgetViewModel() { DeliverableId = 140000, WBSNumber = "123456.123.001", MasterVendorId = 10, isPrimary = true, TowId = 1, BudgetTypeId = 3, FiscalYearId = 2016, BudgetGroupId = 55, DeliverableBudgetId = 1, UserId = 852, DeliverableBudgetUniqueID = DeliverableBudgetUniqueID1 }; deliverableBudget1.ProductionMethodTypeIds = pmoList; DeliverableBudgetViewModel deliverableBudget2 = new DeliverableBudgetViewModel() { DeliverableId = 140000, MasterVendorId = 15, isPrimary = false, TowId = 2, BudgetTypeId = 4, FiscalYearId = 2016, BudgetGroupId = 77, DeliverableBudgetId = 2, DeliverableBudgetUniqueID = DeliverableBudgetUniqueID2 }; deliverableBudget2.ProductionMethodTypeIds = pmoList; List <DeliverableBudgetViewModel> deliverableBudgetViewModelList = new List <DeliverableBudgetViewModel>(); deliverableBudgetViewModelList.Add(deliverableBudget1); deliverableBudgetViewModelList.Add(deliverableBudget2); DeliverableMultiWBSModel deliverableMultiWBSModel = new DeliverableMultiWBSModel() { DeliverableId = 140000, PrimaryDeliverableBudgetUniqueID = DeliverableBudgetUniqueID1, IsLaunchFlag = false }; deliverableMultiWBSModel.Budgets = deliverableBudgetList; DeliverableMultiWBSViewModel deliverableMultiWBSViewModel = new DeliverableMultiWBSViewModel() { DeliverableId = 140000, InitialBudgetAmount = 99, IsLaunchFlag = true, PrimaryDeliverableBudgetUniqueID = DeliverableBudgetUniqueID1, ClipDeliverMasterVendorId = 100, ProducingDepartmentId = 108, MarketingGroupChannelId = 1, Budgets = deliverableBudgetViewModelList, }; deliverableMultiWBSViewModel.Budgets = deliverableBudgetViewModelList; Deliverable_WBSElement deliverable_WBSElement = new Deliverable_WBSElement() { DeliverableId = 14000, Id = 1, }; deliverable_WBSElement.Deliverable = testDeliverable; MasterVendor masterVendor = new MasterVendor() { Id = 1, SAPVendorId = 25, MediatorVendorId = "795" }; PromoPlacementBody promoPlacementBody = new PromoPlacementBody(); PromoPlacementBody promoPlacementBodyResult = new PromoPlacementBody(); #endregion #region Mapper Mapper.CreateMap <Model.Deliverable, PromoPlacementBody>() .ForMember(i => i.ChannelCode, m => m.MapFrom(d => d.Channel.Code)) .ForMember(i => i.DeliverableId, m => m.MapFrom(d => d.Id)) .ForMember(i => i.DeliverableName, m => m.MapFrom(d => d.Name)) .ForMember(i => i.DeliverableStatusCode, m => m.MapFrom(d => d.DeliverableStatus.Code)) .ForMember(i => i.DeliverableTargetCode, m => m.MapFrom(d => d.Channel1.Code)) .ForMember(i => i.DeliverableTypeCode, m => m.MapFrom(d => d.DeliverableType.Code)) .ForMember(i => i.IsOffAir, m => m.MapFrom(d => d.IsOffChannelFlag)) .ForMember(i => i.FinalDueDate, m => m.MapFrom( d => d.DeliverableDate.FirstOrDefault( i => i.DeliverableDateType.Code == Core.Constants.DeliverableDateType.Final_Due) .DateValue)) .ForMember(i => i.FirstPromoAirDate, m => m.MapFrom( d => d.DeliverableDate.FirstOrDefault( i => i.DeliverableDateType.Code == Core.Constants.DeliverableDateType.FirstPromotionalAirDate).DateValue)) .ForMember(i => i.IsReissue, m => m.MapFrom(d => d.IsReIssueFlag)) //Updated for MRM-213 .ForMember(i => i.TOWId, m => m.MapFrom(d => d.DeliverableBudget.Where(x => x.DeliverableBudgetUniqueID == d.PrimaryDeliverableBudgetUniqueID).FirstOrDefault().WBSElement.TypeOfWorkId.Value)) .ForMember(i => i.TOWName, m => m.MapFrom(d => d.DeliverableBudget.Where(x => x.DeliverableBudgetUniqueID == d.PrimaryDeliverableBudgetUniqueID).FirstOrDefault().WBSElement.TypeOfWork.Name)) .ForMember(i => i.WBSNumber, m => m.MapFrom(d => FormatWBS(d.DeliverableBudget.Where(x => x.DeliverableBudgetUniqueID == d.PrimaryDeliverableBudgetUniqueID).FirstOrDefault()))) .ForMember(i => i.WriterProducer, m => m.MapFrom(d => FormatOwnerName(Core.Constants.UserTitle.WriterProducer, d) == string.Empty ? FormatOwnerName(Core.Constants.UserTitle.ProductionManager, d) : FormatOwnerName(Core.Constants.UserTitle.WriterProducer, d))) .ForMember(i => i.WriterProducerId, m => m.MapFrom(d => FormatNetworkLogin(Core.Constants.UserTitle.WriterProducer, d) == string.Empty ? FormatOwnerName(Core.Constants.UserTitle.ProductionManager, d) : FormatNetworkLogin(Core.Constants.UserTitle.WriterProducer, d))); #endregion #region Mocking mockDeliverableServiceV2.Setup(x => x.GetMasterVendorById(It.IsAny <int>())) .Returns(masterVendor); // Check for MediatorVendorId for SAP Vendor ID -- logic in GetVendorSAP() in IntergrationManager.cs mockIntegrationService.Setup(x => x.GetCommentsForDeliverable(It.IsAny <int>())) .Returns(new List <Comment>()); mockIntegrationService.Setup(x => x.GetTargetPlatforms(It.IsAny <List <int> >())) .Returns(new List <TargetPlatform>()); #endregion #region Service promoPlacementBody = Mapper.Map <Model.Deliverable, PromoPlacementBody>(testDeliverable); var integrationMock = new IntergrationManagerMock(deliverableV2Service: mockDeliverableServiceV2.Object, intergrationService: mockIntegrationService.Object); promoPlacementBodyResult = integrationMock.GetPromoPlacementForAssetManagement(testDeliverable, "SWNA\\TestLogin"); #endregion #region Assert Assert.IsFalse(promoPlacementBodyResult == null); Assert.IsTrue(promoPlacementBodyResult.DeliverableStatusCode == "INPCC"); Assert.IsTrue(promoPlacementBodyResult.VendorNumber == masterVendor.MediatorVendorId); Assert.IsTrue(promoPlacementBodyResult.TOWName == typeOfWork1.Name); Assert.IsTrue(promoPlacementBodyResult.WBSNumber == wbsElement1.FullWBSNumber); #endregion }
void ChangeToNextSpline() { TrackElement currentCurve = currentSpline.curve; if (currentSpline.curve.GetType() == typeof(Curve)) {// If we are in a Curve int currentSplineIndex = currentCurve.splines.IndexOf(currentSpline); if (!reverse) { // If there are more splines in the current curve, change to next if (currentSplineIndex + 1 <= currentCurve.splines.Count - 1) { currentSpline = currentCurve.splines[currentSplineIndex + 1]; t = t - 1; return; } else { // Jump to next TrackElement if (((Curve)currentCurve).nextCurve.GetType() == typeof(Curve)) { // Jump from curve to curve Curve nextCurve = (Curve)((Curve)currentCurve).nextCurve; if (nextCurve.nextCurve == currentCurve) {// --->/<--- currentSpline = nextCurve.splines[nextCurve.splines.Count - 1]; reverse = true; // Update t t = 1 - (t - 1); } else if (nextCurve.previousCurve == currentCurve) {// --->/---> currentSpline = nextCurve.splines[0]; reverse = false; // Update t t = t - 1; } } if (((Curve)currentCurve).nextCurve.GetType() == typeof(Bifurcation)) {// Jump from curve to bifurcation. Bifurcation nextBifurcation = (Bifurcation)((Curve)currentCurve).nextCurve; if (nextBifurcation.nextCurveRight == currentCurve) {// --->/---> (From Right path to Start) currentSpline = nextBifurcation.splines[0]; reverse = true; // Update t t = 1 - (t - 1); } else if (nextBifurcation.nextCurveLeft == currentCurve) {// --->/---> (From Left path to Start) currentSpline = nextBifurcation.splines[1]; reverse = true; // Update t t = 1 - (t - 1); } // Here we are sure that we are entering the bifurcation from the start node. else if (nextBifurcation.splines[0].isPath) {// --->/---> (From Start to Right path) currentSpline = nextBifurcation.splines[0]; reverse = false; // Update t t = t - 1; } else if (nextBifurcation.splines[1].isPath) {// --->\---> (From Start to Left path) currentSpline = nextBifurcation.splines[1]; reverse = false; // Update t t = t - 1; } } } } else // reverse mode { // If there are more splines in the current curve, change to previous spline if (currentSplineIndex - 1 >= 0) { currentSpline = currentCurve.splines[currentSplineIndex - 1]; t = 1 + t; return; } else { // Jump to next TrackElement if (((Curve)currentCurve).previousCurve.GetType() == typeof(Curve)) { // Jump to curve Curve previousCurve = (Curve)((Curve)currentCurve).previousCurve; if (previousCurve.nextCurve == currentCurve) {// <---/<--- currentSpline = previousCurve.splines[((Curve)currentCurve).previousCurve.splines.Count - 1]; reverse = true; // Update t t = t + 1; } else if (previousCurve.previousCurve == currentCurve) {// <---/---> currentSpline = previousCurve.splines[0]; reverse = false; // Update t t = 1 - (t + 1); } } if (((Curve)currentCurve).previousCurve.GetType() == typeof(Bifurcation)) {// Jump from curve to bifurcation. Bifurcation nextBifurcation = (Bifurcation)(((Curve)currentCurve).previousCurve); if (nextBifurcation.nextCurveRight == currentCurve) {// --->/---> (From Right path to Start) currentSpline = nextBifurcation.splines[0]; reverse = true; // Update t t = 1 + t; } else if (nextBifurcation.nextCurveLeft == currentCurve) {// --->\---> (From Left path to Start) currentSpline = nextBifurcation.splines[1]; reverse = true; // Update t t = 1 + t; } else if (nextBifurcation.previousCurve == currentCurve) { // --->\---> (From Start to..) if (nextBifurcation.splines[0].isPath) { // --->/---> (From Start to Right path) currentSpline = nextBifurcation.splines[0]; reverse = false; // Update t t = 1 - (1 - t); } else if (nextBifurcation.splines[1].isPath) {// --->\---> (From Start to Left path) currentSpline = nextBifurcation.splines[1]; reverse = false; // Update t t = 1 - (1 - t); } } } } } } else if (currentSpline.curve.GetType() == typeof(Bifurcation)) {// If we are in a Bifurcation Bifurcation bifurcation = (Bifurcation)currentSpline.curve; if (!reverse) { // Start to Right if (currentSpline == bifurcation.splines[0] && bifurcation.nextCurveRight.previousCurve == bifurcation) { // Start to Straight Right if (bifurcation.nextCurveRight.GetType() == typeof(Bifurcation)) { // bifurcation to bifurcation Bifurcation nextBifurcation = (Bifurcation)(bifurcation.nextCurveRight); if (nextBifurcation.splines[0].isPath) { currentSpline = nextBifurcation.splines[0]; } else if (nextBifurcation.splines[1].isPath) { currentSpline = nextBifurcation.splines[1]; } reverse = false; // Update t t = t - 1; } else {// bifurcation to Straight curve currentSpline = bifurcation.nextCurveRight.splines[0]; reverse = false; // Update t t = t - 1; } } else if (currentSpline == bifurcation.splines[0]) {// Start to Reverse Curve currentSpline = bifurcation.nextCurveRight.splines[bifurcation.nextCurveRight.splines.Count - 1]; reverse = true; // Update t t = 1 - (1 - t); } // Start to Left if (currentSpline == bifurcation.splines[1] && bifurcation.nextCurveLeft.previousCurve == bifurcation) { // Start to Straight Left if (bifurcation.nextCurveLeft.GetType() == typeof(Bifurcation)) { // bifurcation to bifurcation Bifurcation nextBifurcation = (Bifurcation)(bifurcation.nextCurveLeft); if (nextBifurcation.splines[0].isPath) { currentSpline = nextBifurcation.splines[0]; } else if (nextBifurcation.splines[1].isPath) { currentSpline = nextBifurcation.splines[1]; } reverse = false; // Update t t = t - 1; } else {// bifurcation to Straight curve currentSpline = bifurcation.nextCurveLeft.splines[0]; reverse = false; // Update t t = t - 1; } } else if (currentSpline == bifurcation.splines[1]) {// Start to Reverse Curve currentSpline = bifurcation.nextCurveLeft.splines[bifurcation.nextCurveLeft.splines.Count - 1]; reverse = true; // Update t t = 1 - (1 - t); } } else { // Reverse mode if (bifurcation.previousCurve.GetType() == typeof(Bifurcation)) { // back to another bifurcation Bifurcation previousBif = (Bifurcation)bifurcation.previousCurve; if (previousBif.nextCurveRight == bifurcation) { currentSpline = previousBif.splines[0]; } if (previousBif.nextCurveLeft == bifurcation) { currentSpline = previousBif.splines[1]; } reverse = true; t = t + 1; } else {// back to a Curve currentSpline = bifurcation.previousCurve.splines[bifurcation.previousCurve.splines.Count - 1]; reverse = true; t = t + 1; } } } return; }
internal void CreateEvent(double StartingDistance, ref double CurrentSpeedLimit, ref TrackElement Element) { int m = Element.Events.Length; Array.Resize(ref Element.Events, m + 1); double d = TrackPosition - StartingDistance; Element.Events[m] = new LimitChangeEvent(d, CurrentSpeedLimit, Speed); CurrentSpeedLimit = Speed; }
static void ChangeTheme(TrackElement element) { element.theme = theme; }
/// <summary>Smooths all curves / turns</summary> public void SmoothTurns(int subdivisions) //, HostInterface currentHost) { if (subdivisions < 2) { throw new InvalidOperationException(); } // subdivide track int length = Elements.Length; int newLength = (length - 1) * subdivisions + 1; float[] midpointsTrackPositions = new float[newLength]; Vector3[] midpointsWorldPositions = new Vector3[newLength]; Vector3[] midpointsWorldDirections = new Vector3[newLength]; Vector3[] midpointsWorldUps = new Vector3[newLength]; Vector3[] midpointsWorldSides = new Vector3[newLength]; float[] midpointsCant = new float[newLength]; TrackFollower follower = new TrackFollower(/*currentHost*/); for (int i = 0; i < newLength; i++) { int m = i % subdivisions; if (m != 0) { int q = i / subdivisions; float r = (float)m / (float)subdivisions; float p = (1.0f - r) * Elements[q].StartingTrackPosition + r * Elements[q + 1].StartingTrackPosition; follower.UpdateAbsolute(-1.0f, true, false); follower.UpdateAbsolute((float)p, true, false); midpointsTrackPositions[i] = p; midpointsWorldPositions[i] = follower.WorldPosition; midpointsWorldDirections[i] = follower.WorldDirection; midpointsWorldUps[i] = follower.WorldUp; midpointsWorldSides[i] = follower.WorldSide; midpointsCant[i] = follower.CurveCant; } } Array.Resize(ref Elements, newLength); for (int i = length - 1; i >= 1; i--) { Elements[subdivisions * i] = Elements[i]; } for (int i = 0; i < Elements.Length; i++) { int m = i % subdivisions; if (m != 0) { int q = i / subdivisions; int j = q * subdivisions; Elements[i] = Elements[j]; // Elements[i].Events = new GeneralEvent[] { }; Elements[i].StartingTrackPosition = midpointsTrackPositions[i]; Elements[i].WorldPosition = midpointsWorldPositions[i]; Elements[i].WorldDirection = midpointsWorldDirections[i]; Elements[i].WorldUp = midpointsWorldUps[i]; Elements[i].WorldSide = midpointsWorldSides[i]; Elements[i].CurveCant = midpointsCant[i]; Elements[i].CurveCantTangent = 0.0f; } } // find turns bool[] isTurn = new bool[Elements.Length]; { for (int i = 1; i < Elements.Length - 1; i++) { int m = i % subdivisions; if (m == 0) { double p = 0.00000001 * Elements[i - 1].StartingTrackPosition + 0.99999999 * Elements[i].StartingTrackPosition; follower.UpdateAbsolute((float)p, true, false); Vector3 d1 = Elements[i].WorldDirection; Vector3 d2 = follower.WorldDirection; Vector3 d = d1 - d2; double t = d.x * d.x + d.z * d.z; const double e = 0.0001; if (t > e) { isTurn[i] = true; } } } } // replace turns by curves for (int i = 0; i < Elements.Length; i++) { if (isTurn[i]) { // estimate radius Vector3 AP = Elements[i - 1].WorldPosition; Vector3 BP = Elements[i + 1].WorldPosition; Vector3 S = Elements[i - 1].WorldSide - Elements[i + 1].WorldSide; float rx; if (S.x * S.x > 0.000001) { rx = (BP.x - AP.x) / S.x; } else { rx = 0.0f; } float rz; if (S.z * S.z > 0.000001) { rz = (BP.z - AP.z) / S.z; } else { rz = 0.0f; } if (rx != 0.0 | rz != 0.0) { float r; if (rx != 0.0 & rz != 0.0) { if (Godot.Mathf.Sign(rx) == Godot.Mathf.Sign(rz)) { float f = rx / rz; if (f > -1.1 & f <-0.9 | f> 0.9 & f < 1.1) { r = Godot.Mathf.Sqrt(Godot.Mathf.Abs(rx * rz)) * Godot.Mathf.Sign(rx); } else { r = 0.0f; } } else { r = 0.0f; } } else if (rx != 0.0) { r = rx; } else { r = rz; } if (r * r > 1.0) { // apply radius Elements[i - 1].CurveRadius = r; double p = 0.00000001 * Elements[i - 1].StartingTrackPosition + 0.99999999 * Elements[i].StartingTrackPosition; follower.UpdateAbsolute((float)p - 1.0f, true, false); follower.UpdateAbsolute((float)p, true, false); Elements[i].CurveRadius = r; Elements[i].WorldPosition = follower.WorldPosition; Elements[i].WorldDirection = follower.WorldDirection; Elements[i].WorldUp = follower.WorldUp; Elements[i].WorldSide = follower.WorldSide; // iterate to shorten track element length p = 0.00000001 * Elements[i].StartingTrackPosition + 0.99999999 * Elements[i + 1].StartingTrackPosition; follower.UpdateAbsolute((float)p - 1.0f, true, false); follower.UpdateAbsolute((float)p, true, false); Vector3 d = Elements[i + 1].WorldPosition - follower.WorldPosition; float bestT = (float)Calc.NormSquared(d); int bestJ = 0; int n = 1000; float a = 1.0f / (float)n * (Elements[i + 1].StartingTrackPosition - Elements[i].StartingTrackPosition); for (int j = 1; j < n - 1; j++) { follower.UpdateAbsolute((float)(Elements[i + 1].StartingTrackPosition - (double)j * a), true, false); d = Elements[i + 1].WorldPosition - follower.WorldPosition; float t = (float)Calc.NormSquared(d); if (t < bestT) { bestT = t; bestJ = j; } else { break; } } float s = (float)bestJ * a; for (int j = i + 1; j < Elements.Length; j++) { Elements[j].StartingTrackPosition -= s; } // introduce turn to compensate for curve p = 0.00000001 * Elements[i].StartingTrackPosition + 0.99999999 * Elements[i + 1].StartingTrackPosition; follower.UpdateAbsolute((float)p - 1.0f, true, false); follower.UpdateAbsolute((float)p, true, false); Vector3 AB = Elements[i + 1].WorldPosition - follower.WorldPosition; Vector3 AC = Elements[i + 1].WorldPosition - Elements[i].WorldPosition; Vector3 BC = follower.WorldPosition - Elements[i].WorldPosition; float sa = Godot.Mathf.Sqrt(BC.x * BC.x + BC.z * BC.z); float sb = Godot.Mathf.Sqrt(AC.x * AC.x + AC.z * AC.z); float sc = Godot.Mathf.Sqrt(AB.x * AB.x + AB.z * AB.z); float denominator = 2.0f * sa * sb; if (denominator != 0.0) { float originalAngle; { float value = (sa * sa + sb * sb - sc * sc) / denominator; if (value < -1.0) { originalAngle = Godot.Mathf.Pi; } else if (value > 1.0) { originalAngle = 0; } else { originalAngle = Godot.Mathf.Acos(value); } } TrackElement originalTrackElement = Elements[i]; bestT = float.MaxValue; bestJ = 0; for (int j = -1; j <= 1; j++) { float g = (float)(j * originalAngle); Elements[i] = originalTrackElement; Elements[i].WorldDirection = Elements[i].WorldDirection.Rotated(Vector3.Down, g); Elements[i].WorldUp = Elements[i].WorldUp.Rotated(Vector3.Down, g); Elements[i].WorldSide = Elements[i].WorldSide.Rotated(Vector3.Down, g); p = 0.00000001 * Elements[i].StartingTrackPosition + 0.99999999 * Elements[i + 1].StartingTrackPosition; follower.UpdateAbsolute((float)p - 1.0f, true, false); follower.UpdateAbsolute((float)p, true, false); d = Elements[i + 1].WorldPosition - follower.WorldPosition; float t = (float)Calc.NormSquared(d); if (t < bestT) { bestT = t; bestJ = j; } } { float newAngle = (float)(bestJ * originalAngle); Elements[i] = originalTrackElement; Elements[i].WorldDirection = Elements[i].WorldDirection.Rotated(Vector3.Down, newAngle); Elements[i].WorldUp = Elements[i].WorldUp.Rotated(Vector3.Down, newAngle); Elements[i].WorldSide = Elements[i].WorldSide.Rotated(Vector3.Down, newAngle); } // iterate again to further shorten track element length p = 0.00000001 * Elements[i].StartingTrackPosition + 0.99999999 * Elements[i + 1].StartingTrackPosition; follower.UpdateAbsolute((float)p - 1.0f, true, false); follower.UpdateAbsolute((float)p, true, false); d = Elements[i + 1].WorldPosition - follower.WorldPosition; bestT = (float)Calc.NormSquared(d); bestJ = 0; n = 1000; a = 1.0f / (float)n * (Elements[i + 1].StartingTrackPosition - Elements[i].StartingTrackPosition); for (int j = 1; j < n - 1; j++) { follower.UpdateAbsolute((float)(Elements[i + 1].StartingTrackPosition - (double)j * a), true, false); d = Elements[i + 1].WorldPosition - follower.WorldPosition; float t = (float)Calc.NormSquared(d); if (t < bestT) { bestT = t; bestJ = j; } else { break; } } s = (float)bestJ * a; for (int j = i + 1; j < Elements.Length; j++) { Elements[j].StartingTrackPosition -= s; } } // compensate for height difference p = 0.00000001 * Elements[i].StartingTrackPosition + 0.99999999 * Elements[i + 1].StartingTrackPosition; follower.UpdateAbsolute((float)p - 1.0f, true, false); follower.UpdateAbsolute((float)p, true, false); Vector3 d1 = Elements[i + 1].WorldPosition - Elements[i].WorldPosition; double a1 = Godot.Mathf.Atan(d1.y / Godot.Mathf.Sqrt(d1.x * d1.x + d1.z * d1.z)); Vector3 d2 = follower.WorldPosition - Elements[i].WorldPosition; double a2 = Godot.Mathf.Atan(d2.y / Godot.Mathf.Sqrt(d2.x * d2.x + d2.z * d2.z)); double b = a2 - a1; if (b * b > 0.00000001) { Elements[i].WorldDirection = Elements[i].WorldDirection.Rotated(Elements[i].WorldSide, (float)b); Elements[i].WorldUp = Elements[i].WorldUp.Rotated(Elements[i].WorldSide, (float)b); } } } } } // correct events /* * for (int i = 0; i < Elements.Length - 1; i++) * { * double startingTrackPosition = Elements[i].StartingTrackPosition; * double endingTrackPosition = Elements[i + 1].StartingTrackPosition; * for (int j = 0; j < Elements[i].Events.Length; j++) * { * GeneralEvent e = Elements[i].Events[j]; * double p = startingTrackPosition + e.TrackPositionDelta; * if (p >= endingTrackPosition) * { * int len = Elements[i + 1].Events.Length; * Array.Resize(ref Elements[i + 1].Events, len + 1); * Elements[i + 1].Events[len] = Elements[i].Events[j]; * e = Elements[i + 1].Events[len]; * e.TrackPositionDelta += startingTrackPosition - endingTrackPosition; * for (int k = j; k < Elements[i].Events.Length - 1; k++) * { * Elements[i].Events[k] = Elements[i].Events[k + 1]; * } * * len = Elements[i].Events.Length; * Array.Resize(ref Elements[i].Events, len - 1); * j--; * } * } * } */ }
void Start() { length = GetLength(); curve = GetComponentInParent <TrackElement>(); }
public void Extrude(Mesh mesh, ExtrudeShape shape) { if (curve == null) { curve = transform.GetComponentInParent <TrackElement>(); } // Bug fix when scaling the whole track if (curve.transform.localScale.x == 0.5f) { transform.localScale = new Vector3(2, 2, 2); } if (curve.transform.localScale.x == 1 || curve.transform.localScale.y == 1) { transform.localScale = new Vector3(1, 1, 1); } if (shape == null) { shape = new ExtrudeShape(); } float splineLength = GetLength(); shape.Initialize(1, curve.horizontalDivisions); int divisions = (int)(curve.divisionsPerCurve * splineLength / curve.trackWidth / 20); if (divisions < 1) { divisions = 1; } int vertsInShape = shape.verts.Length; List <int> triangleIndices = new List <int>(); //new int[triIndexCount]; List <Vector3> vertices = new List <Vector3>(); //new Vector3[vertCount]; List <Vector3> normals = new List <Vector3>(); //new Vector3[vertCount]; List <Vector2> uvs = new List <Vector2>(); //new Vector2[vertCount]; /* * Mesh generation code */ #region meshGeneration float divisionLength = 1.0f / (float)divisions; orientedPoints = new OrientedPoint[divisions + 1]; #region rightSide int rightOffset = 0; // Create vertices for (int i = 0; i <= divisions; ++i) {// for each edgeLoop float t = i * divisionLength; Vector3 up = Vector3.Lerp(startNode.transform.up, endNode.transform.up, t); float curvature = Mathf.Lerp(startNode.rightCurvature, endNode.rightCurvature, t); float width = (curve.trackWidth + Mathf.Lerp(startNode.trackWidthModifier, endNode.trackWidthModifier, t)) / 2; Matrix4x4 scale = Matrix4x4.Scale(new Vector3(width, width, width)); // Initialize oriented point orientedPoints[i].position = transform.InverseTransformPoint(GetPoint(t)); orientedPoints[i].rotation = Quaternion.Inverse(transform.rotation) * (GetOrientation(t, up)); orientedPoints[i].scale = scale; for (int j = 0; j < vertsInShape; ++j) {// for each vertex in the shape Vector2 vertex = Vector2.Lerp(shape.verts[j], shape.curvedVerts[j], curvature); Vector2 normal = Vector2.Lerp(shape.normals[j], shape.curvedNormals[j], curvature); vertices.Add(orientedPoints[i].LocalToWorld(vertex)); normals.Add(orientedPoints[i].LocalToWorldDirection(normal)); // u is based on the 2D shape, and v is based on the distance along the curve uvs.Add(new Vector2(shape.us[j], t * splineLength / width)); } } // Create triangles for (int j = 0; j < divisions; ++j) {// for each division in the curve int offset = shape.verts.Length * j; for (int k = 0; k < shape.lines.Length; k = k + 2) {//for each 2d line in the shape // triangle 1 triangleIndices.Add(shape.lines[k + 1] + offset); triangleIndices.Add(shape.lines[k] + offset); triangleIndices.Add(shape.lines[k] + offset + shape.verts.Length); // triangle 2 triangleIndices.Add(shape.lines[k + 1] + offset); triangleIndices.Add(shape.lines[k] + offset + shape.verts.Length); triangleIndices.Add(shape.lines[k + 1] + offset + shape.verts.Length); } } rightOffset = vertices.Count; #endregion #region leftSide for (int i = 0; i <= divisions; ++i) {// for each edgeLoop float t = i * divisionLength; Vector3 up = Vector3.Lerp(startNode.transform.up, endNode.transform.up, t); float curvature = Mathf.Lerp(startNode.leftCurvature, endNode.leftCurvature, t); float width = curve.trackWidth + Mathf.Lerp(startNode.trackWidthModifier, endNode.trackWidthModifier, t); // Initialize oriented point orientedPoints[i].position = transform.InverseTransformPoint(GetPoint(t)); orientedPoints[i].rotation = Quaternion.Inverse(transform.rotation) * (GetOrientation(t, up)); for (int j = 0; j < vertsInShape; ++j) {// for each vertex in the shape Vector2 vertex = Vector2.Lerp(shape.verts[j], shape.curvedVerts[j], curvature); vertex.x *= -1; Vector2 normal = Vector2.Lerp(shape.normals[j], shape.curvedNormals[j], curvature); vertices.Add(orientedPoints[i].LocalToWorld(vertex)); normals.Add(orientedPoints[i].LocalToWorldDirection(normal)); // u is based on the 2D shape, and v is based on the distance along the curve uvs.Add(new Vector2(shape.us[j], t * splineLength / width)); } } #endregion // Create triangles for (int j = 0; j < divisions; ++j) {// for each division in the curve int offset = shape.verts.Length * j; for (int k = 0; k < shape.lines.Length; k = k + 2) {//for each 2d line in the shape // triangle 1 triangleIndices.Add(shape.lines[k] + offset + rightOffset); triangleIndices.Add(shape.lines[k + 1] + offset + rightOffset); triangleIndices.Add(shape.lines[k] + offset + shape.verts.Length + rightOffset); // triangle 2 triangleIndices.Add(shape.lines[k] + offset + shape.verts.Length + rightOffset); triangleIndices.Add(shape.lines[k + 1] + offset + rightOffset); triangleIndices.Add(shape.lines[k + 1] + offset + shape.verts.Length + rightOffset); } } #endregion if (mesh == null) { mesh = new Mesh(); } mesh.Clear(); mesh.vertices = vertices.ToArray(); mesh.triangles = triangleIndices.ToArray(); mesh.normals = normals.ToArray(); mesh.uv = uvs.ToArray(); //mesh.RecalculateNormals(); gameObject.GetComponent <MeshFilter>().mesh = mesh; gameObject.GetComponent <MeshCollider>().sharedMesh = mesh; //gameObject.GetComponent<MeshCollider>().enabled = true; // enabled by default -> TO-DO: disabled on start! }