static temp_layer_list FindSelectedLayerIndex(project_data *File, int16 NumberOfSelectedLayers) { temp_layer_list List = {}; if (!NumberOfSelectedLayers) return List; int16 i = 0; int16 n = 0; while (NumberOfSelectedLayers) { if (File->Layer[i]->IsSelected == true) { List.LayerIndex[n] = i; n++; NumberOfSelectedLayers--; } i++; Assert(i <= File->NumberOfLayers); } return List; } static transform_info CalculateTransforms(project_layer *Layer, comp_buffer *CompBuffer); static v2 CompUVToLayerUV(project_layer *Layer, comp_buffer *CompBuffer, v2 CompUV) { real32 X = CompUV.x*CompBuffer->Width; real32 Y = CompUV.y*CompBuffer->Height; transform_info T = CalculateTransforms(Layer, CompBuffer); real32 StartVectorX = X - T.OriginX; real32 StartVectorY = Y - T.OriginY; real32 LayerU = (StartVectorX * T.XAxisPX) + (StartVectorY * T.XAxisPY); real32 LayerV = (StartVectorX * T.YAxisPX) + (StartVectorY * T.YAxisPY); return V2(LayerU, LayerV); } static void TransformsInteract(project_data *File, project_state *State, memory *Memory, ui *UI, transforms_hotkey_interact Mode) { if (UI->FocusedWindow == focus_timeline) { temp_layer_list List = FindSelectedLayerIndex(File, State->NumberOfSelectedLayers); for (int i = 0; i < State->NumberOfSelectedLayers; i++) { uint16 Index = List.LayerIndex[i]; if (Mode == sliding_position) { File->Layer[Index]->x.IsToggled ^= 1; File->Layer[Index]->y.IsToggled ^= 1; } else if (Mode == sliding_anchorpoint) { File->Layer[Index]->ax.IsToggled ^= 1; File->Layer[Index]->ay.IsToggled ^= 1; } else if (Mode == sliding_rotation) { File->Layer[Index]->rotation.IsToggled ^= 1; } else if (Mode == sliding_scale) { File->Layer[Index]->scale.IsToggled ^= 1; } } } else if (UI->FocusedWindow == focus_viewport) { // TODO(fox): Make multi-select possible! project_layer *Layer = File->Layer[State->MostRecentlySelectedLayer]; if (Mode == sliding_position) { State->InteractCache[0] = Layer->x.CurrentValue.f; State->InteractCache[1] = Layer->y.CurrentValue.f; } else if (Mode == sliding_anchorpoint) { State->InteractCache[0] = Layer->x.CurrentValue.f; State->InteractCache[1] = Layer->y.CurrentValue.f; State->InteractCache[2] = Layer->ax.CurrentValue.f; State->InteractCache[3] = Layer->ay.CurrentValue.f; } else if (Mode == sliding_rotation) { State->InteractCache[0] = Layer->rotation.CurrentValue.f; } else if (Mode == sliding_scale) { State->InteractCache[0] = Layer->scale.CurrentValue.f; } State->IsInteracting = true; State->TransformsHotkeyInteract = Mode; } } static void SelectLayer(project_layer *Layer, project_state *State, int32 i) { Layer->IsSelected = true; State->NumberOfSelectedLayers++; State->MostRecentlySelectedLayer = i; } static void DuplicateLayer(project_data *File, project_state *State) { project_layer *Layer = File->Layer[State->MostRecentlySelectedLayer]; } static void DeselectAllLayers(project_data *File, project_state *State) { temp_layer_list List = FindSelectedLayerIndex(File, State->NumberOfSelectedLayers); for (int i = 0; i < State->NumberOfSelectedLayers; i++) { uint16 Index = List.LayerIndex[i]; File->Layer[Index]->IsSelected = false; } State->NumberOfSelectedLayers = 0; State->MostRecentlySelectedLayer = -1; } // NOTE(fox): We probably can't get away with being _this_ minimal about layer // indexing without making the code massively more complicated down the road; // keeping an Index value in the layer and just sorting every time the order // changes probably won't be much of a performance cost. static void MoveLayersByIncrement(project_data *File, project_state *State, int16 Increment) { bool32 AllowMove = true; temp_layer_list List = FindSelectedLayerIndex(File, State->NumberOfSelectedLayers); // The layer list is always sorted, so we should be able to safely check // whether the first and last layer on the list is the // top/bottommost-indexed layer. if ((List.LayerIndex[0] == 0) && (Increment < 0)) AllowMove = false; if ((List.LayerIndex[State->NumberOfSelectedLayers - 1] == (File->NumberOfLayers - 1)) && (Increment > 0)) AllowMove = false; if (AllowMove) { int16 i = 0; int16 c = 1; if (Increment < 0) c = -1; while (i < State->NumberOfSelectedLayers) { // If selected layers are right next to each other, we have to sort // them differently. if ((Increment > 0) && (List.LayerIndex[i + c - 1] == (List.LayerIndex[i+c] - 1))) { c++; continue; } uint16 Index = List.LayerIndex[i]; project_layer TopmostLayer = *File->Layer[Index+c]; if (c <= 1) { if (Index == State->MostRecentlySelectedLayer) State->MostRecentlySelectedLayer += Increment; *File->Layer[Index + Increment] = *File->Layer[Index]; *File->Layer[Index] = TopmostLayer; i++; } else { int p = c; while (c > 0) { if (Index+c == State->MostRecentlySelectedLayer) State->MostRecentlySelectedLayer += Increment; // project_layer Temp = *File->Layer[Index+c]; *File->Layer[Index+c] = *File->Layer[Index + c - 1]; c--; } if (Index == State->MostRecentlySelectedLayer) State->MostRecentlySelectedLayer += Increment; *File->Layer[Index] = TopmostLayer; i += p; c = 1; } } } } /* static bool32 TestSelectedLayer(project_state *State, uint16 *a, uint16 Index) { bool32 Result = 0; if (State->NumberOfSelectedLayers == 0) return Result; if (Index == 0) { for (int i = 0; i < State->NumberOfSelectedLayers; i++) { State->TempSelectedLayerSorted[i] = State->SelectedLayerIndex[i]; } bool32 SwapMade = true; while (SwapMade) { int Swaps = 0; for (int i = 0; i < State->NumberOfSelectedLayers - 1; i++) { if (State->TempSelectedLayerSorted[i] > State->TempSelectedLayerSorted[i+1]) { int32 Temp = State->TempSelectedLayerSorted[i]; State->TempSelectedLayerSorted[i] = State->TempSelectedLayerSorted[i+1]; State->TempSelectedLayerSorted[i+1] = Temp; Swaps++; } } if (!Swaps) SwapMade = false; } } if (State->TempSelectedLayerSorted[*a] == Index) { Result = 1; *a += 1; } if (*a >= State->NumberOfSelectedLayers) *a = 0; return Result; } */