summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/createcalls.cpp86
-rw-r--r--src/imgui_ui.cpp9
-rw-r--r--src/imgui_ui_viewport.cpp2
-rw-r--r--src/include/all.h2
-rw-r--r--src/include/main.h7
-rw-r--r--src/main.cpp18
-rw-r--r--src/sorted.cpp78
7 files changed, 136 insertions, 66 deletions
diff --git a/src/createcalls.cpp b/src/createcalls.cpp
index d7fb4b7..ffb4c0f 100644
--- a/src/createcalls.cpp
+++ b/src/createcalls.cpp
@@ -788,32 +788,10 @@ Property_IsGraphSelected(memory *Memory, uint16 *Block_Bezier_Index, uint16 *Arr
return 0;
}
-// TODO(fox): It seems like duping many layers at once causes this to take up
-// exponentially more data on the undo tree than it should. Rewrite the loop to
-// change the offsets before duping, taking into account all dupes, like what
-// the sorting code does.
-// TODO(fox): Add different modes (all dupes on top, each dupe above its layer, two for bottom)
static void
Sort_OffsetDupes(memory *Memory, sorted_layer_array *SortedLayerStart, block_layer *StartLayer,
int i, int FauxIncrement, int LayerCount, int Mode)
{
- block_layer *PrevLayer = StartLayer;
- for (int a = i+1; a < LayerCount; a++) {
- sorted_layer_array *NextSortEntry = &SortedLayerStart[a];
- uint32 NextIndex_Physical = NextSortEntry->Block_Layer_Index;
- block_layer *NextLayer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, NextIndex_Physical);
- if (NextLayer->Vertical_Offset == PrevLayer->Vertical_Offset) {
- if (Mode == 0 && !NextSortEntry->IsFake) {
- History_Action_Swap(Memory, F_Layers, sizeof(NextLayer->Vertical_Offset), &NextLayer->Vertical_Offset);
- NextLayer->Vertical_Offset -= 1;
- } else {
- NextSortEntry->SortedOffset -= 1;
- }
- } else {
- break;
- }
- PrevLayer = NextLayer;
- }
}
// NOTE(fox): PrecompLayer is assumed to be untouched from the layer it was duplicated from!
@@ -867,21 +845,27 @@ Layer_Precomp_CopyContents(project_data *File, project_state *State, memory *Mem
static void
Project_Layer_Duplicate(project_data *File, project_state *State, memory *Memory,
- sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, v2 Offset, bool32 FakeOnly, bool32 NewPrecomp)
+ sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, v2 Offset, bool32 NewPrecomp)
{
for (int c = 0; c < File->Comp_Count; c++) {
sorted_comp_array SortedCompStart = SortedCompArray[c];
sorted_layer_array *SortedLayerStart = Sorted_GetLayerStart(SortedLayerArray, SortedCompArray, c);
int LayerCount = SortedCompStart.LayerCount + SortedCompStart.FakeLayerCount;
- for (int i = 0; i < LayerCount; i++)
+ int FirstDupe = -1;
+ int DupeCount = 0;
+ int Direction = (State->DuplicateMode & sortflag_up) ? 1 : -1;
+ if (State->DuplicateMode & sortflag_furthest && !(State->DuplicateMode & sortflag_up))
+ Direction *= -1;
+ int i = (Direction > 0) ? 0 : LayerCount - 1;
+ for (;;)
{
- sorted_layer_array SortEntry = SortedLayerStart[i];
- uint32 Index_Physical = SortEntry.Block_Layer_Index;
+ sorted_layer_array *SortEntry = &SortedLayerStart[i];
+ uint32 Index_Physical = SortEntry->Block_Layer_Index;
block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
- if ((FakeOnly && SortEntry.IsFake) || (!FakeOnly && (Layer->IsSelected & 0x01)))
+ if (SortEntry->IsFake)
{
- if (!FakeOnly)
- Layer->IsSelected = 0x00;
+ if (FirstDupe == -1)
+ FirstDupe = i;
block_layer *NewLayer = (block_layer *)Memory_Block_AllocateAddress(Memory, F_Layers);
History_Action_Block_Swap(Memory, F_Layers, NewLayer);
@@ -894,11 +878,12 @@ Project_Layer_Duplicate(project_data *File, project_state *State, memory *Memory
// TODO(fox): Effect duplication
Assert(Layer->Block_Effect_Count == 0);
+ int NewIdx = Memory_Block_LazyIndexAtAddress(Memory, F_Layers, NewLayer);
Layer_Select(Memory, State, Memory_Block_LazyIndexAtAddress(Memory, F_Layers, NewLayer));
- NewLayer->Vertical_Offset--;
+ // NOTE(fox): Sort entry being modified outside initial sort
+ // call to make undo tree more efficient!
+ SortEntry->Block_Layer_Index = NewIdx;
- Sort_OffsetDupes(Memory, SortedLayerStart, NewLayer, i, 0, LayerCount, 0);
-
Assert(!NewLayer->x.Keyframe_Count);
Assert(!NewLayer->y.Keyframe_Count);
NewLayer->x.CurrentValue += Offset.x;
@@ -916,6 +901,43 @@ Project_Layer_Duplicate(project_data *File, project_state *State, memory *Memory
} else {
Layer->IsSelected = 0x00;
}
+ if ((Direction > 0) ? !(i < LayerCount) : (i <= 0))
+ break;
+ i += Direction;
+ }
+ if (FirstDupe > -1) {
+ int FauxIncrement = 0;
+ int FurthestMark = -1;
+ {
+ sorted_layer_array SortEntry = SortedLayerStart[FirstDupe];
+ uint32 Index_Physical = SortEntry.Block_Layer_Index;
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
+ FurthestMark = Layer->Vertical_Offset;
+ }
+ if (State->DuplicateMode & sortflag_furthest && !(State->DuplicateMode & sortflag_up))
+ {
+ FauxIncrement = -SortedCompStart.FakeLayerCount;
+ }
+ int i = (Direction > 0) ? 0 : LayerCount - 1;
+ for (;;)
+ {
+ sorted_layer_array SortEntry = SortedLayerStart[i];
+ uint32 Index_Physical = SortEntry.Block_Layer_Index;
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
+ History_Action_Swap(Memory, F_Layers, sizeof(Layer->Vertical_Offset), &Layer->Vertical_Offset);
+ if (Layer->IsSelected) {
+ if (State->DuplicateMode & sortflag_furthest)
+ Layer->Vertical_Offset = FurthestMark;
+ FauxIncrement += Direction;
+ if (State->DuplicateMode & sortflag_furthest && !(State->DuplicateMode & sortflag_up))
+ Layer->Vertical_Offset += 1;
+ }
+ Layer->Vertical_Offset -= FauxIncrement;
+ int a = 0;
+ if ((Direction > 0) ? !(i < LayerCount) : (i <= 0))
+ break;
+ i += Direction;
+ }
}
}
}
diff --git a/src/imgui_ui.cpp b/src/imgui_ui.cpp
index 546392a..aa09bfb 100644
--- a/src/imgui_ui.cpp
+++ b/src/imgui_ui.cpp
@@ -131,6 +131,15 @@ ImGui_ColorPanel(project_data *File, project_state *State, ui *UI, memory *Memor
UI->AltColor = Temp;
}
+ const char *Name = (State->DuplicateMode & sortflag_up) ? "Up" : "Down";
+ if (ImGui::MenuItem(Name, NULL)) {
+ State->DuplicateMode ^= sortflag_up;
+ }
+ Name = (State->DuplicateMode & sortflag_furthest) ? "Furthest" : "Above";
+ if (ImGui::MenuItem(Name, NULL)) {
+ State->DuplicateMode ^= sortflag_furthest;
+ }
+
if (State->Tool == tool_default) {
if (ImGui::MenuItem("All", NULL, (State->SelectionMode == 0))) {
State->SelectionMode = 0;
diff --git a/src/imgui_ui_viewport.cpp b/src/imgui_ui_viewport.cpp
index b2830de..0cfc7da 100644
--- a/src/imgui_ui_viewport.cpp
+++ b/src/imgui_ui_viewport.cpp
@@ -1301,7 +1301,7 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory,
State->Interact_Active = interact_type_none;
State->Interact_Modifier = 0;
v2 Offset = V2(State->Interact_Offset[0], State->Interact_Offset[1]);
- Project_Layer_Duplicate(File, State, Memory, SortedCompArray, SortedLayerArray, Offset, 1, io.KeyCtrl);
+ Project_Layer_Duplicate(File, State, Memory, SortedCompArray, SortedLayerArray, Offset, io.KeyCtrl);
State->Interact_Dup_Previous[0] = State->Interact_Offset[0];
State->Interact_Dup_Previous[1] = State->Interact_Offset[1];
State->Interact_Offset[0] = 0;
diff --git a/src/include/all.h b/src/include/all.h
index 603ba1d..8182b26 100644
--- a/src/include/all.h
+++ b/src/include/all.h
@@ -136,7 +136,7 @@ Property_IsGraphSelected(memory *Memory, uint16 *Block_Bezier_Index, uint16 *Arr
static void
Project_Layer_Duplicate(project_data *File, project_state *State, memory *Memory,
- sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, v2 Offset, bool32 FakeOnly, bool32 NewPrecomp);
+ sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, v2 Offset, bool32 NewPrecomp);
static void
Project_ShapeLayer_New(project_data *File, project_state *State, memory *Memory);
diff --git a/src/include/main.h b/src/include/main.h
index 68df39d..8debbb0 100644
--- a/src/include/main.h
+++ b/src/include/main.h
@@ -480,6 +480,12 @@ enum imgui_popups
popup_keybinds
};
+enum option_sortflag
+{
+ sortflag_up = 1 << 0,
+ sortflag_furthest = 1 << 1
+};
+
struct project_state
{
bool32 UpdateKeyframes = 0;
@@ -488,6 +494,7 @@ struct project_state
bool32 DebugDisableCache = 1;
// TODO(fox): Group inconsequential state UI into one thing?
+ bool32 DuplicateMode = sortflag_furthest | sortflag_up;
bool32 ShapeMode = 0;
bool32 ViewportEnabled = 0;
bool32 SelectionMode = 1;
diff --git a/src/main.cpp b/src/main.cpp
index 894238a..42c07a9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1505,7 +1505,15 @@ int main(int argc, char *argv[]) {
} break;
case hotkey_duplicatelayer:
{
- State_ExecuteAtEnd = 2;
+ State->Interact_Active = interact_type_viewport_duplicate;
+ sorted_file Sorted = File_Sort_Push(File, State, &Memory);
+ History_Entry_Commit(&Memory, "Duplicate layers");
+ v2 Offset = V2(State->Interact_Dup_Previous[0], State->Interact_Dup_Previous[1]);
+ Project_Layer_Duplicate(File, State, &Memory, Sorted.CompArray, Sorted.LayerArray, Offset, io.KeyCtrl);
+ State->Interact_Transform = {};
+ History_Entry_End(&Memory);
+ File_Sort_Pop(&Memory, Sorted.Layer_SortSize, Sorted.Property_SortSize, Sorted.Source_SortSize);
+ State->Interact_Active = interact_type_none;
} break;
case hotkey_deletelayer:
{
@@ -1634,13 +1642,7 @@ int main(int argc, char *argv[]) {
if (State_ExecuteAtEnd) {
if (State_ExecuteAtEnd == 1) {
Project_ShapeLayer_New(File, State, &Memory);
- } else if (State_ExecuteAtEnd == 2) {
- History_Entry_Commit(&Memory, "Duplicate layers");
- v2 Offset = V2(State->Interact_Dup_Previous[0], State->Interact_Dup_Previous[1]);
- Project_Layer_Duplicate(File, State, &Memory, Sorted.CompArray, Sorted.LayerArray, Offset, 0, io.KeyCtrl);
- State->Interact_Transform = {};
- History_Entry_End(&Memory);
- }
+ }
State->UpdateFrame = true;
}
diff --git a/src/sorted.cpp b/src/sorted.cpp
index 3ecd69e..c039c08 100644
--- a/src/sorted.cpp
+++ b/src/sorted.cpp
@@ -292,36 +292,66 @@ Layer_SortAll(project_state *State, memory *Memory,
if (!SortedCompStart->LayerCount)
continue;
sorted_layer_array *SortedLayerStart = Sorted_GetLayerStart(LayerArrayStart, CompArrayStart, c);
- int i = 0;
+ int Direction = (State->DuplicateMode & sortflag_up) ? 1 : -1;
+ int Furthest = (State->DuplicateMode & sortflag_furthest) ? 1 : 0;
+ if (Furthest) { Direction *= -1; }
+ int i = (Direction > 0) ? 0 : SortedCompStart->LayerCount - 1;
int FauxIncrement = 0;
- while (i < SortedCompStart->LayerCount) {
- int Idx = i + FauxIncrement;
+ int FurthestMark = -1;
+ for (;;) {
+ int Idx = i + ((Direction > 0) ? FauxIncrement : 0);
+ if (FauxIncrement && Furthest && (Direction > 0)) {
+ Idx = i + SortedCompStart->FakeLayerCount;
+ }
sorted_layer_array *LayerEntry = &SortedLayerStart[Idx];
block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, LayerEntry->Block_Layer_Index);
if (Layer->IsSelected & 0x01) {
- // Sort_OffsetDupes(Memory, SortedLayerStart, Layer, LayerEntry, i, FauxIncrement, SortedCompStart->LayerCount, 1);
- uint8 *Address_Start = (uint8 *)(LayerEntry);
- uint8 *Address_End = (uint8 *)(&SortedLayerStart[SortedCompStart->LayerCount + FauxIncrement]) - 1;
- Assert(SortedCompStart->CurrentSortIndex != (SortedCompStart->LayerCount + SortedCompStart->FakeLayerCount));
- Arbitrary_ShiftData(Address_Start, Address_End, sizeof(sorted_layer_array), 1);
- sorted_layer_array *FakeLayerEntry = LayerEntry + 1;
- FakeLayerEntry->SortedOffset -= 1;
- Assert(FakeLayerEntry->Block_Layer_Index == LayerEntry->Block_Layer_Index);
- FakeLayerEntry->IsFake = true;
- FauxIncrement++;
-
- sorted_layer_array *PrevLayerEntry = FakeLayerEntry;
- for (int a = i+1; a < SortedCompStart->LayerCount; a++) {
- int NextIdx = a + FauxIncrement;
- sorted_layer_array *NextLayerEntry = &SortedLayerStart[NextIdx];
- if (NextLayerEntry->SortedOffset == PrevLayerEntry->SortedOffset)
- NextLayerEntry->SortedOffset -= 1;
- else
- break;
- PrevLayerEntry = NextLayerEntry;
+ if (Furthest) {
+ if (FauxIncrement == 0) {
+ uint8 *Address_Start = (uint8 *)(LayerEntry);
+ uint8 *Address_End = (uint8 *)(&SortedLayerStart[SortedCompStart->LayerCount + FauxIncrement]) - 1;
+ Assert(SortedCompStart->CurrentSortIndex != (SortedCompStart->LayerCount + SortedCompStart->FakeLayerCount));
+ Arbitrary_ShiftData(Address_Start, Address_End, sizeof(sorted_layer_array) * SortedCompStart->FakeLayerCount, 1);
+ FurthestMark = i + ((Direction > 0) ? 0 : -Direction);
+ }
+ sorted_layer_array *FakeLayerEntry = &SortedLayerStart[FurthestMark + (FauxIncrement * ((Direction > 0) ? 1 : -Direction))];
+ *FakeLayerEntry = *LayerEntry;
+ FakeLayerEntry->IsFake = true;
+ FauxIncrement++;
+ } else {
+ uint8 *Address_Start = (uint8 *)(LayerEntry);
+ uint8 *Address_End = (uint8 *)(&SortedLayerStart[SortedCompStart->LayerCount + FauxIncrement]) - 1;
+ Assert(SortedCompStart->CurrentSortIndex != (SortedCompStart->LayerCount + SortedCompStart->FakeLayerCount));
+ Arbitrary_ShiftData(Address_Start, Address_End, sizeof(sorted_layer_array), 1);
+ sorted_layer_array *FakeLayerEntry = LayerEntry + ((Direction > 0) ? 1 : 0);
+ Assert(FakeLayerEntry->Block_Layer_Index == LayerEntry->Block_Layer_Index);
+ FakeLayerEntry->IsFake = true;
+ FauxIncrement++;
}
}
- i++;
+ if ((Direction > 0) ? !(i < SortedCompStart->LayerCount) : (i <= 0))
+ break;
+ i += Direction;
+ }
+ if (Furthest) { Direction *= -1; }
+ i = FauxIncrement = 0;
+ int LayerCount = SortedCompStart->LayerCount + SortedCompStart->FakeLayerCount;
+ FurthestMark = -1;
+ i = (Direction > 0) ? 0 : LayerCount - 1;
+ for (;;) {
+ sorted_layer_array *LayerEntry = &SortedLayerStart[i];
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, LayerEntry->Block_Layer_Index);
+ if (LayerEntry->IsFake) {
+ if (FurthestMark == -1)
+ FurthestMark = Layer->Vertical_Offset;
+ if (Furthest)
+ LayerEntry->SortedOffset = FurthestMark;
+ FauxIncrement += Direction;
+ }
+ LayerEntry->SortedOffset -= FauxIncrement;
+ if ((Direction > 0) ? !(i < LayerCount) : (i <= 0))
+ break;
+ i += Direction;
}
}
}