protected void CreateNativeTransformCollections() { _nativeTweenStates = new NativeArray <TweenTransformState>(_tweenStates.Length, Allocator.TempJob); JTweenTools.CopyTweenStateDirectlyToNativeArray(_tweenStates.buffer, _nativeTweenStates, _tweenStates.Length); _nativeTweenPositions = new NativeArray <TweenFloat3>(_tweenPositions.Length, Allocator.TempJob); JTweenTools.CopyTween3DirectlyToNativeArray(_tweenPositions.buffer, _nativeTweenPositions, _tweenPositions.Length); _nativeTweenRotations = new NativeArray <TweenRotation>(_tweenRotations.Length, Allocator.TempJob); JTweenTools.CopyTweenRotationDirectlyToNativeArray(_tweenRotations.buffer, _nativeTweenRotations, _tweenRotations.Length); _nativeTweenScales = new NativeArray <TweenFloat3>(_tweenScales.Length, Allocator.TempJob); JTweenTools.CopyTween3DirectlyToNativeArray(_tweenScales.buffer, _nativeTweenScales, _tweenScales.Length); _nativePositionLifetimes = new NativeArray <TweenLifetime>(_tweenPositionLifetimes.Length, Allocator.TempJob); JTweenTools.CopyTweenLifetimeDirectlyToNativeArray(_tweenPositionLifetimes.buffer, _nativePositionLifetimes, _tweenPositionLifetimes.Length); _nativeRotationLifetimes = new NativeArray <TweenLifetime>(_tweenRotationLifetimes.Length, Allocator.TempJob); JTweenTools.CopyTweenLifetimeDirectlyToNativeArray(_tweenRotationLifetimes.buffer, _nativeRotationLifetimes, _tweenRotationLifetimes.Length); _nativeScaleLifetimes = new NativeArray <TweenLifetime>(_tweenScaleLifetimes.Length, Allocator.TempJob); JTweenTools.CopyTweenLifetimeDirectlyToNativeArray(_tweenScaleLifetimes.buffer, _nativeScaleLifetimes, _tweenScaleLifetimes.Length); _nativePositions = new NativeArray <float3>(_tweenPositions.Length, Allocator.TempJob); _nativeRotations = new NativeArray <quaternion>(_tweenRotations.Length, Allocator.TempJob); _nativeScales = new NativeArray <float3>(_tweenScales.Length, Allocator.TempJob); }
protected void CopyNativeCollectionsToManaged() { JTweenTools.CopyNativeArrayDirectlyToTweenState(_nativeTweenStates, _tweenStates.buffer); JTweenTools.CopyNativeArrayDirectlyToTweenLifetime(_nativePositionLifetimes, _tweenPositionLifetimes.buffer); JTweenTools.CopyNativeArrayDirectlyToTweenLifetime(_nativeRotationLifetimes, _tweenRotationLifetimes.buffer); JTweenTools.CopyNativeArrayDirectlyToTweenLifetime(_nativeScaleLifetimes, _tweenScaleLifetimes.buffer); }
protected override void LateUpdateTweens() { Profiler.BeginSample(LATE_UPDATE_PROFILE); if (!_isJobScheduled) { Profiler.EndSample(); return; } _isJobScheduled = false; // Complete the batch process job _processBatchJobHandle.Complete(); JTweenTools.CopyNativeArrayDirectlyToTweenBatch(_nativeTweenBatches, _tweenBatches.buffer); JTweenTools.CopyNativeArrayDirectlyToTweenLifetime(_nativeTweenBatchLifetimes, _tweenBatchLifetimes.buffer); // Complete the tween job and any dependencies applyTweenUpdates.Complete(); // Get the data we need back from the native collections or if tween completed remove it. CopyNativeCollectionsToManaged(); // Sort batches from earliest index to latest, check for any completed batches, // and then remove en masse tweens where their batch is complete. for (var i = _tweenBatches.Length - 1; i >= 0; i--) { var batch = _tweenBatches.buffer[i]; if (_tweenBatchHandles.buffer[i] != null) { _tweenBatchHandles.buffer[i].state = batch.state; } if (batch.IsCompleted()) { if (batch.JustEnded()) { batch.state &= ~TweenStateType.JustEnded; _tweenBatches.buffer[i] = batch; if (_tweenBatchHandles.buffer[i] != null) { _tweenBatchHandles.buffer[i].state = batch.state; _tweenHandleCallbackEventQueue.Enqueue(_tweenBatchHandles.buffer[i]); } } if (batch.RequiresRecycling()) { var index = (int)batch.startIndex; var length = (int)batch.length; // We don't have a great option here for removing a range of transforms from this // specific native collection type. for (var j = index + length - 1; j >= index; j--) { Profiler.BeginSample(TRANSFORM_ACCESS_ARRAY_REMOVE_PROFILE); _transformAccessArray.RemoveAtSwapBack(j); Profiler.EndSample(); } Profiler.BeginSample(FAST_LIST_REMOVE_RANGE); _transforms.RemoveRange(index, length); _tweenStates.RemoveRange(index, length); _tweenPositions.RemoveRange(index, length); _tweenRotations.RemoveRange(index, length); _tweenScales.RemoveRange(index, length); _tweenPositionLifetimes.RemoveRange(index, length); _tweenRotationLifetimes.RemoveRange(index, length); _tweenScaleLifetimes.RemoveRange(index, length); // Shuffle all batches ahead of the current one so that their start indexes are adjusted back // based on the length of the batch we are removing. for (var j = i + 1; j < _tweenBatches.Length; j++) { var laterTweenBatch = _tweenBatches.buffer[j]; laterTweenBatch.startIndex -= batch.length; _tweenBatches.buffer[j] = laterTweenBatch; } _tweenBatches.RemoveAt(i); _tweenBatchLifetimes.RemoveAt(i); _tweenBatchHandles.RemoveAt(i); Profiler.EndSample(); } } } // Properly dispose of the native collections DisposeNativeTransformCollections(); _nativeTweenBatches.Dispose(); _nativeTweenBatchLifetimes.Dispose(); Profiler.EndSample(); Profiler.BeginSample(EVENT_COMPLETED_PROFILE); // After all sensitive native work has completed, kick out any and all completed events while (_tweenHandleCallbackEventQueue.Count > 0) { var tweenHandle = _tweenHandleCallbackEventQueue.Dequeue(); _tweenHandlePool.AddLast(tweenHandle); tweenHandle.Completed?.Invoke(); } Profiler.EndSample(); }
protected override void UpdateTweens() { Profiler.BeginSample(UPDATE_PROFILE); if (_transforms.Length == 0) { Profiler.EndSample(); return; } while (_tweenHandleActionEventQueue.Count > 0) { var updateLifetimes = false; var tweenHandleAction = _tweenHandleActionEventQueue.Dequeue(); if (tweenHandleAction.index >= 0 && tweenHandleAction.index < _tweenBatchHandles.Length) { var tweenHandle = _tweenBatchHandles.buffer[tweenHandleAction.index]; var tweenBatch = _tweenBatches.buffer[tweenHandleAction.index]; switch (tweenHandle.actionType) { case TweenHandleActionType.Play: if (!tweenBatch.IsCompleted() && tweenBatch.IsPaused()) { tweenBatch.state |= TweenStateType.IsPlaying; tweenBatch.state &= ~TweenStateType.IsPaused; } break; case TweenHandleActionType.Pause: if (tweenBatch.IsPlaying()) { tweenBatch.state &= ~TweenStateType.IsPlaying; tweenBatch.state |= TweenStateType.IsPaused; } break; case TweenHandleActionType.Stop: if (tweenBatch.IsPlaying() || tweenBatch.IsPaused()) { tweenBatch.state &= ~TweenStateType.IsPlaying; tweenBatch.state &= ~TweenStateType.IsPaused; tweenBatch.state |= TweenStateType.IsCompleted; tweenBatch.state |= TweenStateType.JustEnded; } break; case TweenHandleActionType.Recycle: tweenBatch.state &= ~TweenStateType.IsPaused; tweenBatch.state &= ~TweenStateType.IsPlaying; tweenBatch.state &= ~TweenStateType.HasHandle; tweenBatch.state |= TweenStateType.IsCompleted; tweenBatch.state |= TweenStateType.RequiresRecycling; break; case TweenHandleActionType.Rewind: tweenBatch.state = HANDLE_START_PAUSED; var tweenBatchLifetimeRewind = _tweenBatchLifetimes.buffer[tweenHandleAction.index]; tweenBatchLifetimeRewind.Restart(); _tweenBatchLifetimes.buffer[tweenHandleAction.index] = tweenBatchLifetimeRewind; updateLifetimes = true; break; case TweenHandleActionType.Restart: tweenBatch.state = HANDLE_START_PLAYING; var tweenBatchLifetimeRestart = _tweenBatchLifetimes.buffer[tweenHandleAction.index]; tweenBatchLifetimeRestart.Restart(); _tweenBatchLifetimes.buffer[tweenHandleAction.index] = tweenBatchLifetimeRestart; updateLifetimes = true; break; case TweenHandleActionType.None: default: throw new NotImplementedException(); } for (var i = tweenBatch.startIndex; i < tweenBatch.startIndex + tweenBatch.length; i++) { var tweenState = _tweenStates.buffer[i]; tweenState.state = tweenBatch.state; _tweenStates.buffer[i] = tweenState; if (updateLifetimes) { var tweenPosLifetime = _tweenPositionLifetimes.buffer[i]; tweenPosLifetime.Restart(); _tweenPositionLifetimes.buffer[i] = tweenPosLifetime; var tweenRotLifetime = _tweenRotationLifetimes.buffer[i]; tweenRotLifetime.Restart(); _tweenRotationLifetimes.buffer[i] = tweenRotLifetime; var tweenScaleLifetime = _tweenScaleLifetimes.buffer[i]; tweenScaleLifetime.Restart(); _tweenScaleLifetimes.buffer[i] = tweenScaleLifetime; } } tweenHandle.state = tweenBatch.state; _tweenBatches.buffer[tweenHandleAction.index] = tweenBatch; } else { Debug.LogWarning(RuntimeConstants.HANDLE_BATCH_NOT_FOUND); } } for (var i = 0; i < _tweenBatches.Length; i++) { var tweenBatch = _tweenBatches.buffer[i]; if (tweenBatch.IsPlaying() && tweenBatch.JustStarted()) { tweenBatch.state &= ~TweenStateType.JustStarted; _tweenBatches.buffer[i] = tweenBatch; if (_tweenBatchHandles.buffer[i] != null) { _tweenBatchHandles.buffer[i].state = tweenBatch.state; _tweenHandleCallbackEventQueue.Enqueue(_tweenBatchHandles.buffer[i]); } } } // Create and setup native collections. Copy over existing data CreateNativeTransformCollections(); _nativeTweenBatches = new NativeArray <TweenTransformBatchState>(_tweenBatches.Length, Allocator.TempJob); JTweenTools.CopyTweenBatchDirectlyToNativeArray(_tweenBatches.buffer, _nativeTweenBatches, _tweenBatches.Length); _nativeTweenBatchLifetimes = new NativeArray <TweenLifetime>(_tweenBatchLifetimes.Length, Allocator.TempJob); JTweenTools.CopyTweenLifetimeDirectlyToNativeArray(_tweenBatchLifetimes.buffer, _nativeTweenBatchLifetimes, _tweenBatchLifetimes.Length); // Schedule Jobs _processBatchJob = new ProcessBatchJob { deltaTime = _deltaTime, batchLifetimes = _nativeTweenBatchLifetimes, tweenBatches = _nativeTweenBatches }; _processBatchJobHandle = _processBatchJob.Schedule(_tweenBatches.Length, 1); SetupJobs(); _isJobScheduled = true; Profiler.EndSample(); Profiler.BeginSample(EVENT_STARTED_PROFILE); // After all sensitive native work has completed, kick out any and all started events while (_tweenHandleCallbackEventQueue.Count > 0) { var tweenEvent = _tweenHandleCallbackEventQueue.Dequeue(); tweenEvent.Started?.Invoke(); } Profiler.EndSample(); }
internal void RotateOnAxis( Transform target, float angle, float duration, RotateMode rotateMode, SpaceType spaceType, EaseType easeType, LoopType loopType, int loopCount, Action onStart, Action onComplete, bool useTweenHandle, out ITweenHandle tweenHandle) { Assert.IsTrue(rotateMode != RotateMode.XYZ, RuntimeConstants.INVALID_ROTATE_MODE); tweenHandle = null; _transforms.Add(target); _transformAccessArray.Add(target); var rotateType = JTweenTools.GetTweenSpaceTypeFromRotateMode(rotateMode); _tweenStates.Add(new TweenTransformState { state = useTweenHandle ? HANDLE_START_PAUSED : NO_HANDLE_START, transformType = TweenTransformType.Rotation, spaceType = spaceType == SpaceType.World ? TweenSpaceType.WorldRotation | rotateType : TweenSpaceType.LocalRotation | rotateType }); _tweenPositions.Add(new TweenFloat3()); var eulerAngles = spaceType == SpaceType.World ? target.eulerAngles : target.localEulerAngles; _tweenRotations.Add(new TweenRotation { from = new quaternion(eulerAngles.x, eulerAngles.y, eulerAngles.z, 0), angle = angle }); _tweenScales.Add(new TweenFloat3()); _tweenPositionLifetimes.Add(new TweenLifetime()); _tweenRotationLifetimes.Add(new TweenLifetime { duration = Mathf.Max(0, duration), easeType = easeType, loopType = loopType, loopCount = (short)Mathf.Clamp(loopCount, -1, short.MaxValue), originalLoopCount = (short)Mathf.Clamp(loopCount, -1, short.MaxValue) }); _tweenScaleLifetimes.Add(new TweenLifetime()); var hasEvents = onStart != null || onComplete != null; if (useTweenHandle || hasEvents) { var availableTweenHandle = GetNextAvailableTweenHandle(); availableTweenHandle.state = useTweenHandle ? HANDLE_START_PAUSED : NO_HANDLE_START; if (onStart != null) { availableTweenHandle.AddOnStartedListener(onStart); } if (onComplete != null) { availableTweenHandle.AddOnCompletedListener(onComplete); } _tweenHandles.Add(availableTweenHandle); // Only populate the out parameter if explicitly called out for. if (useTweenHandle) { tweenHandle = availableTweenHandle; } } else { _tweenHandles.Add(null); } }