static keyframe* KeyframeLookupMemory(property_channel *Property, int16 i) { int16 b = i / MAX_KEYFRAMES_PER_BLOCK; int16 k = i - b*MAX_KEYFRAMES_PER_BLOCK; return &Property->KeyframeBlock[b]->Keyframe[k]; } static keyframe* PushKeyframe(property_channel *Property) { int16 i = Property->NumberOfTotalKeyframes; int16 b = i / MAX_KEYFRAMES_PER_BLOCK; int16 k = i - b*MAX_KEYFRAMES_PER_BLOCK; return &Property->KeyframeBlock[b]->Keyframe[k]; } static temp_keyframe_list GetSelectedKeyframes(project_data *File) { temp_keyframe_list KeyframeList; int z = 0; for (int i = 0; i < File->NumberOfLayers; i++) { for (int a = 0; a < AmountOf(File->Layer[i]->Property); a++) { for (int l = 0; l < File->Layer[i]->Property[a].NumberOfTotalKeyframes; l++) { keyframe *Keyframe = KeyframeLookupMemory(&File->Layer[i]->Property[a], l); if (Keyframe->IsSelected) { KeyframeList.SelectedKeyframe[z] = Keyframe; z++; } } } } KeyframeList.Amount = z; return KeyframeList; } static void SelectKeyframe(project_data *File, project_layer *Layer, property_channel *Property, keyframe *Keyframe) { Layer->IsSelected = true; File->NumberOfSelectedLayers++; Property->NumberOfSelectedKeyframes++; Keyframe->IsSelected = true; } static void DeselectKeyframe(project_data *File, project_layer *Layer, property_channel *Property, keyframe *Keyframe) { Layer->IsSelected = true; File->NumberOfSelectedLayers++; Property->NumberOfSelectedKeyframes++; Keyframe->IsSelected = true; } static void CheckKeyframeSort(property_channel *Property, int32 Increment, int32 b) { /* int32 i = KeyframeMemoryToIndex(Property, b); if (Increment > 0) { if (i+1 != Property->NumberOfTotalKeyframes) { keyframe *CurrentKeyframe = KeyframeLookupIndex(Property, i); keyframe *NextKeyframe = KeyframeLookupIndex(Property, i + 1); if (NextKeyframe->FrameNumber < CurrentKeyframe->FrameNumber) { uint16 Temp = Property->SortedIndex[i]; Property->SortedIndex[i] = Property->SortedIndex[i + 1]; Property->SortedIndex[i + 1] = Temp; } } } else { if (i != 0) { keyframe *CurrentKeyframe = KeyframeLookupIndex(Property, i); keyframe *LastKeyframe = KeyframeLookupIndex(Property, i - 1); if (CurrentKeyframe->FrameNumber < LastKeyframe->FrameNumber) { uint16 Temp = Property->SortedIndex[i]; Property->SortedIndex[i] = Property->SortedIndex[i - 1]; Property->SortedIndex[i - 1] = Temp; } } } */ } static void ShiftKeyframeIndex(property_channel *Property, int16 Increment, int16 StopAt) { /* if (Increment > 0) { int16 i = Property->NumberOfTotalKeyframes - 1; while (i > StopAt) { Property->SortedIndex[i + Increment] = Property->SortedIndex[i]; i--; } } else { int16 i = StopAt; while (i < Property->NumberOfTotalKeyframes - 1) { Property->SortedIndex[i] = Property->SortedIndex[i + Increment]; i++; } } */ } static void DeleteKeyframeFromMemory(property_channel *Property, int16 Increment, int16 StopAt) { if (Increment > 0) { int16 i = Property->NumberOfTotalKeyframes - 1; while (i > StopAt) { keyframe *CurrentKeyframe = KeyframeLookupMemory(Property, i); keyframe *NextKeyframe = KeyframeLookupMemory(Property, i + Increment); *NextKeyframe = *CurrentKeyframe; i--; } Property->NumberOfTotalKeyframes += Increment; } else { int16 i = StopAt; while (i < Property->NumberOfTotalKeyframes - 1) { keyframe *CurrentKeyframe = KeyframeLookupMemory(Property, i); keyframe *NextKeyframe = KeyframeLookupMemory(Property, i - Increment); *CurrentKeyframe = *NextKeyframe; i++; } Property->NumberOfTotalKeyframes += Increment; } } static void ResortPropertyChannel(property_channel *Property) { /* for (int16 i = 0; i < Property->NumberOfTotalKeyframes; i++) { Property->SortedIndex[i] = i; } for (;;) { int16 Swaps = 0; for (int16 i = 0; i < Property->NumberOfTotalKeyframes - 1; i++) { keyframe *Keyframe = KeyframeLookupIndex(Property, i); keyframe *NextKeyframe = KeyframeLookupIndex(Property, i + 1); if (Keyframe->FrameNumber > NextKeyframe->FrameNumber) { uint16 Temp = Property->SortedIndex[i]; Property->SortedIndex[i] = Property->SortedIndex[i + 1]; Property->SortedIndex[i + 1] = Temp; Swaps++; } } if (Swaps == 0) break; } */ } static void DeleteSelectedKeyframes(project_data *File, memory *Memory) { for (int i = 0; i < File->NumberOfLayers; i++) { for (int a = 0; a < AmountOf(File->Layer[i]->Property); a++) { property_channel *Property = &File->Layer[i]->Property[a]; for (int l = 0; l < Property->NumberOfTotalKeyframes; l++) { keyframe *Keyframe = KeyframeLookupMemory(Property, l); if (Keyframe->IsSelected) { int16 ToShift = 1; bool32 Until = true; while (Until) { keyframe *KeyframeN = KeyframeLookupMemory(Property, l + ToShift); if (KeyframeN->IsSelected) { ToShift += 1; } else { Until = false; } } DeleteKeyframeFromMemory(Property, -ToShift, l); } } ResortPropertyChannel(Property); } } } static void CalculatePropertyMinMax(property_channel *Property) { Property->LocalMaxVal = Property->MinVal; Property->LocalMinVal = Property->MaxVal; for (int16 i = 0; i < Property->NumberOfTotalKeyframes; i++) { keyframe *Keyframe = KeyframeLookupMemory(Property, i); Property->LocalMinVal.f = Ceil(Property->LocalMinVal.f, Keyframe->Value.f); Property->LocalMaxVal.f = Floor(Property->LocalMaxVal.f, Keyframe->Value.f); } if (Property->LocalMinVal.f == Property->LocalMaxVal.f) { Property->LocalMaxVal.f += 1; } } static void IncrementKeyframes(property_channel *Property, int16 Increment) { /* for (int i = 0; i < Property->NumberOfTotalKeyframes; i++) { keyframe *Keyframe = KeyframeLookupIndex(Property, i); Keyframe->FrameNumber += Increment; } */ } static void IncrementKeyframesInLayer(project_layer *Layer, int16 Increment) { for (int a = 0; a < AmountOf(Layer->Property); a++) IncrementKeyframes(&Layer->Property[a], Increment); for (int e = 0; e < Layer->NumberOfEffects; e++) for (int a = 0; a < Layer->Effect[e]->NumberOfProperties; a++) IncrementKeyframes(&Layer->Effect[e]->Property[a], Increment); } static void CreateKeyframeBlock(property_channel *, memory *); // dir 0 left, 1 right static void ClampKeyframeHandles(property_channel *Property, int16 b, int16 dir) { if (dir == 0) { if (b > 0) { keyframe *Keyframe = KeyframeLookupMemory(Property, b - 1); keyframe *NextKeyframe = KeyframeLookupMemory(Property, b); real32 XSpan = NextKeyframe->FrameNumber - Keyframe->FrameNumber; // TODO(fox): Fix this! #if WINDOWS if (NextKeyframe->TangentLeft.x > XSpan) #else if (abs(NextKeyframe->TangentLeft.x) > XSpan) #endif NextKeyframe->TangentLeft.x = -XSpan; if (NextKeyframe->TangentLeft.x > 0) NextKeyframe->TangentLeft.x = 0; } } if (dir == 1) { if (b < Property->NumberOfTotalKeyframes - 1) { keyframe *Keyframe = KeyframeLookupMemory(Property, b); keyframe *NextKeyframe = KeyframeLookupMemory(Property, b + 1); real32 XSpan = NextKeyframe->FrameNumber - Keyframe->FrameNumber; if (Keyframe->TangentRight.x > XSpan) Keyframe->TangentRight.x = XSpan; if (Keyframe->TangentRight.x < 0) Keyframe->TangentRight.x = 0; } } } static void ClampSurroundingKeyframeHandles(property_channel *Property, int16 b) { ClampKeyframeHandles(Property, b, 0); ClampKeyframeHandles(Property, b, 1); if (b > 0) { ClampKeyframeHandles(Property, b-1, 0); ClampKeyframeHandles(Property, b-1, 1); } if (b < Property->NumberOfTotalKeyframes - 1) { ClampKeyframeHandles(Property, b+1, 0); ClampKeyframeHandles(Property, b+1, 1); } } static void ManualKeyframeInsertF(property_channel *Property, memory *Memory, int32 CurrentFrame, real32 Val) { /* if (!(Property->NumberOfTotalKeyframes % MAX_KEYFRAMES_PER_BLOCK)) { CreateKeyframeBlock(Property, Memory); } keyframe *Keyframe = NULL; if (Property->NumberOfTotalKeyframes == 0) { Keyframe = &Property->KeyframeBlock[0]->Keyframe[0]; } else if (Property->NumberOfTotalKeyframes == 1) { keyframe *FirstKeyframe = &Property->KeyframeBlock[0]->Keyframe[0]; if (CurrentFrame > FirstKeyframe->FrameNumber) { Keyframe = &Property->KeyframeBlock[0]->Keyframe[1]; } else { Keyframe = &Property->KeyframeBlock[0]->Keyframe[0]; } } else { uint32 Index = Property->NumberOfTotalKeyframes - 1; bool32 Found = false; while (!Found) { keyframe *CurrentKeyframe = KeyframeLookupMemory(Property, Index); if (CurrentKeyframe->FrameNumber < CurrentFrame) { ShiftKeyframes(Property, 1, i - 1); Found = true; } else { Index--; } } Keyframe = PushKeyframe(Property); } if (Keyframe->FrameNumber != CurrentFrame) Property->NumberOfTotalKeyframes++; Assert(!(Keyframe == NULL)) Keyframe->FrameNumber = CurrentFrame; Keyframe->Value.f = Val; Keyframe->Type = bezier; Keyframe->TangentLeft = V2(-1, 0); Keyframe->TangentRight = V2(1, 0); Keyframe->ImguiID = RandomGlobalIncrement++; CalculatePropertyMinMax(Property); */ } static void CalculateKeyframesLinearly(uint16 CurrentFrame, struct property_channel *Property) { /* keyframe *FirstKeyframe = KeyframeLookupIndex(Property, 0); keyframe *LastKeyframe = KeyframeLookupIndex(Property, Property->NumberOfTotalKeyframes - 1); if (Property->NumberOfTotalKeyframes == 0) { // do nothing } // check if current frame is before first keyframe or after last else if (Property->NumberOfTotalKeyframes == 1 || CurrentFrame < FirstKeyframe->FrameNumber) { Property->CurrentValue = FirstKeyframe->Value; } else if (CurrentFrame > LastKeyframe->FrameNumber) { Property->CurrentValue = LastKeyframe->Value; } else if (Property->NumberOfTotalKeyframes > 1) { for (int i = 0; i < (Property->NumberOfTotalKeyframes - 1); i++) { keyframe *Keyframe = KeyframeLookupIndex(Property, i); keyframe *NextKeyframe = KeyframeLookupIndex(Property, i+1); if (CurrentFrame >= Keyframe->FrameNumber && CurrentFrame <= NextKeyframe->FrameNumber) { real32 FakeVelocity = ((CurrentFrame - Keyframe->FrameNumber) / (NextKeyframe->FrameNumber - (real32)Keyframe->FrameNumber)); real32 t = FakeVelocity; // real32 u = 1.0f - t; // real32 w1 = u * u * u; // real32 w2 = 3 * u * u * t; // real32 w3 = 3 * u * t * t; // real32 w4 = t * t * t; real32 t2 = t * t; real32 t3 = t2 * t; real32 mt = 1-t; real32 mt2 = mt * mt; real32 mt3 = mt2 * mt; if (Property->VarType == type_real ) { real32 OldValue = Property->CurrentValue.f; real32 CurrentVal = Keyframe->Value.f; real32 CurrentTan = CurrentVal + Keyframe->TangentRight.y; real32 NextVal = NextKeyframe->Value.f; real32 NextTan = NextVal + NextKeyframe->TangentLeft.y; // Property->CurrentValue.f = w1 * CurrentVal + w2 * CurrentTan + w3 * NextTan + w4 * NextVal; Property->CurrentValue.f = CurrentVal*mt3 + 3*CurrentTan*mt2*t + 3*NextTan*mt*t2 + NextVal*t3; //Property->CurrentValue.f = CurrentVal + ((NextVal - CurrentVal) * FakeVelocity); } else if (Property->VarType == type_color) { v4 OldValue = Property->CurrentValue.col; v4 CurrentVal = Keyframe->Value.col; v4 NextVal = NextKeyframe->Value.col; Property->CurrentValue.col = CurrentVal + ((NextVal - CurrentVal) * FakeVelocity); } break; } } } */ }