summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--createcalls.cpp539
-rw-r--r--functions.h6
-rw-r--r--imgui_helper_widgets.cpp18
-rw-r--r--lib/base64.c189
-rw-r--r--lib/base64.h17
-rw-r--r--main.cpp235
-rw-r--r--main.h75
-rw-r--r--memory.cpp42
-rw-r--r--my_imgui_widgets.cpp596
-rw-r--r--prenderer.cpp665
-rw-r--r--stable_diffusion.cpp28
-rw-r--r--stable_diffusion.h25
-rw-r--r--strings.cpp2
-rw-r--r--threading.cpp66
14 files changed, 1568 insertions, 935 deletions
diff --git a/createcalls.cpp b/createcalls.cpp
index 01f1caa..85faa3c 100644
--- a/createcalls.cpp
+++ b/createcalls.cpp
@@ -10,7 +10,7 @@ Source_Generate_Blank(project_data *File, project_state *State, memory *Memory,
{
Assert(File->Source_Count < MAX_SOURCES);
uint16 Index = Memory_Block_AllocateNew(Memory, F_Sources);
- block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Index);
+ block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Index, 0);
Source->Occupied = 1;
Source->Width = Width;
Source->Height = Height;
@@ -46,7 +46,7 @@ Source_Generate(project_data *File, project_state *State, memory *Memory, void *
bool32 IsVideo = 0;
if (Source_IsFileSupported((char *)TempString, &IsVideo)) {
uint16 Index = Memory_Block_AllocateNew(Memory, F_Sources);
- block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Index);
+ block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Index, 0);
History_Entry_Commit(Memory, "Add source");
History_Action_Block_Swap(Memory, F_Sources, Source);
@@ -74,27 +74,24 @@ Bezier_LookupAddress(memory *Memory, property_channel *Property, uint16 Index)
return &Bezier->Point[Index];
}
-/*
-if (State->Interact_Active == interact_type_keyframe_rotate) {
- ImVec2 Keyframe_LocalPos_Ratio = (V2(Keyframe_LocalPos_[0]) - ImVec2(0, GraphInfo.MinVal)) * ImVec2(Increment.x, Y_Increment);
- ImVec2 Keyframe_ScreenPos = Layer_ScreenPos_Min + ((ImVec2(1, -1) * Keyframe_LocalPos_Ratio + ImVec2(0, 0.5)) * TimelineZoomSize) + ImVec2(0, Layer_ScreenSize.y/2);
- real32 Slope_Old = (Keyframe_ScreenPos.y - State->Interact_Offset[3]) / (Keyframe_ScreenPos.x - State->Interact_Offset[2]);
- real32 Slope_New = (Keyframe_ScreenPos.y - io.MousePos.y) / (Keyframe_ScreenPos.x - io.MousePos.x);
- State->Interact_Offset[0] = atan((Slope_Old - Slope_New) / (1 + Slope_Old * Slope_New));
- DebugWatchVar("Rotation: ", &State->Interact_Offset[0], d_float);
-}
-*/
-// Keyframe_Interact_Evaluate(Memory, State, Point->IsSelected, Point->Pos, Keyframe_LocalPos_);
-
-
+// NOTE(fox): It's not required for the Y to be set correctly in i.e. sorting.
static void
-Bezier_EvaluateValue(project_state *State, bezier_point *PointAddress, v2 *Pos)
+Bezier_EvaluateValue(project_state *State, bezier_point *PointAddress, v2 *Pos, real32 GraphZoomHeight = 1, real32 Y_Increment = 1)
{
Pos[0] = PointAddress->Pos[0];
Pos[1] = PointAddress->Pos[1];
Pos[2] = PointAddress->Pos[2];
- if (State->Interact_Active == interact_type_keyframe_move && PointAddress->IsSelected) {
- Pos[0].x += (int32)State->Interact_Offset[0];
+ if (PointAddress->IsSelected) {
+ if (State->Interact_Active == interact_type_keyframe_move) {
+ Pos[PointAddress->IsSelected - 1].x += (int32)State->Interact_Offset[0];
+ Pos[PointAddress->IsSelected - 1].y -= (State->Interact_Offset[1] / GraphZoomHeight / Y_Increment);
+ } else if (State->Interact_Active == interact_type_keyframe_scale) {
+ Pos[1].x += State->Interact_Offset[0];
+ Pos[2].x -= State->Interact_Offset[0];
+ } else if (State->Interact_Active == interact_type_keyframe_rotate) {
+ // how do I do this??
+ Assert(0);
+ }
}
}
@@ -125,36 +122,17 @@ Bezier_Add(memory *Memory, property_channel *Property, bezier_point PointData)
static property_channel
-Property_InitFloat(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPERTY_REAL_MIN, real32 MaxVal = PROPERTY_REAL_MAX) { property_channel Property = {};
+Property_InitFloat(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPERTY_REAL_MIN, real32 MaxVal = PROPERTY_REAL_MAX, bool32 AlwaysInteger = 0) {
+ property_channel Property = {};
Property.Name = Name;
Property.CurrentValue = Val;
Property.MinVal = MinVal;
Property.MaxVal = MaxVal;
+ Property.AlwaysInteger = AlwaysInteger;
Property.ScrubVal = ScrubVal;
return Property;
}
-static void
-Keyframe_Interact_Evaluate(memory *Memory, project_state *State, uint8 IsSelected, v2 Pos_Initial[3], v2 Pos_New[3])
-{
- /*
- Assert(Pos_New[0].y == Pos_Initial[0].y);
- if (State->Interact_Active == interact_type_keyframe_move) {
- Pos_New[0].x = Pos_New[0].x + Offset.x;
- Pos_New[0].y = Pos_New[0].y + Offset.y;
- } else if (State->Interact_Active == interact_type_keyframe_scale) {
- Pos_New[1].x += (IsSelected - 1 == 0 || IsSelected - 1 == 1) ? Offset.x : 0;
- Pos_New[2].x -= (IsSelected - 1 == 0 || IsSelected - 1 == 2) ? Offset.x : 0;
- } else if (State->Interact_Active == interact_type_keyframe_rotate) {
- real32 Rad = State->Interact_Offset[0];
- v2 XAxis = V2(8, 8) * V2(cos(Rad), sin(Rad));
- v2 YAxis = V2(sin(Rad), -cos(Rad));
- Pos_New[2].x += XAxis.x + XAxis.y;
- Pos_New[2].y += YAxis.x + YAxis.y;
- }
- */
-}
-
static block_composition *
Precomp_Init(project_data *File, memory *Memory)
{
@@ -212,13 +190,13 @@ Layer_Select(memory *Memory, project_state *State, int32 i)
// State->RecentSelectionType = selection_layer;
}
-// TODO(fox): Precomps!
-void Layer_DeselectAll(memory *Memory, uint32 LayerCount) {
- for (uint32 i = 0; i < LayerCount; i++) {
+void Layer_DeselectAll(project_data *File, project_state *State, memory *Memory) {
+ int h = 0, c = 0, i = 0;
+ while (Block_Loop(Memory, F_Sources, File->Layer_Count, &h, &c, &i)) {
block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i);
- if (Layer->IsSelected)
- Layer->IsSelected = false;
+ Layer->IsSelected = false;
}
+ State->MostRecentlySelectedLayer = -1;
}
void Source_DeselectAll(project_data *File, memory *Memory)
@@ -230,6 +208,81 @@ void Source_DeselectAll(project_data *File, memory *Memory)
}
}
+void Clipboard_Paste(project_data *File, project_state *State, memory *Memory, sorted_layer *SortedLayerArray)
+{
+ clipboard_contents *Contents = (clipboard_contents *)State->ClipboardBuffer;
+ uint64 ClipboardPos = sizeof(clipboard_contents);
+ ClipboardPos = sizeof(clipboard_contents);
+ int h = 0, c = 0, i = 0;
+ block_layer *Layer;
+ clipboard_channel *Channel;
+ int b = 0;
+ while (b < Contents->ChannelCount) {
+ Channel = &Contents->Channel[b];
+ while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i))
+ {
+ Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i);
+ if (Layer->IsSelected)
+ break;
+ }
+ // NOTE(fox): This loop assumes all layers and the clipboard have
+ // channels laid out in the same way!
+ for (int h = 0; h < AmountOf(Layer->Property); h++) {
+ property_channel *Property = &Layer->Property[h];
+ if (Property->Name == Channel->Name) {
+ for (int p = 0; p < Channel->KeyframeCount; p++) {
+ bezier_point PointData = *(bezier_point *)((uint8 *)State->ClipboardBuffer + ClipboardPos);
+ Bezier_Add(Memory, Property, PointData);
+ ClipboardPos += sizeof(bezier_point);
+ }
+ b++;
+ Channel = &Contents->Channel[b];
+ }
+ }
+ }
+}
+
+
+void Clipboard_Store(project_data *File, project_state *State, memory *Memory, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray)
+{
+ // TODO(fox): Multi-precomp support!
+ int LocalOffset = 0;
+ clipboard_contents *Contents = (clipboard_contents *)State->ClipboardBuffer;
+ *Contents = {};
+ uint64 ClipboardPos = sizeof(clipboard_contents);
+ // for (int i = SortedCompInfo.LayerCount - 1; i >= 0; i--)
+ Assert(0);
+ for (int i = 10; i >= 0; i--)
+ {
+ sorted_layer SortEntry = {}; // SortedLayerInfo[i];
+ uint32 Index_Physical = SortEntry.Block_Layer_Index;
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
+ for (int h = 0; h < AmountOf(Layer->Property); h++) {
+ property_channel *Property = &Layer->Property[h];
+ if (Property->IsToggled || Layer->IsSelected) {
+ sorted_property_info *InfoLocation = SortedPropertyInfo + (i * 7) + h;
+ uint16 *ArrayLocation = SortedPropertyArray + (i * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK);
+ clipboard_channel *Channel = &Contents->Channel[Contents->ChannelCount];
+ for (int p = 0; p < Property->Keyframe_Count; p++) {
+ bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[p]);
+ if (PointAddress->IsSelected) {
+ Arbitrary_WriteInto((uint8 *)PointAddress, (uint8 *)State->ClipboardBuffer + ClipboardPos, sizeof(bezier_point));
+ ClipboardPos += sizeof(bezier_point);
+ Channel->KeyframeCount++;
+ }
+ }
+ if (Channel->KeyframeCount) {
+ if (!LocalOffset)
+ LocalOffset = i;
+ Contents->ChannelCount++;
+ Channel->LayerOffset = LocalOffset - i;
+ Channel->Name = Property->Name;
+ }
+ }
+ }
+ }
+}
+
static sorted_layer *
Layer_GetSortedArray(sorted_layer *LayerArrayStart, sorted_comp_info *SortedCompStart, uint32 TargetComp)
{
@@ -288,41 +341,67 @@ void Layer_RecursiveDeselect(memory *Memory, sorted_comp_info *SortedCompArray,
}
}
-void Property_MinMax(memory *Memory, project_state *State, property_channel *Property, uint16 *ArrayLocation, v2 *Min, v2 *Max)
+void Property_MinMax_X(memory *Memory, project_state *State, property_channel *Property,
+ uint16 *ArrayLocation, real32 *Min, real32 *Max)
{
v2 FirstPointPos[3];
bezier_point *FirstPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[0]);
Bezier_EvaluateValue(State, FirstPointAddress, FirstPointPos);
- Min->x = FirstPointPos[0].x;
+ *Min = FirstPointPos[0].x;
v2 LastPointPos[3];
bezier_point *LastPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[Property->Keyframe_Count - 1]);
Bezier_EvaluateValue(State, LastPointAddress, LastPointPos);
- Max->x = LastPointPos[0].x;
- int32 Offset = (State->Interact_Active == interact_type_keyframe_move) ? (int32)State->Interact_Offset[0] : 0;
- real32 MinY = FLT_MAX;
- real32 MaxY = FLT_MIN;
- for (int p = 0; p < Property->Keyframe_Count; p++) {
- bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[p]);
- MinY = (MinY < PointAddress->Pos[0].y) ? MinY : PointAddress->Pos[0].y;
- MaxY = (MaxY > PointAddress->Pos[0].y) ? MaxY : PointAddress->Pos[0].y;
+ *Max = LastPointPos[0].x;
+}
+void Property_MinMax_Y(memory *Memory, project_state *State, property_channel *Property,
+ sorted_property_info *PropertyInfo, real32 *Min, real32 *Max, bool32 Evaluate = 1)
+{
+ if (Evaluate) {
+ v2 MinYPointPos[3];
+ bezier_point *MinYPointAddress = Bezier_LookupAddress(Memory, Property, PropertyInfo->MinYIndex);
+ Bezier_EvaluateValue(State, MinYPointAddress, MinYPointPos);
+ *Min = MinYPointPos[0].y;
+ v2 MaxYPointPos[3];
+ bezier_point *MaxYPointAddress = Bezier_LookupAddress(Memory, Property, PropertyInfo->MaxYIndex);
+ Bezier_EvaluateValue(State, MaxYPointAddress, MaxYPointPos);
+ *Max = MaxYPointPos[0].y;
+ } else {
+ bezier_point *MinYPointAddress = Bezier_LookupAddress(Memory, Property, PropertyInfo->MinYIndex);
+ *Min = MinYPointAddress->Pos[0].y;
+ bezier_point *MaxYPointAddress = Bezier_LookupAddress(Memory, Property, PropertyInfo->MaxYIndex);
+ *Max = MaxYPointAddress->Pos[0].y;
}
- Min->y = MinY;
- Max->y = MaxY;
}
// The sorting algorithm is straightforward: read every point, evaluate it if
// it's currently being interacted with by the user, record index in a sorted
// list, and repeat, shiftig the list as necessary.
-void Property_SortAll(memory *Memory, project_state *State, property_channel *Property, uint16 *PropertyArrayStart)
+void Property_SortAll(memory *Memory, project_state *State, property_channel *Property, sorted_property_info *PropertyInfo, uint16 *PropertyArrayStart)
{
int h = 0, c = 0, i = 0;
uint32 CurrentSortIndex = 0;
+ real32 MinY = FLT_MAX;
+ real32 MaxY = FLT_MIN;
int32 Offset = (State->Interact_Active == interact_type_keyframe_move) ? (int32)State->Interact_Offset[0] : 0;
while (Block_Loop(Memory, Property, Property->Keyframe_Count, &h, &c, &i)) {
v2 PointPos[3];
bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, i);
+
+ if (PointAddress->IsSelected)
+ PropertyInfo->IsGraphSelected = true;
+
Bezier_EvaluateValue(State, PointAddress, PointPos);
+
+ if (MinY > PointAddress->Pos[0].y) {
+ MinY = PointAddress->Pos[0].y;
+ PropertyInfo->MinYIndex = i;
+ }
+ if (MaxY < PointAddress->Pos[0].y) {
+ MaxY = PointAddress->Pos[0].y;
+ PropertyInfo->MaxYIndex = i;
+ }
+
uint32 SortedIndex_Playhead = 0;
while (SortedIndex_Playhead < CurrentSortIndex) {
uint16 TestPointEntry = PropertyArrayStart[SortedIndex_Playhead];
@@ -347,7 +426,26 @@ void Property_SortAll(memory *Memory, project_state *State, property_channel *Pr
}
}
-void Layer_Sort_CheckPrev(memory *Memory, int i, int Direction, sorted_layer *SortedLayerInfo, sorted_comp_info SortedCompInfo, int *EntriesPassed, sorted_layer *LayerEntry)
+void Property_DeselectAll(project_data *File, memory *Memory, uint16 *SortedPropertyArray)
+{
+ int h = 0, c = 0, i = 0;
+ while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) {
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i);
+ if (!Layer->IsSelected)
+ continue;
+ for (int h = 0; h < AmountOf(Layer->Property); h++) {
+ property_channel *Property = &Layer->Property[h];
+ uint16 *ArrayLocation = SortedPropertyArray + (i * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK);
+ for (int p = 0; p < Property->Keyframe_Count; p++) {
+ int k = ArrayLocation[p];
+ bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, k);
+ PointAddress->IsSelected = 0;
+ }
+ }
+ }
+}
+
+void Layer_Sort_CheckPrev(memory *Memory, int i, int Direction, sorted_layer *SortedLayerInfo, sorted_comp_info SortedCompInfo, int *EntriesPassed, sorted_layer *LayerEntry, bool32 AltMethod)
{
int PrevOffsetIndex = i + Direction + (*EntriesPassed * Direction);
bool32 OutOfBounds = (Direction > 0) ? (PrevOffsetIndex > (SortedCompInfo.LayerCount - 1)) : (PrevOffsetIndex < 0);
@@ -355,18 +453,46 @@ void Layer_Sort_CheckPrev(memory *Memory, int i, int Direction, sorted_layer *So
sorted_layer *PrevLayerEntry = &SortedLayerInfo[PrevOffsetIndex];
real32 PrevOffset = PrevLayerEntry->SortedOffset;
if (PrevOffset == (LayerEntry->SortedOffset - Direction)) {
- LayerEntry->SortedOffset -= Direction;
(*EntriesPassed)++;
- Layer_Sort_CheckPrev(Memory, i, Direction, SortedLayerInfo, SortedCompInfo, EntriesPassed, LayerEntry);
+ if (!AltMethod) {
+ PrevLayerEntry->SortedOffset += Direction;
+ } else {
+ LayerEntry->SortedOffset -= Direction;
+ Layer_Sort_CheckPrev(Memory, i, Direction, SortedLayerInfo, SortedCompInfo, EntriesPassed, LayerEntry, AltMethod);
+ }
}
}
}
+void Layer_Evaluate_Display(block_layer *Layer, sorted_layer *LayerArrayStart, sorted_comp_info *CompStart, sorted_layer *SortedLayerInfo, int i, real32 *Offset)
+{
+ int ExtraPad = 1;
+ for (int h = 0; h < AmountOf(Layer->Property); h++) {
+ property_channel *Property = &Layer->Property[h];
+ if (Property->IsToggled) {
+ *Offset += 1 + ExtraPad;
+ ExtraPad = 0;
+ }
+ }
+ /*
+ if (Layer->Precomp_Toggled) {
+ Assert(Layer->IsPrecomp);
+ sorted_comp_info *Layer_SortedCompInfo = &CompStart[Layer->Block_Source_Index];
+ sorted_layer *Layer_SortedLayerInfo = Layer_GetSortedArray(LayerArrayStart, CompStart, Layer->Block_Source_Index);
+ sorted_layer *TopLayerEntry = &Layer_SortedLayerInfo[0];
+ sorted_layer *BottomLayerEntry = &Layer_SortedLayerInfo[Layer_SortedCompInfo->LayerCount - 1];
+ *Offset += TopLayerEntry->SortedOffset - BottomLayerEntry->SortedOffset + 2;
+ }
+ */
+}
+
// The first loop is for counting how many layers are in each precomp, the
// second is for sorting the layers by offset, and the third is for applying
// interactivity if the user is moving any layers.
-void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sorted_layer *LayerArrayStart, sorted_comp_info *CompStart, uint16 *SortedPropertyArray, uint32 LayerCount, uint32 CompCount)
+void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sorted_layer *LayerArrayStart,
+ sorted_comp_info *CompStart, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray,
+ uint32 LayerCount, uint32 CompCount)
{
int h = 0, c = 0, i = 0;
while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) {
@@ -376,19 +502,19 @@ void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sor
for (int h = 0; h < AmountOf(Layer->Property); h++) {
property_channel *Property = &Layer->Property[h];
if (Property->Block_Bezier_Count) {
+ sorted_property_info *InfoLocation = SortedPropertyInfo + (i * 7) + h;
uint16 *ArrayLocation = SortedPropertyArray + (i * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK);
- Property_SortAll(Memory, State, Property, ArrayLocation);
+ Property_SortAll(Memory, State, Property, InfoLocation, ArrayLocation);
}
}
}
h = 0, c = 0, i = 0;
- uint32 CurrentSortIndex = 0;
while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) {
block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i);
sorted_comp_info *SortedCompInfo = &CompStart[Layer->Block_Composition_Index];
sorted_layer *SortedLayerInfo = Layer_GetSortedArray(LayerArrayStart, CompStart, Layer->Block_Composition_Index);
uint32 SortedIndex_Playhead = 0;
- while (SortedIndex_Playhead < CurrentSortIndex) {
+ while (SortedIndex_Playhead < SortedCompInfo->CurrentSortIndex) {
sorted_layer LayerEntry = SortedLayerInfo[SortedIndex_Playhead];
block_layer *TestLayer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, LayerEntry.Block_Layer_Index);
if (-Layer->Vertical_Offset < -TestLayer->Vertical_Offset) {
@@ -397,16 +523,16 @@ void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sor
SortedIndex_Playhead++;
}
}
- if (SortedIndex_Playhead != CurrentSortIndex) {
+ if (SortedIndex_Playhead != SortedCompInfo->CurrentSortIndex) {
uint8 *Address_Start = (uint8 *)(SortedLayerInfo + SortedIndex_Playhead);
- uint8 *Address_End = (uint8 *)(SortedLayerInfo + CurrentSortIndex) - 1;
- Assert(CurrentSortIndex != SortedCompInfo->LayerCount);
+ uint8 *Address_End = (uint8 *)(SortedLayerInfo + SortedCompInfo->CurrentSortIndex) - 1;
+ Assert(SortedCompInfo->CurrentSortIndex != SortedCompInfo->LayerCount);
Arbitrary_ShiftData(Address_Start, Address_End, sizeof(sorted_layer), 1);
}
sorted_layer *LayerEntry = SortedLayerInfo + SortedIndex_Playhead;
LayerEntry->Block_Layer_Index = i;
LayerEntry->SortedOffset = Layer->Vertical_Offset;
- CurrentSortIndex++;
+ SortedCompInfo->CurrentSortIndex++;
}
if (State->Interact_Active == interact_type_layer_move) {
int32 Offset = (int32)State->Interact_Offset[1];
@@ -426,7 +552,7 @@ void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sor
if (Layer->IsSelected) {
int32 SpacesToMove = Offset * Direction;
while (SpacesToMove) {
- Layer_Sort_CheckPrev(Memory, i, Direction, SortedLayerInfo, *SortedCompInfo, &EntriesPassed, LayerEntry);
+ Layer_Sort_CheckPrev(Memory, i, Direction, SortedLayerInfo, *SortedCompInfo, &EntriesPassed, LayerEntry, 0);
LayerEntry->SortedOffset -= Direction;
SpacesToMove--;
}
@@ -465,7 +591,7 @@ sorted_file File_Sort_Push(project_data *File, project_state *State, memory *Mem
Sorted.PropertyInfo = (sorted_property_info *)Property_SortedArray;
Sorted.PropertyArray = (uint16 *)((uint8 *)Property_SortedArray + PropertyInfoSize);
- Layer_SortAll(File, State, Memory, Sorted.LayerArray, Sorted.CompArray, Sorted.PropertyArray, File->Layer_Count, File->Comp_Count);
+ Layer_SortAll(File, State, Memory, Sorted.LayerArray, Sorted.CompArray, Sorted.PropertyInfo, Sorted.PropertyArray, File->Layer_Count, File->Comp_Count);
return Sorted;
}
@@ -486,6 +612,7 @@ Layer_Delete(project_data *File, memory *Memory, uint32 Index)
File->Layer_Count--;
}
+
block_layer * Layer_Init(project_data *File, memory *Memory)
{
if (File->Layer_Count + 1 > MAX_LAYERS) {
@@ -498,7 +625,7 @@ block_layer * Layer_Init(project_data *File, memory *Memory)
Layer->Occupied = 1;
Layer->Block_String_Index = Memory_Block_AllocateNew(Memory, F_Strings);
- block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Layer->Block_String_Index);
+ block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Layer->Block_String_Index, 0);
sprintf(String->Char, "Layer %i", File->Layer_Count + 1); // CSbros...
String->Occupied = 1;
@@ -509,7 +636,7 @@ block_layer * Layer_Init(project_data *File, memory *Memory)
Layer->scale = Property_InitFloat("Scale", 1.0f, 0.005f);
Layer->rotation = Property_InitFloat("Rotation", 0.0f, 1.0f);
Layer->opacity = Property_InitFloat("Opacity", 1.0f, 0.005f, 0.0f, 1.0f);
- Layer->time = Property_InitFloat("Frame Number", 0.0f, 1.0f, 0, 100000);
+ Layer->time = Property_InitFloat("Frame Number", 0.0f, 1.0f, 0, 100000, 1);
Layer->IsVisible = 1;
@@ -546,6 +673,7 @@ void Source_UICreateButton(project_data *File, project_state *State, memory *Mem
Layer->x.CurrentValue = Source->Width / 2;
Layer->y.CurrentValue = Source->Height / 2;
Layer->Vertical_Offset = TopOffset-1;
+ Layer->Frame_Start = Comp->Frame_Start;
Layer->Frame_End = Comp->Frame_End;
TopOffset--;
}
@@ -556,6 +684,56 @@ void Source_UICreateButton(project_data *File, project_state *State, memory *Mem
Source_DeselectAll(File, Memory);
}
+void Precomp_UICreateButton(project_data *File, project_state *State, memory *Memory, uint16 CompIndex,
+ sorted_comp_info SortedCompInfo, sorted_layer *SortedLayerInfo)
+{
+ block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, CompIndex);
+ History_Entry_Commit(Memory, "Pre-compose layer");
+ block_composition *NewComp = Precomp_Init(File, Memory);
+ NewComp->Width = Comp->Width;
+ NewComp->Height = Comp->Height;
+ NewComp->FPS = Comp->FPS;
+ NewComp->BytesPerPixel = Comp->BytesPerPixel;
+ NewComp->Frame_Count = Comp->Frame_Count;
+ NewComp->Frame_Start = Comp->Frame_Start;
+ NewComp->Frame_End = Comp->Frame_End;
+ int32 TopOffset = 0;
+ for (int i = SortedCompInfo.LayerCount - 1; i >= 0; i--)
+ {
+ sorted_layer SortEntry = SortedLayerInfo[i];
+ uint32 Index_Physical = SortEntry.Block_Layer_Index;
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
+ if (Layer->IsSelected) {
+ TopOffset = Layer->Vertical_Offset;
+ break;
+ }
+ }
+ for (int i = SortedCompInfo.LayerCount - 1; i >= 0; i--)
+ {
+ sorted_layer SortEntry = SortedLayerInfo[i];
+ uint32 Index_Physical = SortEntry.Block_Layer_Index;
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
+ if (Layer->IsSelected) {
+ History_Action_Swap(Memory, F_File, sizeof(Layer->Block_Composition_Index), &Layer->Block_Composition_Index);
+ Layer->Block_Composition_Index = File->Comp_Count - 1;
+ }
+ }
+ block_layer *PrecompLayer = Layer_Init(File, Memory);
+ bezier_point Point0 = { 1, {0, 0, 1, 0, 1, 0}, interpolation_type_linear, 0, {0, 0, 0}, 0 };
+ bezier_point Point1 = { 1, {(real32)NewComp->Frame_End, (real32)NewComp->Frame_End, 1, 0, 1, 0}, interpolation_type_linear, 0, {0, 0, 0}, 0 };
+ Bezier_Add(Memory, &PrecompLayer->time, Point0);
+ Bezier_Add(Memory, &PrecompLayer->time, Point1);
+ PrecompLayer->IsPrecomp = true;
+ PrecompLayer->Block_Source_Index = File->Comp_Count - 1;
+ PrecompLayer->Block_Composition_Index = CompIndex;
+ PrecompLayer->Vertical_Offset = TopOffset;
+ PrecompLayer->Frame_End = NewComp->Frame_End;
+ PrecompLayer->ColIndex = 3;
+ PrecompLayer->x.CurrentValue = Comp->Width/2;
+ PrecompLayer->y.CurrentValue = Comp->Height/2;
+ History_Entry_End(Memory);
+ State->UpdateFrame = true;
+}
// Helper for working with different bit depths.
@@ -592,16 +770,19 @@ State_BindBrushTexture(memory *Memory, brush_state *Brush, uint32 BytesPerPixel)
static void
Brush_CalcBitmapAlphaFromSize(memory *Memory, brush_state *Brush, uint32 BytesPerPixel)
{
- real32 BrushLength = Brush->Size;
- real32 BrushCenter = BrushLength / 2;
+ int32 BrushLength = Brush->Size;
+ if (BrushLength > 128) {
+ BrushLength = BrushLength + (16 - (BrushLength % 16));
+ }
+ real32 BrushCenter = (real32)BrushLength / 2;
real32 MaxLength = BrushCenter;
void *BrushAddress = Brush->PaintBuffer;
render_byte_info Byte = Bitmap_ByteInfo(BytesPerPixel);
- for (int Y = 0; Y < (int)BrushLength; Y++) {
- for (int X = 0; X < (int)BrushLength; X++) {
- uint8 *PixelAddress = (uint8 *)BrushAddress + (Y * BytesPerPixel*(int)BrushLength) + (X * BytesPerPixel);
+ for (int Y = 0; Y < BrushLength; Y++) {
+ for (int X = 0; X < BrushLength; X++) {
+ uint8 *PixelAddress = (uint8 *)BrushAddress + (Y * BytesPerPixel*BrushLength) + (X * BytesPerPixel);
uint32 *R_DestAddress = (uint32 *)(PixelAddress + Byte.ByteOffset*0);
// uint32 *G_DestAddress = (uint32 *)(PixelAddress + Byte.ByteOffset*1);
// uint32 *B_DestAddress = (uint32 *)(PixelAddress + Byte.ByteOffset*2);
@@ -616,18 +797,21 @@ Brush_CalcBitmapAlphaFromSize(memory *Memory, brush_state *Brush, uint32 BytesPe
}
}
-// TODO(fox): We could merge this exactly with the standard rendering code.
static void
-PaintTest(memory *Memory, block_source *Source, brush_state *Brush, void *Address, v2 LayerPos, uint32 BytesPerPixel, v4 Color)
+Brush_Info(brush_info *B, brush_state *Brush, block_source *Source, v2 LayerPos, v4 Color)
{
- uint32 BrushLength = (uint32)Brush->Size;
+ B->BrushLength = (uint32)Brush->Size;
+ if (B->BrushLength > 128) {
+ B->BrushLength = B->BrushLength + (16 - (B->BrushLength % 16));
+ }
rectangle RenderRegion = { 0, 0, Source->Width, Source->Height };
- rectangle BrushPos = { (int32)(LayerPos.x - (BrushLength / 2)),
- (int32)(LayerPos.y - (BrushLength / 2)),
- (int32)(LayerPos.x + (BrushLength / 2)),
- (int32)(LayerPos.y + (BrushLength / 2)) };
- rectangle LayerBounds = ClipRectangle(BrushPos, RenderRegion);
+ rectangle BrushPos = { (int32)(LayerPos.x - (B->BrushLength / 2)),
+ (int32)(LayerPos.y - (B->BrushLength / 2)),
+ (int32)(LayerPos.x + (B->BrushLength / 2)),
+ (int32)(LayerPos.y + (B->BrushLength / 2)) };
+
+ B->LayerBounds = ClipRectangle(BrushPos, RenderRegion);
if (BrushPos.Min.x < Brush->CacheBounds.Min.x)
Brush->CacheBounds.Min.x = BrushPos.Min.x;
@@ -638,68 +822,79 @@ PaintTest(memory *Memory, block_source *Source, brush_state *Brush, void *Addres
if (BrushPos.Max.y > Brush->CacheBounds.Max.y)
Brush->CacheBounds.Max.y = BrushPos.Max.y;
- uint32 LayerPitch = Source->Width*Source->BytesPerPixel;
- uint32 BrushPitch = (int)BrushLength * BytesPerPixel;
+ B->BytesPerPixel = 4;
+ B->SourceWidth = Source->Width;
+ B->SourceBytesPerPixel = Source->BytesPerPixel;
+
+ Assert(Source->BytesPerPixel == 4);
- render_byte_info LayerBits = Bitmap_ByteInfo(Source->BytesPerPixel);
- render_byte_info BrushBits = Bitmap_ByteInfo(BytesPerPixel);
+ B->LayerPitch = Source->Width*Source->BytesPerPixel;
+ B->BrushPitch = (int)B->BrushLength * B->BytesPerPixel;
- int32 ExtraX = 0;
- int32 ExtraY = 0;
+ B->LayerBits = Bitmap_ByteInfo(Source->BytesPerPixel);
+ B->BrushBits = Bitmap_ByteInfo(B->BytesPerPixel);
+
+ B->ExtraX = 0;
+ B->ExtraY = 0;
if (BrushPos.Min.x < 0) {
- ExtraX = BrushPos.Min.x;
+ B->ExtraX = BrushPos.Min.x;
}
if (BrushPos.Min.y < 0) {
- ExtraY = BrushPos.Min.y;
+ B->ExtraY = BrushPos.Min.y;
}
- void *BrushBuffer = Brush->PaintBuffer;
+ B->BrushBuffer = Brush->PaintBuffer;
// ImGui's color picker works in sRGB, so we need to convert to linear.
// real32 R_Brush = (Color.r >= 0.04045) ? pow((Color.r + 0.055) / (1 + 0.055), 2.4) : Color.r / 12.92;
// real32 G_Brush = (Color.g >= 0.04045) ? pow((Color.g + 0.055) / (1 + 0.055), 2.4) : Color.g / 12.92;
// real32 B_Brush = (Color.b >= 0.04045) ? pow((Color.b + 0.055) / (1 + 0.055), 2.4) : Color.b / 12.92;
// real32 A_Brush = (Color.a >= 0.04045) ? pow((Color.a + 0.055) / (1 + 0.055), 2.4) : Color.a / 12.92;
- real32 R_Brush = Color.r;
- real32 G_Brush = Color.g;
- real32 B_Brush = Color.b;
- real32 A_Brush = Color.a;
+ B->R_Brush = Color.r;
+ B->G_Brush = Color.g;
+ B->B_Brush = Color.b;
+ B->A_Brush = Color.a;
- uint8 *BrushRow = (uint8 *)BrushBuffer;
- for (int32 Y = LayerBounds.Min.y; Y < LayerBounds.Max.y; Y++) {
- for (int32 X = LayerBounds.Min.x; X < LayerBounds.Max.x; X++) {
+ B->BrushRow = (uint8 *)B->BrushBuffer;
+}
+
+static void
+PaintTest(brush_info B, void *Buffer, rectangle RenderRegion)
+{
+ for (int32 Y = RenderRegion.Min.y; Y < RenderRegion.Max.y; Y++) {
+ for (int32 X = RenderRegion.Min.x; X < RenderRegion.Max.x; X++) {
- uint32 Offset = Y*LayerPitch + X*Source->BytesPerPixel;
- uint8 *LayerPixel = (uint8 *)Address + Offset;
+ uint32 Offset = Y*B.LayerPitch + X*B.SourceBytesPerPixel;
+ uint8 *LayerPixel = (uint8 *)Buffer + Offset;
- uint32 *R_DestAddress = (uint32 *)(LayerPixel + LayerBits.ByteOffset * 0);
- uint32 *G_DestAddress = (uint32 *)(LayerPixel + LayerBits.ByteOffset * 1);
- uint32 *B_DestAddress = (uint32 *)(LayerPixel + LayerBits.ByteOffset * 2);
- uint32 *A_DestAddress = (uint32 *)(LayerPixel + LayerBits.ByteOffset * 3);
+ uint32 *R_DestAddress = (uint32 *)(LayerPixel + B.LayerBits.ByteOffset * 0);
+ uint32 *G_DestAddress = (uint32 *)(LayerPixel + B.LayerBits.ByteOffset * 1);
+ uint32 *B_DestAddress = (uint32 *)(LayerPixel + B.LayerBits.ByteOffset * 2);
+ uint32 *A_DestAddress = (uint32 *)(LayerPixel + B.LayerBits.ByteOffset * 3);
- real32 R_Layer = (real32)(*R_DestAddress & LayerBits.MaskPixel) * LayerBits.Normalized;
- real32 G_Layer = (real32)(*G_DestAddress & LayerBits.MaskPixel) * LayerBits.Normalized;
- real32 B_Layer = (real32)(*B_DestAddress & LayerBits.MaskPixel) * LayerBits.Normalized;
- real32 A_Layer = (real32)(*A_DestAddress & LayerBits.MaskPixel) * LayerBits.Normalized;
+ real32 R_Layer = (real32)(*R_DestAddress & B.LayerBits.MaskPixel) * B.LayerBits.Normalized;
+ real32 G_Layer = (real32)(*G_DestAddress & B.LayerBits.MaskPixel) * B.LayerBits.Normalized;
+ real32 B_Layer = (real32)(*B_DestAddress & B.LayerBits.MaskPixel) * B.LayerBits.Normalized;
+ real32 A_Layer = (real32)(*A_DestAddress & B.LayerBits.MaskPixel) * B.LayerBits.Normalized;
- int32 TrueX = (X - LayerBounds.Min.x) - ExtraX;
- int32 TrueY = (Y - LayerBounds.Min.y) - ExtraY;
+ int32 TrueX = (X - B.LayerBounds.Min.x) - B.ExtraX;
+ int32 TrueY = (Y - B.LayerBounds.Min.y) - B.ExtraY;
// Assert(TrueX >= 0 && TrueX < BrushLength);
// Assert(TrueY >= 0 && TrueY < BrushLength);
- uint8 *BrushPixel = (uint8 *)BrushBuffer + (TrueY * BrushPitch) + (TrueX * BytesPerPixel);
+ uint8 *BrushPixel = (uint8 *)B.BrushRow + (TrueY * B.BrushPitch) + (TrueX * B.BytesPerPixel);
- real32 Brush_BitmapAlpha = (real32)((*(uint32 *)(BrushPixel + BrushBits.ByteOffset*3)) & BrushBits.MaskPixel) * BrushBits.Normalized;
+ real32 Brush_BitmapAlpha = (real32)((*(uint32 *)(BrushPixel + B.BrushBits.ByteOffset*3)) & B.BrushBits.MaskPixel) * B.BrushBits.Normalized;
- real32 BrushAlpha = Brush_BitmapAlpha * A_Brush;
+ real32 BrushAlpha = Brush_BitmapAlpha * B.A_Brush;
real32 LayerAlpha = A_Layer;
real32 A_Blend = LayerAlpha + BrushAlpha;
- real32 R_Blend = (R_Layer * (1.0f - BrushAlpha)) + (R_Brush * BrushAlpha);
- real32 G_Blend = (G_Layer * (1.0f - BrushAlpha)) + (G_Brush * BrushAlpha);
- real32 B_Blend = (B_Layer * (1.0f - BrushAlpha)) + (B_Brush * BrushAlpha);
+ real32 R_Blend = (R_Layer * (1.0f - BrushAlpha)) + (B.R_Brush * BrushAlpha);
+ real32 G_Blend = (G_Layer * (1.0f - BrushAlpha)) + (B.G_Brush * BrushAlpha);
+ real32 B_Blend = (B_Layer * (1.0f - BrushAlpha)) + (B.B_Brush * BrushAlpha);
/*
R_Blend = (R_Brush * (1.0f - LayerAlpha)) + (R_Blend * LayerAlpha);
@@ -709,19 +904,102 @@ PaintTest(memory *Memory, block_source *Source, brush_state *Brush, void *Addres
Assert(R_Blend <= 1.0f);
- uint32 R_Out = (uint32)(Normalize(R_Blend) * LayerBits.Bits);
- uint32 G_Out = (uint32)(Normalize(G_Blend) * LayerBits.Bits);
- uint32 B_Out = (uint32)(Normalize(B_Blend) * LayerBits.Bits);
- uint32 A_Out = (uint32)(Normalize(A_Blend) * LayerBits.Bits);
+ uint32 R_Out = (uint32)(Normalize(R_Blend) * B.LayerBits.Bits);
+ uint32 G_Out = (uint32)(Normalize(G_Blend) * B.LayerBits.Bits);
+ uint32 B_Out = (uint32)(Normalize(B_Blend) * B.LayerBits.Bits);
+ uint32 A_Out = (uint32)(Normalize(A_Blend) * B.LayerBits.Bits);
- *R_DestAddress = (*R_DestAddress & ~LayerBits.MaskPixel) | R_Out;
- *G_DestAddress = (*G_DestAddress & ~LayerBits.MaskPixel) | G_Out;
- *B_DestAddress = (*B_DestAddress & ~LayerBits.MaskPixel) | B_Out;
- *A_DestAddress = (*A_DestAddress & ~LayerBits.MaskPixel) | A_Out;
+ *R_DestAddress = (*R_DestAddress & ~B.LayerBits.MaskPixel) | R_Out;
+ *G_DestAddress = (*G_DestAddress & ~B.LayerBits.MaskPixel) | G_Out;
+ *B_DestAddress = (*B_DestAddress & ~B.LayerBits.MaskPixel) | B_Out;
+ *A_DestAddress = (*A_DestAddress & ~B.LayerBits.MaskPixel) | A_Out;
}
}
}
+static void
+PaintTest_AVX2(brush_info B, void *Buffer, rectangle RenderRegion)
+{
+ __m256 One = _mm256_set1_ps(1);
+ __m256 Zero = _mm256_set1_ps(0);
+ __m256 Eight = _mm256_set1_ps(8);
+ __m256i FF = _mm256_set1_epi32(0xFF);
+ __m256 R_Brush =_mm256_set1_ps(B.R_Brush);
+ __m256 G_Brush =_mm256_set1_ps(B.G_Brush);
+ __m256 B_Brush =_mm256_set1_ps(B.B_Brush);
+ __m256 A_Brush =_mm256_set1_ps(B.A_Brush);
+ __m256 Norm255 = _mm256_set1_ps(1/255.0f);
+ __m256 Real255 = _mm256_set1_ps(255.0f);
+ __m256 LayerBoundsMaxX = _mm256_set1_ps(B.SourceWidth);
+
+ for (int32 Y = RenderRegion.Min.y; Y < RenderRegion.Max.y; Y++) {
+ __m256 PixelX = _mm256_setr_ps((real32)RenderRegion.Min.x,
+ (real32)RenderRegion.Min.x+1,
+ (real32)RenderRegion.Min.x+2,
+ (real32)RenderRegion.Min.x+3,
+ (real32)RenderRegion.Min.x+4,
+ (real32)RenderRegion.Min.x+5,
+ (real32)RenderRegion.Min.x+6,
+ (real32)RenderRegion.Min.x+7);
+ for (int32 X = RenderRegion.Min.x; X < RenderRegion.Max.x; X += 8) {
+
+ __m256i TileBarrier = _mm256_cvtps_epi32(_mm256_cmp_ps(PixelX, LayerBoundsMaxX, 1));
+
+ uint32 Offset = Y*B.LayerPitch + X*B.SourceBytesPerPixel;
+ uint8 *LayerPixelAddress = (uint8 *)Buffer + Offset;
+
+ __m256i LayerPixels = _mm256_loadu_si256((const __m256i *)LayerPixelAddress);
+
+ __m256 R_Layer = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256( LayerPixels, FF)), Norm255);
+ __m256 G_Layer = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srli_epi32(LayerPixels, 8), FF)), Norm255);
+ __m256 B_Layer = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srli_epi32(LayerPixels, 16), FF)), Norm255);
+ __m256 A_Layer = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srli_epi32(LayerPixels, 24), FF)), Norm255);
+
+ int32 TrueX = (X - B.LayerBounds.Min.x) - B.ExtraX;
+ int32 TrueY = (Y - B.LayerBounds.Min.y) - B.ExtraY;
+ uint8 *BrushPixelAddress = (uint8 *)B.BrushRow + (TrueY * B.BrushPitch) + (TrueX * B.BytesPerPixel);
+ __m256i BrushPixels = _mm256_loadu_si256((const __m256i *)BrushPixelAddress);
+
+ __m256 Brush_BitmapAlpha = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srli_epi32(BrushPixels, 24), FF)), Norm255);
+
+ __m256 A_BrushMultiplied = _mm256_mul_ps(Brush_BitmapAlpha, A_Brush);
+
+ __m256 A_Blend = _mm256_add_ps(A_Layer, A_BrushMultiplied);
+
+ __m256 R_Blend = _mm256_add_ps(_mm256_mul_ps(R_Layer, _mm256_sub_ps(One, A_BrushMultiplied)), _mm256_mul_ps(R_Brush, A_BrushMultiplied));
+ __m256 G_Blend = _mm256_add_ps(_mm256_mul_ps(G_Layer, _mm256_sub_ps(One, A_BrushMultiplied)), _mm256_mul_ps(G_Brush, A_BrushMultiplied));
+ __m256 B_Blend = _mm256_add_ps(_mm256_mul_ps(B_Layer, _mm256_sub_ps(One, A_BrushMultiplied)), _mm256_mul_ps(B_Brush, A_BrushMultiplied));
+
+ __m256i R_Out = _mm256_cvtps_epi32(_mm256_mul_ps(_mm256_max_ps(_mm256_min_ps(One, R_Blend), Zero), Real255));
+ __m256i G_Out = _mm256_cvtps_epi32(_mm256_mul_ps(_mm256_max_ps(_mm256_min_ps(One, G_Blend), Zero), Real255));
+ __m256i B_Out = _mm256_cvtps_epi32(_mm256_mul_ps(_mm256_max_ps(_mm256_min_ps(One, B_Blend), Zero), Real255));
+ __m256i A_Out = _mm256_cvtps_epi32(_mm256_mul_ps(_mm256_max_ps(_mm256_min_ps(One, A_Blend), Zero), Real255));
+
+ __m256i OutputPixel = _mm256_or_si256(
+ _mm256_or_si256(R_Out, _mm256_slli_epi32(G_Out, 8)),
+ _mm256_or_si256(_mm256_slli_epi32(B_Out, 16), _mm256_slli_epi32(A_Out, 24)));
+
+ // _mm256_storeu_si256((__m256i *)LayerPixelAddress, OutputPixel);
+ _mm256_maskstore_epi32((int *)LayerPixelAddress, TileBarrier, OutputPixel);
+ PixelX = _mm256_add_ps(PixelX, Eight);
+ }
+ }
+}
+
+static void
+Brush_Render(project_state *State, ui *UI, layer_transforms T_Layer, block_composition *MainComp, block_source *Source, void *BitmapAddress, ImVec2 ViewportMin, ImVec2 MousePos)
+{
+ brush_info B;
+ v2 LayerPos = Transform_ScreenSpaceToLocal(T_Layer, MainComp->Width, MainComp->Height, Source->Width, Source->Height, UI->CompPos, UI->CompZoom, ViewportMin, MousePos);
+ Brush_Info(&B, &State->Brush, Source, LayerPos, UI->Color);
+ if (State->Brush.Size >= 128) {
+ Render_Main((void *)&B, BitmapAddress, render_type_brush, B.LayerBounds);
+ } else {
+ PaintTest(B, BitmapAddress, B.LayerBounds);
+ }
+}
+
+
#if 0
static void
@@ -913,14 +1191,13 @@ Layer_LocalToScreenSpace(project_layer *Layer, ui *UI, comp_buffer CompBuffer, v
}
static v2
-Layer_ScreenSpaceToLocal(project_layer *Layer, ui *UI, comp_buffer CompBuffer, ImVec2 ViewportMin, ImVec2 Point)
+Layer_ScreenSpaceToLocal(project_layer *Layer, ImVec2 CompPos, ImVec2 CompZoom, comp_buffer CompBuffer, ImVec2 ViewportMin, ImVec2 Point)
{
source *Source = Layer->Source;
- v2 CompUV = ImGui_ScreenPointToCompUV(ViewportMin, UI->CompPos, UI->CompZoom, Point);
+ v2 CompUV = ImGui_ScreenPointToCompUV(ViewportMin, CompPos, CompZoom, Point);
v2 LayerUV = CompUVToLayerUV(Layer, &CompBuffer, CompUV);
return V2(LayerUV.x * Source->Info.Width, LayerUV.y * Source->Info.Height);
}
-
static void
LoadTestFootage(project_data *File, project_state *State, memory *Memory)
{
diff --git a/functions.h b/functions.h
index a6b608e..a1f5d2a 100644
--- a/functions.h
+++ b/functions.h
@@ -5,17 +5,19 @@ static void Arbitrary_Zero(uint8 *Address_Write, uint64 Size);
static void Arbitrary_SwapData(memory *Memory, uint8 *Address_0, uint8 *Address_1, uint64 Size);
static void Arbitrary_ShiftData(uint8 *Address_Start, uint8 *Address_End, uint64 ShiftAmount, int32 Direction);
+static void Render_Main(void *Data, void *OutputBuffer, render_type RenderType, rectangle RenderRegion);
+
static v2 T_CompUVToLayerUV(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uint32 SourceWidth, uint32 SourceHeight, v2 CompUV);
static void Interact_Transform_Begin(project_data *File, memory *Memory, project_state *State, ImVec2 OGPos, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray);
-static v2 Transform_ScreenSpaceToLocal(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uint32 SourceWidth, uint32 SourceHeight, ui UI, ImVec2 ViewportMin, ImVec2 Point);
+static v2 Transform_ScreenSpaceToLocal(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uint32 SourceWidth, uint32 SourceHeight, ImVec2 CompPos, ImVec2 CompZoom, ImVec2 ViewportMin, ImVec2 Point);
static ImVec2 Layer_LocalToScreenSpace(project_state *State, memory *Memory, block_layer *Layer, ui *UI, uint32 PrincipalCompIndex, v2 Point);
static v2 TransformPoint(layer_transforms T, real32 Width, real32 Height, v2 Point);
static bezier_point * Bezier_LookupAddress(memory *Memory, property_channel *Property, uint16 Index);
-static void Bezier_EvaluateValue(project_state *State, bezier_point *PointAddress, v2 *Pos);
+static void Bezier_EvaluateValue(project_state *State, bezier_point *PointAddress, v2 *Pos, real32 Y_Increment);
static void Transform_ApplyInteractive(interact_transform Interact, real32 *OutputX, real32 *OutputY, real32 *OutputRotation, real32 *OutputScale);
diff --git a/imgui_helper_widgets.cpp b/imgui_helper_widgets.cpp
index 105dad2..17a9193 100644
--- a/imgui_helper_widgets.cpp
+++ b/imgui_helper_widgets.cpp
@@ -66,3 +66,21 @@ ImGui_WarpMouseFinish(ui *UI, ImVec2 MousePos)
Assert(0);
}
}
+
+static ImVec2
+ImGui_Brush_CalcMousePos(project_state *State, ImGuiIO &io, ImVec2 MouseDelta, int32 i, real32 DeltaDistance, real32 DeltaSlope)
+{
+ ImVec2 MousePos;
+ if (State->Brush.Type == brush_normal) {
+ MousePos = io.MousePos - (MouseDelta * (i / DeltaDistance));
+ } else if (State->Brush.Type == brush_wacky1) {
+ MousePos = io.MousePos + (io.MousePos * (i / MouseDelta));
+ } else if (State->Brush.Type == brush_wacky2) {
+ MousePos = io.MousePos - (MouseDelta / (i / DeltaDistance));
+ } else if (State->Brush.Type == brush_wacky3) {
+ MousePos = io.MousePos - (MouseDelta * (i / ImVec2(MouseDelta.y, MouseDelta.x)));
+ } else {
+ Assert(0);
+ }
+ return MousePos;
+}
diff --git a/lib/base64.c b/lib/base64.c
new file mode 100644
index 0000000..1e7e192
--- /dev/null
+++ b/lib/base64.c
@@ -0,0 +1,189 @@
+/*
+The compilation of software known as FreeBSD is distributed under the
+following terms:
+
+Copyright (c) 1992-2014 The FreeBSD Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+*/
+
+/*
+ * Base64 encoding/decoding (RFC1341)
+ * Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "base64.h"
+
+static const unsigned char base64_table[65] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * base64_encode - Base64 encode
+ * @src: Data to be encoded
+ * @len: Length of the data to be encoded
+ * @out_len: Pointer to output length variable, or %NULL if not used
+ * Returns: Allocated buffer of out_len bytes of encoded data,
+ * or %NULL on failure
+ *
+ * Caller is responsible for freeing the returned buffer. Returned buffer is
+ * nul terminated to make it easier to use as a C string. The nul terminator is
+ * not included in out_len.
+ */
+
+size_t base64_encode_size(size_t len)
+{
+ size_t olen;
+ olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
+ olen += olen / 72; /* line feeds */
+ olen++; /* nul termination */
+ Assert(olen >= len);
+ return olen;
+}
+
+void base64_encode(const unsigned char *src, size_t len,
+ unsigned char *out, size_t *out_len)
+{
+ unsigned char *pos;
+ const unsigned char *end, *in;
+ int line_len;
+
+ Assert(out != NULL)
+
+ end = src + len;
+ in = src;
+ pos = out;
+ line_len = 0;
+ while (end - in >= 3) {
+ *pos++ = base64_table[in[0] >> 2];
+ *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
+ *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
+ *pos++ = base64_table[in[2] & 0x3f];
+ in += 3;
+ line_len += 4;
+ if (line_len >= 72) {
+ *pos++ = '\n';
+ line_len = 0;
+ }
+ }
+
+ if (end - in) {
+ *pos++ = base64_table[in[0] >> 2];
+ if (end - in == 1) {
+ *pos++ = base64_table[(in[0] & 0x03) << 4];
+ *pos++ = '=';
+ } else {
+ *pos++ = base64_table[((in[0] & 0x03) << 4) |
+ (in[1] >> 4)];
+ *pos++ = base64_table[(in[1] & 0x0f) << 2];
+ }
+ *pos++ = '=';
+ line_len += 4;
+ }
+
+ if (line_len)
+ *pos++ = '\n';
+
+ *pos = '\0';
+ if (out_len)
+ *out_len = pos - out;
+}
+
+
+/**
+ * base64_decode - Base64 decode
+ * @src: Data to be decoded
+ * @len: Length of the data to be decoded
+ * @out_len: Pointer to output length variable
+ * Returns: Allocated buffer of out_len bytes of decoded data,
+ * or %NULL on failure
+ *
+ * Caller is responsible for freeing the returned buffer.
+ */
+unsigned char * base64_decode(const unsigned char *src, size_t len,
+ size_t *out_len)
+{
+ unsigned char dtable[256], *out, *pos, block[4], tmp;
+ size_t i, count, olen;
+ int pad = 0;
+
+ // paranoid
+ // os_memset(dtable, 0x80, 256);
+ for (i = 0; i < 256; i++) {
+ dtable[i] = 0x80;
+ }
+
+ for (i = 0; i < sizeof(base64_table) - 1; i++)
+ dtable[base64_table[i]] = (unsigned char) i;
+ dtable[(int)'='] = 0;
+
+ count = 0;
+ for (i = 0; i < len; i++) {
+ if (dtable[src[i]] != 0x80)
+ count++;
+ }
+
+ if (count == 0 || count % 4)
+ return NULL;
+
+ olen = count / 4 * 3;
+ // pos = out = os_malloc(olen);
+ pos = out = NULL;
+ Assert(0);
+ if (out == NULL)
+ return NULL;
+
+ count = 0;
+ for (i = 0; i < len; i++) {
+ tmp = dtable[src[i]];
+ if (tmp == 0x80)
+ continue;
+
+ if (src[i] == '=')
+ pad++;
+ block[count] = tmp;
+ count++;
+ if (count == 4) {
+ *pos++ = (block[0] << 2) | (block[1] >> 4);
+ *pos++ = (block[1] << 4) | (block[2] >> 2);
+ *pos++ = (block[2] << 6) | block[3];
+ count = 0;
+ if (pad) {
+ if (pad == 1)
+ pos--;
+ else if (pad == 2)
+ pos -= 2;
+ else {
+ /* Invalid padding */
+ return NULL;
+ }
+ break;
+ }
+ }
+ }
+
+ *out_len = pos - out;
+ return out;
+}
+
diff --git a/lib/base64.h b/lib/base64.h
new file mode 100644
index 0000000..aa21fd0
--- /dev/null
+++ b/lib/base64.h
@@ -0,0 +1,17 @@
+/*
+ * Base64 encoding/decoding (RFC1341)
+ * Copyright (c) 2005, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BASE64_H
+#define BASE64_H
+
+unsigned char * base64_encode(const unsigned char *src, size_t len,
+ size_t *out_len);
+unsigned char * base64_decode(const unsigned char *src, size_t len,
+ size_t *out_len);
+
+#endif /* BASE64_H */
diff --git a/main.cpp b/main.cpp
index 31572b4..85dd002 100644
--- a/main.cpp
+++ b/main.cpp
@@ -33,11 +33,13 @@
#define STBI_FAILURE_USERMSG
#include "lib/stb_image.h"
+
#include "defines.h"
#include "my_math.h"
#include "structs.h"
#include "memory.h"
+#include "stable_diffusion.h"
#include "main.h"
#include "debug.h"
@@ -57,7 +59,7 @@ static uint64 BitmapBlockSize;
static instruction_mode InstructionMode = instruction_mode_scalar;
static uint32 RandomGlobalIncrement = 0;
-// render_entry Entries[256];
+#include "lib/base64.c"
#include "memory.cpp"
#include "undo.cpp"
@@ -67,6 +69,7 @@ static uint32 RandomGlobalIncrement = 0;
#endif
#include "createcalls.cpp"
// #include "ffmpeg_backend.cpp"
+#include "stable_diffusion.cpp"
#include "my_imgui_widgets.cpp"
#include "prenderer.cpp"
#include "gl_calls.cpp"
@@ -136,6 +139,16 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI,
Interact_Transform_Begin(File, Memory, State, io.MousePos, Sorted.CompArray, Sorted.LayerArray);
}
+ bool32 mod_key = io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl;
+ if (mod_key) {
+ if (ImGui::IsKeyPressed(ImGuiKey_C)) {
+ Clipboard_Store(File, State, Memory, Sorted.PropertyInfo, Sorted.PropertyArray);
+ }
+ if (ImGui::IsKeyPressed(ImGuiKey_V)) {
+ Clipboard_Paste(File, State, Memory, Sorted.LayerArray);
+ }
+ }
+
ImGui::DockSpaceOverViewport();
if (Debug.ToggleWindow) {
@@ -146,58 +159,90 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI,
if (State->Initializing == 3) {
Source_UICreateButton(File, State, Memory, Sorted.CompArray, Sorted.LayerArray);
- block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0);
+ /*
+ block_layer *Layera = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 2);
+ Layera->x.IsToggled = true;
+ Layera->y.IsToggled = true;
+ block_layer *Layerb = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 1);
+ Layerb->x.IsToggled = true;
+ Layerb->y.IsToggled = true;
+ block_layer *Layerc = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0);
+ Layerc->x.IsToggled = true;
+ Layerc->y.IsToggled = true;
+ */
+ /*
+ Layer_Select(Memory, State, 0);
+ Layer_Select(Memory, State, 1);
+ Layer_Select(Memory, State, 2);
+ }
+ if (State->Initializing == 2) {
+ block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex);
+ Precomp_UICreateButton(File, State, Memory, MainComp, *Sorted.CompArray, Sorted.LayerArray);
+ Layer_DeselectAll(Memory, State, File->Layer_Count);
+ */
+ // block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0);
+ Layer_Select(Memory, State, 0);
+ /*
History_Entry_Commit(Memory, "Add keyframe");
property_channel *Property = &Layer->x;
{
- bezier_point Point = { 1, {0, 800, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
+ bezier_point Point = { 1, {1, 0, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
Bezier_Add(Memory, Property, Point);
}
{
- bezier_point Point = { 1, {20, 300, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
+ bezier_point Point = { 1, {10, 300, -3, 0, 3, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
Bezier_Add(Memory, Property, Point);
}
{
- bezier_point Point = { 1, {10, 200, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
+ bezier_point Point = { 1, {20, 300, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
Bezier_Add(Memory, Property, Point);
}
+ Property = &Layer->y;
{
- bezier_point Point = { 1, {15, 200, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
+ bezier_point Point = { 1, {10, 50, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
Bezier_Add(Memory, Property, Point);
}
- History_Entry_End(Memory);
-
- /*
- History_Entry_Commit(Memory, "Add keyframe");
- Property = &Layer->y;
{
- bezier_point Point = { 1, {0, 400, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
+ bezier_point Point = { 1, {0, -800, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
Bezier_Add(Memory, Property, Point);
}
{
bezier_point Point = { 1, {20, 400, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
Bezier_Add(Memory, Property, Point);
}
+ Property = &Layer->rotation;
+ {
+ bezier_point Point = { 1, {0, 0, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
+ Bezier_Add(Memory, Property, Point);
+ }
+ {
+ bezier_point Point = { 1, {20, -360, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
+ Bezier_Add(Memory, Property, Point);
+ }
+ {
+ bezier_point Point = { 1, {40, 360, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
+ Bezier_Add(Memory, Property, Point);
+ }
Property = &Layer->opacity;
{
bezier_point Point = { 1, {0, 1, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
Bezier_Add(Memory, Property, Point);
}
{
- bezier_point Point = { 1, {20, 0, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
+ bezier_point Point = { 1, {35, 0, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 };
Bezier_Add(Memory, Property, Point);
}
- */
-
History_Entry_End(Memory);
+ */
}
ImGui_Viewport(File, State, UI, Memory, io, textureID, Sorted.CompArray, Sorted.LayerArray);
- ImGui_Timeline(File, State, Memory, UI, io, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyArray);
+ ImGui_Timeline(File, State, Memory, UI, io, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyInfo, Sorted.PropertyArray);
ImGui_File(File, State, Memory, io, Sorted.CompArray, Sorted.LayerArray);
ImGui_PropertiesPanel(File, State, UI, Memory, io);
ImGui_ColorPanel(File, State, UI, Memory, io);
+ ImGui_StableDiffusion(File, State, UI, Memory, io);
ImGui_Menu(File, State, UI, Memory, io);
File_Sort_Pop(Memory, Sorted.Layer_SortSize, Sorted.Property_SortSize);
@@ -209,11 +254,26 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI,
ImGui::EndFrame();
}
+static void
+Render_Main(void *Data, void *OutputBuffer, render_type RenderType, rectangle RenderRegion)
+{
+ bool32 IsRendering = true;
+ Renderer_Start(Data, OutputBuffer, RenderType, RenderRegion);
+ while (IsRendering) {
+ // SDL_Delay(1);
+ // Main_InputTest(File, State, &Memory, &UI);
+ Renderer_Check(&IsRendering, RenderType);
+ // TODO(fox): Make interruptable if the render time gets too long.
+ }
+}
+
static void *
-Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, uint16 *SortedPropertyArray, uint32 CompIndex)
+Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io,
+ sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray,
+ sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray, uint32 CompIndex, int32 Frame_Current)
{
block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, CompIndex);
- cache_entry *Entry_Main = Memory_Cache_Search(State, Memory, cache_entry_type_comp, CompIndex, State->Frame_Current);
+ cache_entry *Entry_Main = Memory_Cache_Search(State, Memory, cache_entry_type_comp, CompIndex, Frame_Current);
void *CompBuffer = Memory_Block_Bitmap_AddressAtIndex(Memory, Entry_Main->Block_StartIndex);
uint64 Size = Comp->Width * Comp->Height * Comp->BytesPerPixel;
Arbitrary_Zero((uint8 *)CompBuffer, Size);
@@ -230,16 +290,69 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
sorted_layer SortEntry = SortedLayerInfo[i];
uint32 Index_Physical = SortEntry.Block_Layer_Index;
block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
- if (Layer->Frame_Start <= State->Frame_Current &&
- Layer->Frame_End > State->Frame_Current && Layer->IsVisible)
+ if (Layer->Frame_Start <= Frame_Current &&
+ Layer->Frame_End > Frame_Current && Layer->IsVisible)
{
+ int32 Offset = (State->Interact_Active == interact_type_keyframe_move) ? (int32)State->Interact_Offset[0] : 0;
+ for (int h = 0; h < AmountOf(Layer->Property); h++) {
+ property_channel *Property = &Layer->Property[h];
+ sorted_property_info *InfoLocation = SortedPropertyInfo + (Index_Physical * 7) + h;
+ uint16 *ArrayLocation = SortedPropertyArray + (Index_Physical * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK);
+ if (Property->Block_Bezier_Count) {
+ real32 MinY, MaxY;
+ Property_MinMax_Y(Memory, State, Property, InfoLocation, &MinY, &MaxY);
+ real32 Y_Increment = 1 / (MaxY - MinY);
+ v2 FirstPointPos[3];
+ bezier_point *FirstPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[0]);
+ Bezier_EvaluateValue(State, FirstPointAddress, FirstPointPos);
+ v2 LastPointPos[3];
+ bezier_point *LastPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[Property->Keyframe_Count - 1]);
+ Bezier_EvaluateValue(State, LastPointAddress, LastPointPos);
+ if (FirstPointPos[0].x >= Frame_Current) {
+ Property->CurrentValue = FirstPointPos[0].y;
+ } else if (LastPointPos[0].x <= Frame_Current) {
+ Property->CurrentValue = LastPointPos[0].y;
+ } else {
+ int KeyframeIndex = 0;
+ for (;;) {
+ v2 PointPos[3];
+ bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex + 1]);
+ Bezier_EvaluateValue(State, PointAddress, PointPos, 1, Y_Increment);
+ if (PointPos[0].x >= Frame_Current)
+ break;
+ KeyframeIndex++;
+ }
+ v2 PointPos[3];
+ bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex]);
+ Bezier_EvaluateValue(State, PointAddress, PointPos, 1, Y_Increment);
+ v2 NextPointPos[3];
+ bezier_point *NextPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex + 1]);
+ Bezier_EvaluateValue(State, NextPointAddress, NextPointPos, 1, Y_Increment);
+ if (PointAddress->Type == interpolation_type_hold) {
+ Property->CurrentValue = PointPos[0].y;
+ } else if (PointAddress->Type == interpolation_type_linear && NextPointAddress->Type == interpolation_type_linear) {
+ real32 Ratio = (Frame_Current - PointPos[0].x) / (NextPointPos[0].x - PointPos[0].x);
+ Property->CurrentValue = PointPos[0].y + ((NextPointPos[0].y - PointPos[0].y) * Ratio);
+ } else {
+ Property->CurrentValue = Bezier_SolveYForX(PointPos[0], PointPos[0] + PointPos[2], NextPointPos[0] + NextPointPos[1], NextPointPos[0], Frame_Current);
+ }
+ }
+ }
+ }
+
layer_bitmap_state *BitmapState = &State->Render.Bitmap[Index_Physical];
void *BitmapAddress = NULL;
if (!Layer->IsPrecomp) {
block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index);
if (Source->Type == source_type_principal) {
- BitmapAddress = Memory_Block_AddressAtIndex(Memory, F_PrincipalBitmaps, Source->Bitmap_Index);
+ if (State->Interact_Active == interact_type_brush && State->Brush.LayerToPaint_Index == Index_Physical) {
+ // Assert(0);
+ // Render_Main((void *)T, , RenderRegion);
+ BitmapAddress = Memory_Block_AddressAtIndex(Memory, F_PrincipalBitmaps, Source->Bitmap_Index);
+ } else {
+ BitmapAddress = Memory_Block_AddressAtIndex(Memory, F_PrincipalBitmaps, Source->Bitmap_Index);
+ }
} else {
cache_entry *Entry = Memory_Cache_Search(State, Memory, cache_entry_type_source, Layer->Block_Source_Index, 0);
if (!Entry->IsCached) {
@@ -266,13 +379,8 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
} else {
block_composition *Precomp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, Layer->Block_Source_Index);
- cache_entry *Entry = Memory_Cache_Search(State, Memory, cache_entry_type_comp, Layer->Block_Source_Index, State->Frame_Current);
- // if (!Entry->IsCached) {
- uint64 Src_TimeStart = GetTime();
- Render_Comp(File, State, Memory, io, SortedCompArray, SortedLayerArray, SortedPropertyArray, Layer->Block_Source_Index);
- Entry->CycleTime = GetTime() - Src_TimeStart;
- // }
- BitmapAddress = Memory_Block_Bitmap_AddressAtIndex(Memory, Entry->Block_StartIndex);
+ BitmapAddress = Render_Comp(File, State, Memory, io, SortedCompArray, SortedLayerArray,
+ SortedPropertyInfo, SortedPropertyArray, Layer->Block_Source_Index, (int32)Layer->time.CurrentValue);
}
Assert(BitmapAddress);
@@ -281,38 +389,6 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
// for (int a = 0; a < Layer->Block_Effect_Count; a++) {
// }
- int32 Offset = (State->Interact_Active == interact_type_keyframe_move) ? (int32)State->Interact_Offset[0] : 0;
- for (int h = 0; h < AmountOf(Layer->Property); h++) {
- property_channel *Property = &Layer->Property[h];
- uint16 *ArrayLocation = SortedPropertyArray + (i * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK);
- if (Property->Block_Bezier_Count) {
- v2 Min, Max;
- Property_MinMax(Memory, State, Property, ArrayLocation, &Min, &Max);
- if (Min.x >= State->Frame_Current) {
- Property->CurrentValue = Min.y;
- } else if (Max.x <= State->Frame_Current) {
- Property->CurrentValue = Max.y;
- } else {
- int KeyframeIndex = 0;
- for (;;) {
- v2 PointPos[3];
- bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex + 1]);
- Bezier_EvaluateValue(State, PointAddress, PointPos);
- if (PointPos[0].x >= State->Frame_Current)
- break;
- KeyframeIndex++;
- }
- v2 PointPos[3];
- bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex]);
- Bezier_EvaluateValue(State, PointAddress, PointPos);
- v2 NextPointPos[3];
- bezier_point *NextPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex + 1]);
- Bezier_EvaluateValue(State, NextPointAddress, NextPointPos);
- Property->CurrentValue = Bezier_SolveYForX(PointPos[0], PointPos[0] + PointPos[2], NextPointPos[0] + NextPointPos[1], NextPointPos[0], State->Frame_Current);
- }
- }
- }
-
/*
for (int h = 0; h < AmountOf(Layer->Property); h++) {
property_channel *Property = &Layer->Property[h];
@@ -326,13 +402,7 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
T.SourceBuffer = BitmapAddress;
rectangle RenderRegion = {0, 0, Comp->Width, Comp->Height};
- bool32 IsRendering = true;
- Renderer_Start((void *)&T, CompBuffer, RenderRegion);
- while (IsRendering) {
- SDL_Delay(1);
- Renderer_Check(&IsRendering);
- // TODO(fox): Make interruptable if the render time gets too long.
- }
+ Render_Main((void *)&T, CompBuffer, render_type_main, RenderRegion);
}
}
Entry_Main->CycleTime = GetTime() - Comp_TimeStart;
@@ -349,7 +419,8 @@ Main_Renderer(project_data *File, project_state *State, memory *Memory, SDL_Wind
sorted_file Sorted = File_Sort_Push(File, State, Memory);
- void *MainCompBuffer = Render_Comp(File, State, Memory, io, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyArray, File->PrincipalCompIndex);
+ void *MainCompBuffer = Render_Comp(File, State, Memory, io, Sorted.CompArray, Sorted.LayerArray,
+ Sorted.PropertyInfo, Sorted.PropertyArray, File->PrincipalCompIndex, State->Frame_Current);
File_Sort_Pop(Memory, Sorted.Layer_SortSize, Sorted.Property_SortSize);
@@ -402,7 +473,7 @@ int main(int argc, char *argv[]) {
Memory_InitTable(&GlobalMemory, &Memory, (uint64)50 * 1024 * 1024, F_PrincipalBitmaps, "Principal bitmap data", BitmapBlockSize);
Memory_InitTable(&GlobalMemory, &Memory, (uint64)64 * 1024 * 1024, B_ScratchSpace, "Scratch");
- Memory_InitTable(&GlobalMemory, &Memory, (uint64)200 * 1024 * 1024, B_CachedBitmaps, "Cached bitmap buffer");
+ Memory_InitTable(&GlobalMemory, &Memory, (uint64)50 * 1024 * 1024, B_CachedBitmaps, "Cached bitmap buffer");
#if ARM
@@ -416,16 +487,26 @@ int main(int argc, char *argv[]) {
}
#endif
-
- project_state *State = (project_state *)Memory.Slot[P_MiscCache].Address;
- *State = {};
+ project_state State_ = {};
+ project_state *State = &State_;
project_data *File = (project_data *)Memory_Block_AllocateAddress(&Memory, F_File);
*File = {};
File->Occupied = 1;
- State->Brush.PaintBuffer = Memory.Slot[B_ScratchSpace].Address;
+ // NOTE(fox): Right now I'm just gonna throw all dynamic allocs that can't
+ // be simplified to the push/pop model here; will worry about how to best
+ // use RAM later.
+
+ State->Brush.PaintBuffer = (void *)((uint8 *)Memory.Slot[B_ScratchSpace].Address + Memory.ScratchPos);
uint64 ScratchPaintSize = 2048*2048*4;
Memory.ScratchPos += ScratchPaintSize;
+ State->Brush.TransientBitmap = (void *)((uint8 *)Memory.Slot[B_ScratchSpace].Address + Memory.ScratchPos);
+ ScratchPaintSize = 2048*2048*4;
+ Memory.ScratchPos += ScratchPaintSize;
+
+ State->ClipboardBuffer = (void *)((uint8 *)Memory.Slot[B_ScratchSpace].Address + Memory.ScratchPos);
+ State->ClipboardSize = 1024*1024;
+ Memory.ScratchPos += State->ClipboardSize;
ui UI = {};
UI.Test = ImDrawListSplitter();
@@ -438,8 +519,8 @@ int main(int argc, char *argv[]) {
block_composition *MainComp = (block_composition *)Memory_Block_AllocateAddress(&Memory, F_Precomps);
- MainComp->Width = 1024;
- MainComp->Height = 512;
+ MainComp->Width = 1280;
+ MainComp->Height = 720;
MainComp->FPS = 24;
MainComp->BytesPerPixel = 4;
MainComp->Frame_Count = 48;
@@ -763,8 +844,8 @@ int main(int argc, char *argv[]) {
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
diff --git a/main.h b/main.h
index 26b3666..e0a9374 100644
--- a/main.h
+++ b/main.h
@@ -90,6 +90,28 @@ struct block_bezier {
bezier_point Point[MAX_KEYFRAMES_PER_BLOCK];
};
+enum selection_type
+{
+ selection_none,
+ selection_layer,
+ selection_effect,
+ selection_keyframe,
+ selection_maskpoint,
+ selection_source
+};
+
+struct clipboard_channel {
+ void *Name;
+ uint16 LayerOffset;
+ uint16 KeyframeCount;
+};
+
+struct clipboard_contents {
+ selection_type Type;
+ clipboard_channel Channel[16];
+ uint16 ChannelCount;
+};
+
struct layer_bitmap_state {
// Image and video
bool32 ToUpdate = 1;
@@ -120,11 +142,13 @@ struct sorted_property_info
{
uint32 MinYIndex;
uint32 MaxYIndex;
+ bool32 IsGraphSelected;
};
struct sorted_comp_info
{
uint32 LayerCount;
+ uint32 CurrentSortIndex; // Used intermediately in the sorting algorithm
};
struct sorted_layer
@@ -227,12 +251,14 @@ char *BrushNames[brush_amount] = {
struct brush_state
{
ImVec2 UIPos; // Initial position when ctrl is held
- real32 Size = 15; // Maxes at 1024 for now
+ real32 Size = 512; // Maxes at 1024 for now
real32 Hardness = 1.0f; // From 1 to 100
real32 Spacing = 1.0f;
brush_type Type = brush_normal;
GLuint GLTexture;
void *PaintBuffer;
+ void *TransientBitmap;
+ uint32 LayerToPaint_Index = -1;
rectangle CacheBounds;
};
@@ -245,7 +271,7 @@ enum interact_type
interact_type_keyframe_move,
interact_type_keyframe_scale,
interact_type_keyframe_rotate,
- interact_type_newlayer_paint
+ interact_type_brush
};
char *ToolName[] {
@@ -288,12 +314,17 @@ struct project_state
pen_state Pen = {};
brush_state Brush;
+ sd_state SD;
+
char DummyName2[512];
bool32 IsRunning = 1;
bool32 IsPlaying;
bool32 FirstFrame = 1;
+ void *ClipboardBuffer;
+ uint64 ClipboardSize;
+
int16 MostRecentlySelectedLayer = -1;
// selection_type RecentSelectionType = selection_none;
@@ -376,6 +407,7 @@ struct property_header
real32 DefaultVal;
real32 MinVal;
real32 MaxVal;
+ bool32 AlwaysInteger;
};
struct property_channel {
@@ -388,6 +420,7 @@ struct property_channel {
real32 CurrentValue;
real32 MaxVal;
real32 MinVal;
+ bool32 AlwaysInteger;
real32 ScrubVal; // increment when dragging on sliders, etc.
bool32 IsToggled;
@@ -476,9 +509,36 @@ struct transform_info {
void *SourceBuffer;
};
+struct brush_info {
+ uint32 BrushLength;
+ rectangle LayerBounds;
+ uint32 LayerPitch;
+ uint32 BrushPitch;
+ int32 ExtraX;
+ int32 ExtraY;
+ render_byte_info LayerBits;
+ render_byte_info BrushBits;
+ int BytesPerPixel;
+ int SourceWidth;
+ int SourceBytesPerPixel;
+ void *BrushBuffer;
+ real32 R_Brush;
+ real32 G_Brush;
+ real32 B_Brush;
+ real32 A_Brush;
+ uint8 *BrushRow;
+};
+
+enum render_type {
+ render_type_main,
+ render_type_direct,
+ render_type_brush
+};
+
struct render_entry {
void *RenderData;
void *OutputBuffer;
+ render_type RenderType;
rectangle RenderRegion;
};
@@ -538,17 +598,6 @@ struct main_sdl
SDL_Renderer *Renderer;
};
-// used to determine what to copy/paste, delete, etc
-enum selection_type
-{
- selection_none,
- selection_layer,
- selection_effect,
- selection_keyframe,
- selection_maskpoint,
- selection_source
-};
-
char *ToolName[] {
"Move",
"Pen"
diff --git a/memory.cpp b/memory.cpp
index 53388bf..4593d49 100644
--- a/memory.cpp
+++ b/memory.cpp
@@ -26,16 +26,18 @@ Memory_Block_AllocateNew(memory *Memory, memory_table_list TableName)
}
static void *
-Memory_Block_AddressAtIndex(memory *Memory, memory_table_list TableName, uint32 Index)
+Memory_Block_AddressAtIndex(memory *Memory, memory_table_list TableName, uint32 Index, bool32 AssertExists = 1)
{
memory_table *Table = &Memory->Slot[TableName];
Assert(Table->Block_ElementSize != 0);
uint8 *Address = (uint8 *)Table->Address + (Table->Block_ElementSize * Index);
+ if (AssertExists)
+ Assert(*Address != 0);
return (void *)Address;
}
static uint16
-Memory_Block_IndexAtAddress(memory *Memory, memory_table_list TableName, void *Address)
+Memory_Block_LazyIndexAtAddress(memory *Memory, memory_table_list TableName, void *Address)
{
memory_table *Table = &Memory->Slot[TableName];
return ((uint8 *)Address - (uint8 *)Table->Address) / Table->Block_ElementSize;
@@ -45,7 +47,7 @@ static void *
Memory_Block_AllocateAddress(memory *Memory, memory_table_list TableName)
{
uint16 FileIndex = Memory_Block_AllocateNew(Memory, TableName);
- return Memory_Block_AddressAtIndex(Memory, TableName, FileIndex);
+ return Memory_Block_AddressAtIndex(Memory, TableName, FileIndex, 0);
}
// IMPORTANT(fox): All block data has to start with a uint8 Occupied variable!
@@ -60,7 +62,7 @@ Block_Loop(memory *Memory, memory_table_list TableName, uint32 TotalCount, int *
*HasIncremented = 0;
(*Index)++;
}
- uint8 *Occupied = (uint8 *)Memory_Block_AddressAtIndex(Memory, TableName, *Index);
+ uint8 *Occupied = (uint8 *)Memory_Block_AddressAtIndex(Memory, TableName, *Index, 0);
if (*Occupied) {
*HasIncremented = 1;
(*CurrentCount)++;
@@ -179,23 +181,6 @@ Memory_Block_Bitmap_AllocateNew(project_state *State, memory *Memory, cache_entr
}
-static void
-Memory_Cache_Invalidate(project_state *State, memory *Memory, cache_entry_type Type, uint32 TypeInfo, uint32 TypeInfo_Sub)
-{
- cache_entry *EntryArray = State->Render.Entry;
- int c = 0;
- int count = Memory->EntryCount;
- while (count != 0) {
- if (EntryArray[c].Type == Type &&
- EntryArray[c].TypeInfo == TypeInfo) {
- EntryArray[c].IsOccupied = false;
- Memory->EntryCount--;
- }
- c++;
- count--;
- }
-}
-
static cache_entry *
Memory_Cache_Search(project_state *State, memory *Memory, cache_entry_type Type, uint32 TypeInfo, uint32 TypeInfo_Sub)
{
@@ -203,10 +188,17 @@ Memory_Cache_Search(project_state *State, memory *Memory, cache_entry_type Type,
int c = 0;
int count = Memory->EntryCount;
while (count != 0) {
- if (EntryArray[c].Type == Type &&
- EntryArray[c].TypeInfo == TypeInfo &&
- EntryArray[c].TypeInfo_Sub == TypeInfo_Sub) {
- return &EntryArray[c];
+ if (Type == cache_entry_type_comp) {
+ if (EntryArray[c].Type == Type &&
+ EntryArray[c].TypeInfo == TypeInfo) {
+ return &EntryArray[c];
+ }
+ } else {
+ if (EntryArray[c].Type == Type &&
+ EntryArray[c].TypeInfo == TypeInfo &&
+ EntryArray[c].TypeInfo_Sub == TypeInfo_Sub) {
+ return &EntryArray[c];
+ }
}
c++;
count--;
diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp
index 04cedb0..bfe114b 100644
--- a/my_imgui_widgets.cpp
+++ b/my_imgui_widgets.cpp
@@ -52,9 +52,12 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *
for (int h = 0; h < AmountOf(Layer->Property); h++) {
property_channel *Property = &Layer->Property[h];
ImGui::PushID(Property);
- ImGui::Button("K");
- // if (ImGui::Button("K"))
- // Keyframe_Insert(Property, Memory, File->CurrentFrame, Property->CurrentValue.f);
+ if (ImGui::Button("K")) {
+ History_Entry_Commit(Memory, "Add keyframe");
+ bezier_point Point = { 1, {(real32)State->Frame_Current, Property->CurrentValue, -1, 0, 1, 0}, interpolation_type_linear, 0, {0, 0, 0}, 0 };
+ Bezier_Add(Memory, Property, Point);
+ History_Entry_End(Memory);
+ }
ImGui::SameLine();
ImGui_InteractSliderProperty(State, Memory, Property);
ImGui::PopID();
@@ -83,15 +86,19 @@ ImGui_DebugMemoryViewer(memory *Memory, project_state *State)
cache_entry *EntryArray = State->Render.Entry;
char *Type[4] = { "unassigned", "comp", "source", "layer" };
- int c = 0;
uint32 Blocks_Total = Memory->Slot[B_CachedBitmaps].Size / BitmapBlockSize;
uint32 PerRow = sqrt(Blocks_Total);
real32 BlockSize = ViewportScale.x / PerRow;
- while (EntryArray[c+1].CycleTime != 0) {
+ for (int c = 0; c < Memory->EntryCount; c++) {
ImGui::PushID(c);
cache_entry Entry = EntryArray[c];
- cache_entry NextEntry = EntryArray[c+1];
- uint32 BlockSpan = NextEntry.Block_StartIndex - Entry.Block_StartIndex;
+ uint32 BlockSpan;
+ if (c+1 != Memory->EntryCount) {
+ cache_entry NextEntry = EntryArray[c+1];
+ BlockSpan = NextEntry.Block_StartIndex - Entry.Block_StartIndex;
+ } else {
+ BlockSpan = 1;
+ }
ImVec2 ButtonPos = ViewportMin + ImVec2((Entry.Block_StartIndex % PerRow) * BlockSize, BlockSize * (Entry.Block_StartIndex / PerRow));
ImVec2 ButtonSize = ImVec2(BlockSpan * BlockSize, BlockSize);
ImGui::SetCursorScreenPos(ButtonPos);
@@ -111,7 +118,6 @@ ImGui_DebugMemoryViewer(memory *Memory, project_state *State)
ImGui::Text("Type - %s, Start - %i, Info - %i, %i", Type[EntryArray[c].Type], EntryArray[c].Block_StartIndex, EntryArray[c].TypeInfo, EntryArray[c].TypeInfo_Sub);
ImGui::EndTooltip();
}
- c++;
ImGui::PopID();
}
// ImGui::PopStyleVar(2);
@@ -231,6 +237,54 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ImGuiIO io,
}
static void
+ImGui_StableDiffusion(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io)
+{
+ ImGui::Begin("SD prompt input");
+ sd_state *SD = &State->SD;
+ int Size = ImGui::GetFontSize();
+ ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(200, 80, 0, 255));
+ if (ImGui::Button("Generate!", ImVec2(Size*8, Size*2))) {
+ /*
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0);
+ block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index);
+ cache_entry *Entry = Memory_Cache_Search(State, Memory, cache_entry_type_source, Layer->Block_Source_Index, 0);
+ Assert(Entry->IsCached);
+ void *BitmapAddress = Memory_Block_Bitmap_AddressAtIndex(Memory, Entry->Block_StartIndex);
+ uint64 Size = Source->Width * Source->Height * Source->BytesPerPixel;
+ uint64 EncodedLength = 0;
+ uint64 EncodedAllocSize = base64_encode_size(Size);
+ void *EncodedOutput = Memory_PushScratch(Memory, EncodedSize);
+ uint64 EncodedTrueSize;
+ base64_encode((uint8 *)BitmapAddress, Size, (uint8 *)EncodedOutput, &EncodedTrueSize);
+ Memory_PopScratch(Memory, EncodedSize);
+ */
+ SD_Txt2Txt(SD);
+ }
+ ImGui::InputText("Address", SD->ServerAddress, SD_LEN_ADDRESS);
+ if (State->Initializing && (SD->ServerAddress[0] == '\0')) {
+ sprintf(SD->Prompt, "%s", "1girl, looking at viewer, smile, hakurei reimu, cowboy shot");
+ sprintf(SD->NegPrompt, "%s", "nsfw, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark");
+ sprintf(SD->ServerAddress, "%s", "http://127.0.0.1:7860");
+ }
+ ImGui::PopStyleColor();
+ ImGui::InputTextMultiline("Prompt", SD->Prompt, SD_LEN_PROMPT);
+ ImGui::InputTextMultiline("Negative prompt", SD->NegPrompt, SD_LEN_PROMPT);
+ ImGui::SliderInt("Steps", &SD->Steps, 0, 150);
+ ImGui::SliderInt("Width", &SD->Width, 64, 2048, "%i px");
+ if (ImGui::IsItemDeactivatedAfterEdit()) {
+ SD->Width = SD->Width + (64 - (SD->Width % 64));
+ }
+ ImGui::SliderInt("Height", &SD->Height, 64, 2048, "%i px");
+ if (ImGui::IsItemDeactivatedAfterEdit()) {
+ SD->Height = SD->Height + (64 - (SD->Height % 64));
+ }
+ ImGui::SliderFloat("CFG scale", &SD->CFG, 1, 30, "%.2f");
+ ImGui::SliderFloat("Denoising strength", &SD->DenoisingStrength, 0, 1, "%.2f");
+ ImGui::InputInt("Seed", &SD->Seed);
+ ImGui::End();
+}
+
+static void
ImGui_ColorPanel(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io)
{
ImGuiStyle& style = ImGui::GetStyle();
@@ -444,7 +498,7 @@ ImGui_TransformUI(project_data *File, project_state *State, memory *Memory, ui *
// real32 LocalX = ((io.MousePos.x - UI->CompPos.x) - Center.x) ;
// real32 LocalY = ((io.MousePos.y - UI->CompPos.y) - Center.y) ;
layer_transforms BoxTransforms = { Center.x, Center.y, 0.5, 0.5, (real32)(Interact->Radians / (PI / 180)), Interact->Scale };
- v2 LayerPoint = Transform_ScreenSpaceToLocal(BoxTransforms, CompWidth, CompHeight, BoxLength.x, BoxLength.y, *UI, ViewportMin, io.MousePos);
+ v2 LayerPoint = Transform_ScreenSpaceToLocal(BoxTransforms, CompWidth, CompHeight, BoxLength.x, BoxLength.y, UI->CompPos, UI->CompZoom, ViewportMin, io.MousePos);
real32 U = LayerPoint.x / BoxLength.x;
real32 V = LayerPoint.y / BoxLength.y;
@@ -744,7 +798,6 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory,
UI->FocusedWindow = focus_viewport;
block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex);
- block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0);
ImVec2 ViewportMin = ImGui::GetCursorScreenPos();
@@ -763,7 +816,7 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory,
ImDrawList* draw_list = ImGui::GetWindowDrawList();
draw_list->AddRectFilled(ViewportMin, ViewportMax, IM_COL32(50, 50, 50, 255));
draw_list->AddRect(ViewportMin, ViewportMax, IM_COL32(255, 255, 255, 255));
- draw_list->AddRect(CompPosMin, CompPosMax, IM_COL32(255, 255, 255, 55));
+ // draw_list->AddRect(CompPosMin, CompPosMax, IM_COL32(255, 255, 255, 55));
// Actual composition texture
draw_list->PushClipRect(ViewportMin, ViewportMax, true);
@@ -787,29 +840,67 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory,
ImGui::InvisibleButton("canvas", ViewportScale, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
bool32 IsHovered = ImGui::IsItemHovered();
+#if 0
bool32 IsActive = ImGui::IsItemActive();
bool32 IsActivated = ImGui::IsItemActivated();
+#else
+ bool32 IsActive = ImGui::IsKeyDown(ImGuiKey_3);
+ bool32 IsActivated = ImGui::IsKeyPressed(ImGuiKey_3);
+#endif
bool32 IsDeactivated = ImGui::IsItemDeactivated();
- if (IsHovered && IsActivated && ImGui::IsMouseDown(ImGuiMouseButton_Left))
+ if (IsHovered && IsActivated && !ImGui::IsMouseDown(ImGuiMouseButton_Right))
{
// Point to zoom in on if Z is held
UI->TempZoomRatio = ImGui_ScreenPointToCompUV(ViewportMin, UI->CompPos, UI->CompZoom, io.MousePos);
- if (State->Tool == tool_brush && File->Layer_Count != 2) {
- State->Interact_Active = interact_type_newlayer_paint;
- History_Entry_Commit(Memory,"Paint new layer");
- uint16 SourceIndex = Source_Generate_Blank(File, State, Memory, MainComp->Width, MainComp->Height, MainComp->BytesPerPixel);
- Assert(0);
- // Layer_CreateFromSource(File, State, Memory, SourceIndex, MainComp->Frame_End);
- History_Entry_End(Memory);
+ if (State->Tool == tool_brush) {
+ sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, File->PrincipalCompIndex);
+ sorted_comp_info SortedCompInfo = SortedCompArray[File->PrincipalCompIndex];
+ for (int i = SortedCompInfo.LayerCount - 1; i >= 0; i--) {
+ sorted_layer SortEntry = SortedLayerInfo[i];
+ uint32 Index_Physical = SortEntry.Block_Layer_Index;
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
+ block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index);
+ if (Layer->IsSelected && Source->Type == source_type_principal) {
+ State->Interact_Active = interact_type_brush;
+ State->Brush.LayerToPaint_Index = Layer->Block_Source_Index;
+ }
+ }
+ if (State->Brush.LayerToPaint_Index == -1) {
+ State->Interact_Active = interact_type_brush;
+ Layer_DeselectAll(File, State, Memory);
+ Arbitrary_Zero((uint8 *)State->Brush.TransientBitmap, 2048*2048*4);
+ History_Entry_Commit(Memory,"Paint new layer");
+ uint16 i = Source_Generate_Blank(File, State, Memory, MainComp->Width, MainComp->Height, MainComp->BytesPerPixel);
+ block_layer *Layer = Layer_Init(File, Memory);
+ block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index);
+ State->Brush.LayerToPaint_Index = Memory_Block_LazyIndexAtAddress(Memory, F_Layers, (void *)Layer);
+ Layer->Block_Source_Index = i;
+ Layer->x.CurrentValue = MainComp->Width / 2;
+ Layer->y.CurrentValue = MainComp->Height / 2;
+ int TopOffset = 0;
+ sorted_comp_info SortedCompInfo = SortedCompArray[File->PrincipalCompIndex];
+ if (SortedCompInfo.LayerCount)
+ {
+ sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, File->PrincipalCompIndex);
+ block_layer *TopLayer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, SortedLayerInfo[SortedCompInfo.LayerCount - 1].Block_Layer_Index);
+ TopOffset = TopLayer->Vertical_Offset;
+ }
+ Layer->Vertical_Offset = TopOffset - 1;
+ Layer->Frame_Start = MainComp->Frame_Start;
+ Layer->Frame_End = MainComp->Frame_End;
+ Layer->IsSelected = true;
+ History_Entry_End(Memory);
+ State->UpdateFrame = true;
+ }
}
// Layer selection
if (!ImGui::IsKeyDown(ImGuiKey_Z) && State->Tool == tool_default && State->Interact_Active == interact_type_none) {
int32 Selection = Layer_TestSelection(Memory, State, UI, SortedCompArray, SortedLayerArray, File->PrincipalCompIndex);
if (!io.KeyShift && State->Interact_Active == interact_type_none)
- Layer_DeselectAll(Memory, File->Layer_Count);
+ Layer_DeselectAll(File, State, Memory);
if (Selection != -1)
Layer_Select(Memory, State, Selection);
}
@@ -832,9 +923,10 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory,
}
bool32 OtherActions = ImGui::IsKeyDown(ImGuiKey_Z) || ImGui::IsMouseDown(ImGuiMouseButton_Right);
- if (State->Tool == tool_brush) {
+ if (State->Tool == tool_brush && State->Interact_Active == interact_type_brush) {
+ Assert(State->Brush.LayerToPaint_Index != -1);
if (IsActive && !OtherActions) {
- block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0);
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, State->Brush.LayerToPaint_Index);
layer_transforms T_Layer = Layer_GetTransforms(Layer);
block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index);
void *SourceBitmapAddress = Memory_Block_AddressAtIndex(Memory, F_PrincipalBitmaps, Source->Bitmap_Index);
@@ -844,31 +936,19 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory,
real32 DeltaDistance = sqrt(MouseDelta.x * MouseDelta.x + MouseDelta.y * MouseDelta.y);
real32 DeltaSlope = MouseDelta.y / MouseDelta.x;
for (real32 i = 0; i < DeltaDistance; i += State->Brush.Spacing) {
- ImVec2 MousePos;
- if (State->Brush.Type == brush_normal) {
- MousePos = io.MousePos - (MouseDelta * (i / DeltaDistance));
- } else if (State->Brush.Type == brush_wacky1) {
- MousePos = io.MousePos + (io.MousePos * (i / MouseDelta));
- } else if (State->Brush.Type == brush_wacky2) {
- MousePos = io.MousePos - (MouseDelta / (i / DeltaDistance));
- } else if (State->Brush.Type == brush_wacky3) {
- MousePos = io.MousePos - (MouseDelta * (i / ImVec2(MouseDelta.y, MouseDelta.x)));
- } else {
- Assert(0);
- }
- v2 LayerPos = Transform_ScreenSpaceToLocal(T_Layer, MainComp->Width, MainComp->Height, Source->Width, Source->Height, *UI, ViewportMin, MousePos);
- PaintTest(Memory, Source, &State->Brush, SourceBitmapAddress, LayerPos, 4, UI->Color);
+ ImVec2 MousePos = ImGui_Brush_CalcMousePos(State, io, MouseDelta, i, DeltaDistance, DeltaSlope);
+ Brush_Render(State, UI, T_Layer, MainComp, Source, SourceBitmapAddress, ViewportMin, MousePos);
}
} else if (IsActivated) {
ImVec2 MousePos = io.MousePos;
- v2 LayerPos = Transform_ScreenSpaceToLocal(T_Layer, MainComp->Width, MainComp->Height, Source->Width, Source->Height, *UI, ViewportMin, MousePos);
- PaintTest(Memory, Source, &State->Brush, SourceBitmapAddress, LayerPos, 4, UI->Color);
+ Brush_Render(State, UI, T_Layer, MainComp, Source, SourceBitmapAddress, ViewportMin, MousePos);
}
- Memory_Cache_Invalidate(State, Memory, cache_entry_type_comp, Layer->Block_Composition_Index, 0);
+ // Memory_Cache_Invalidate(State, Memory, cache_entry_type_comp, Layer->Block_Composition_Index, 0);
State->UpdateFrame = true;
}
if (IsDeactivated) {
+ State->Brush.LayerToPaint_Index = -1;
State->Interact_Active = interact_type_none;
}
}
@@ -956,7 +1036,7 @@ ImGui_TimelineHorizontalIncrementDraw(project_state *State, ui *UI, ImDrawList *
static void
-ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io)
+ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray)
{
bool open = true;
ImGui::Begin("Graph info", &open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
@@ -975,8 +1055,14 @@ ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI
for (int h = 0; h < AmountOf(Layer->Property); h++) {
property_channel *Property = &Layer->Property[h];
if (Property->Block_Bezier_Count) {
+ sorted_property_info *InfoLocation = SortedPropertyInfo + (i * 7) + h;
+ uint16 *ArrayLocation = SortedPropertyArray + (i * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK);
ImGui::PushID(Property);
- ImGui::Text(Property->Name);
+ if (ImGui::Selectable(Property->Name, InfoLocation->IsGraphSelected)) {
+ Property_DeselectAll(File, Memory, SortedPropertyArray);
+ bezier_point *FirstPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[0]);
+ FirstPointAddress->IsSelected = true;
+ }
ImGui::PopID();
}
}
@@ -988,15 +1074,77 @@ ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI
}
static void
+ImGui_Timeline_DrawKeySheet(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list, property_channel *Property, uint16 *ArrayLocation,
+ ImVec2 Increment, ImVec2 TimelineAbsolutePos, ImVec2 TimelineMoveSize, ImVec2 TimelineZoomSize,
+ ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement)
+{
+ ImGui::PushID(Property);
+ for (int p = 0; p < Property->Keyframe_Count; p++) {
+ int k = ArrayLocation[p];
+ bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, k);
+
+ v2 PointPos[3];
+ Bezier_EvaluateValue(State, PointAddress, PointPos);
+
+ real32 LocalPos_Ratio_X = PointPos[0].x * Increment.x;
+ real32 Keyframe_ScreenPos_X = TimelineAbsolutePos.x + TimelineMoveSize.x + LocalPos_Ratio_X * TimelineZoomSize.x;
+
+ ImVec2 Keyframe_ScreenPos(Keyframe_ScreenPos_X, TimelineAbsolutePos.y);
+
+ if (UI->BoxSelect) {
+ real32 Y_Top = (io.MouseClickedPos[0].y < io.MousePos.y) ? io.MouseClickedPos[0].y : io.MousePos.y;
+ real32 Y_Bottom = (io.MouseClickedPos[0].y > io.MousePos.y) ? io.MouseClickedPos[0].y : io.MousePos.y;
+ real32 X_Left = (io.MouseClickedPos[0].x < io.MousePos.x) ? io.MouseClickedPos[0].x : io.MousePos.x;
+ real32 X_Right = (io.MouseClickedPos[0].x > io.MousePos.x) ? io.MouseClickedPos[0].x : io.MousePos.x;
+
+ if (Keyframe_ScreenPos.y >= Y_Top && Keyframe_ScreenPos.y <= Y_Bottom &&
+ Keyframe_ScreenPos.x >= X_Left && Keyframe_ScreenPos.x <= X_Right)
+ {
+ if (!PointAddress->IsSelected) {
+ PointAddress->IsSelected = 1;
+ }
+ } else if (!io.KeyShift) {
+ PointAddress->IsSelected = 0;
+ }
+ }
+
+ ImVec2 ButtonSize(16, 16);
+
+ ImGui::PushID(p);
+
+ ImU32 PointCol = (PointAddress->IsSelected) ? ImColor(0.8f, 0.5f, 0.0f, 1.0f) : ImColor(0.1f, 0.1f, 0.1f, 1.0f);
+ ImU32 LineCol = (PointAddress->IsSelected) ? ImColor(0.8f, 0.5f, 0.5f, 1.0f) : ImColor(0.4f, 0.4f, 0.4f, 1.0f);
+ ImGui::SetCursorScreenPos(Keyframe_ScreenPos - (ButtonSize * 0.5));
+ ImGui::InvisibleButton("##keyframemover", ButtonSize, ImGuiMouseButton_Left);
+ bool32 IsHovered = ImGui::IsItemHovered();
+ bool32 IsItemActive = ImGui::IsItemActive();
+ bool32 IsItemActivated = ImGui::IsItemActivated();
+ bool32 IsItemDeactivated = ImGui::IsItemDeactivated();
+ bool32 LeftClick = ImGui::IsMouseDown(ImGuiMouseButton_Left);
+ bool32 RightClick = ImGui::IsMouseDown(ImGuiMouseButton_Right);
+
+ if (IsHovered)
+ PointCol = ImColor(1.0f, 0.8f, 0.8f, 1.0f);
+
+ if (IsItemActivated) {
+ PointAddress->IsSelected = 1;
+ }
+
+ draw_list->AddCircleFilled(Keyframe_ScreenPos, 4, PointCol);
+
+ ImGui::PopID();
+ }
+ ImGui::PopID();
+}
+
+static void
ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list,
ImVec2 Increment, ImVec2 TimelineAbsolutePos, ImVec2 TimelineMoveSize, ImVec2 TimelineZoomSize,
- ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement, uint16 *SortedPropertyArray)
+ ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray)
{
+ // I'm using the draw splitter here to be able to draw the dots on top of the graph lines.
UI->Test.Split(draw_list, 2);
- TimelineMoveSize.y = TimelineMoveSize.y + (TimelineZoomSize.y * (0.25 / 4));
- TimelineZoomSize.y = TimelineZoomSize.y * 0.6;
-
int h = 0, c = 0, i = 0;
while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i))
{
@@ -1006,44 +1154,63 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor
int32 Frame_Start = Layer->Frame_Start;
- ImVec2 Layer_ScreenPos_Min = TimelineAbsolutePos + TimelineMoveSize; // (* TimelineZoomSize);
-
ImGui::PushID(i);
- ImU32 col = IM_COL32(255, 255, 255, 255);
-
- if (State->Interact_Active == interact_type_keyframe_move) {
- ImVec2 DragDelta = io.MousePos - ImVec2(State->Interact_Offset[2], State->Interact_Offset[3]);
- // NOTE(fox): I'm setting the X (time) to the transformed value and
- // the Y (value) to the raw drag delta, because the Y units can be
- // normalized while the X units are always universal across all the
- // graphs (and it has to be passed into the sorter).
- State->Interact_Offset[0] = (DragDelta.x / TimelineZoomSize.x) / Increment.x;
- State->Interact_Offset[1] = DragDelta.y;
- DebugWatchVar("DeltaX: ", &DragDelta.x, d_float);
- DebugWatchVar("Deltay: ", &DragDelta.y, d_float);
- } else if (State->Interact_Active == interact_type_keyframe_scale) {
- ImVec2 DragDelta = io.MousePos - ImVec2(State->Interact_Offset[2], State->Interact_Offset[3]);
- State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) / Increment.x;
- // TODO(fox): Pass min/max to sort to calculate this better!
- }
-
- if ((io.MouseDelta.x || io.MouseDelta.y) &&
- (State->Interact_Active == interact_type_keyframe_move ||
+ if ((State->Interact_Active == interact_type_keyframe_move ||
State->Interact_Active == interact_type_keyframe_rotate ||
State->Interact_Active == interact_type_keyframe_scale))
{
- // Memory_Cache_Invalidate(State, Memory, cache_entry_type_comp, Lay
+ ImGui_WarpMouse(UI, io.MousePos, TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder);
+ ImVec2 DragDelta = io.MousePos - ImVec2(State->Interact_Offset[2], State->Interact_Offset[3]);
+ DragDelta = DragDelta + (ImVec2(UI->Warp_X, UI->Warp_Y) * TimelineSize);
+ if (io.MouseDelta.x || io.MouseDelta.y) {
+ State->UpdateFrame = true;
+ }
+ if (State->Interact_Active == interact_type_keyframe_move) {
+ // The Y increment varies between graphs, so we have to do it in the Bezier_EvaluateValue call.
+ State->Interact_Offset[0] = (DragDelta.x / TimelineZoomSize.x) / Increment.x;
+ State->Interact_Offset[1] = DragDelta.y;
+ } else if (State->Interact_Active == interact_type_keyframe_scale) {
+ State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) / Increment.x;
+ } else if (State->Interact_Active == interact_type_keyframe_rotate) {
+ State->Interact_Offset[0] = (DragDelta.x / TimelineZoomSize.x);
+ /*
+ real32 Slope_Old = (Keyframe_ScreenPos.y - State->Interact_Offset[3]) / (Keyframe_ScreenPos.x - State->Interact_Offset[2]);
+ real32 Slope_New = (Keyframe_ScreenPos.y - io.MousePos.y) / (Keyframe_ScreenPos.x - io.MousePos.x);
+ State->Interact_Offset[0] = atan((Slope_Old - Slope_New) / (1 + Slope_Old * Slope_New));
+ */
+ }
}
for (int h = 0; h < AmountOf(Layer->Property); h++) {
property_channel *Property = &Layer->Property[h];
+ sorted_property_info *InfoLocation = SortedPropertyInfo + (i * 7) + h;
uint16 *ArrayLocation = SortedPropertyArray + (i * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK);
ImGui::PushID(Property);
if (Property->Block_Bezier_Count) {
- v2 Min, Max;
- Property_MinMax(Memory, State, Property, ArrayLocation, &Min, &Max);
- real32 Y_Increment = 1 / (Max.y - Min.y);
+ real32 MinY, MaxY;
+ Property_MinMax_Y(Memory, State, Property, InfoLocation, &MinY, &MaxY, 0);
+ real32 Y_Increment = 1 / (MaxY - MinY);
+
+ real32 GraphScale = 0;
+ real32 GraphPos = 0;
+ if ((1 / Y_Increment) < 5) {
+ GraphScale = 0.2;
+ GraphPos = 0.3;
+ } else if ((1 / Y_Increment) > 700) {
+ GraphScale = 0.6;
+ GraphPos = 0.06;
+ } else {
+ GraphScale = 0.4;
+ GraphPos = 0.2;
+ }
+
+
+ real32 GraphMoveHeight = TimelineMoveSize.y + (TimelineZoomSize.y * GraphPos);
+ real32 GraphZoomHeight = TimelineZoomSize.y * GraphScale;
+
+ uint32 GraphCol = InfoLocation->IsGraphSelected ? IM_COL32(255, 180, 150, 255) : IM_COL32(255, 255, 255, 70);
+
bezier_point *PointAddress[2] = {};
ImVec2 Keyframe_ScreenPos[6] = {};
for (int p = 0; p < Property->Keyframe_Count; p++) {
@@ -1054,14 +1221,14 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor
PointAddress[Idx] = Bezier_LookupAddress(Memory, Property, k);
v2 PointPos[3];
- Bezier_EvaluateValue(State, PointAddress[Idx], PointPos);
+ Bezier_EvaluateValue(State, PointAddress[Idx], PointPos, GraphZoomHeight, Y_Increment);
ImVec2 Keyframe_LocalPos[3] = { V2(PointPos[0]), V2(PointPos[0] + PointPos[1]), V2(PointPos[0] + PointPos[2]) };
ImVec2 Keyframe_LocalPos_Ratio[3];
for (int b = 0; b < 3; b++) {
- Keyframe_LocalPos_Ratio[b] = (Keyframe_LocalPos[b] - ImVec2(0, Min.y)) * ImVec2(Increment.x, Y_Increment);
- Keyframe_ScreenPos[NewIdx + b] = TimelineAbsolutePos + TimelineMoveSize + ((ImVec2(1, 1) * Keyframe_LocalPos_Ratio[b]) * TimelineZoomSize);
+ Keyframe_LocalPos_Ratio[b] = (Keyframe_LocalPos[b] - ImVec2(0, MinY)) * ImVec2(Increment.x, Y_Increment);
+ Keyframe_ScreenPos[NewIdx + b] = TimelineAbsolutePos + ImVec2(TimelineMoveSize.x, GraphMoveHeight) + ((ImVec2(1, -1) * Keyframe_LocalPos_Ratio[b] + ImVec2(0, 1)) * ImVec2(TimelineZoomSize.x, GraphZoomHeight));
}
if (UI->BoxSelect) {
@@ -1110,10 +1277,16 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor
if (b != 0 && PointAddress[Idx]->IsSelected)
draw_list->AddLine(Keyframe_ScreenPos[NewIdx], Keyframe_ScreenPos[NewIdx + b], LineCol, 2.0f);
- if (b == 0)
+ if (b == 0) {
draw_list->AddCircleFilled(Keyframe_ScreenPos[NewIdx + b], 4, PointCol);
- else
+ if (InfoLocation->IsGraphSelected) {
+ char buf[8];
+ sprintf(buf, "%.2f", Keyframe_LocalPos[0].y);
+ draw_list->AddText(Keyframe_ScreenPos[NewIdx + b], 0xFFFFFFFF, buf);
+ }
+ } else {
draw_list->AddCircle(Keyframe_ScreenPos[NewIdx + b], 6, PointCol, 0, 2);
+ }
ImGui::PopID();
}
@@ -1124,9 +1297,9 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor
if (p != 0) {
if (PointAddress[0]->Type == interpolation_type_bezier && PointAddress[1]->Type == interpolation_type_bezier) {
draw_list->AddBezierCubic(Keyframe_ScreenPos[OldIdx], Keyframe_ScreenPos[OldIdx + 2],
- Keyframe_ScreenPos[NewIdx + 1], Keyframe_ScreenPos[NewIdx], col, 1.0f, 0);
+ Keyframe_ScreenPos[NewIdx + 1], Keyframe_ScreenPos[NewIdx], GraphCol, 1.0f, 0);
} else {
- draw_list->AddLine(Keyframe_ScreenPos[0], Keyframe_ScreenPos[3], col, 1.0f);
+ draw_list->AddLine(Keyframe_ScreenPos[0], Keyframe_ScreenPos[3], GraphCol, 1.0f);
}
}
}
@@ -1144,7 +1317,7 @@ static void
ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list, uint16 CompIndex,
ImVec2 Increment, ImVec2 TimelineAbsolutePos, ImVec2 TimelineMoveSize, ImVec2 TimelineZoomSize,
ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement,
- sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray)
+ sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray)
{
block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, CompIndex);
sorted_comp_info SortedCompInfo = SortedCompArray[CompIndex];
@@ -1152,29 +1325,60 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
ImGui::PushID(CompIndex);
- if (UI->TimelineMode == timeline_mode_default) {
+ // Layers are drawn from top to bottom, so we can account for opened precomps/keyframes
+ // without needing another loop.
+ real32 DisplayOffset = 0;
+ for (int i = SortedCompInfo.LayerCount - 1; i >= 0; i--)
+ {
+ sorted_layer SortEntry = SortedLayerInfo[i];
+ uint32 Index_Physical = SortEntry.Block_Layer_Index;
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
+
+ int32 Frame_Start = Layer->Frame_Start;
+ int32 Frame_End = Layer->Frame_End;
+ real32 Vertical_Offset = SortEntry.SortedOffset + DisplayOffset;
+
+ Layer_Evaluate_Display(Layer, SortedLayerArray, SortedCompArray, SortedLayerInfo, i, &DisplayOffset);
- for (int i = 0; i < SortedCompInfo.LayerCount; i++)
- {
- sorted_layer SortEntry = SortedLayerInfo[i];
- uint32 Index_Physical = SortEntry.Block_Layer_Index;
- block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
-
- int32 Frame_Start = Layer->Frame_Start;
- int32 Frame_End = Layer->Frame_End;
- real32 Vertical_Offset = SortEntry.SortedOffset;
- if (Layer->IsSelected)
- Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End);
- ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset);
- ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height);
-
- ImVec2 Layer_LocalPos_Ratio = (Layer_LocalPos * Increment);
- ImVec2 Layer_LocalSize_Ratio = Layer_LocalSize * Increment;
- ImVec2 Layer_ScreenPos_Min = TimelineAbsolutePos + TimelineMoveSize + (Layer_LocalPos_Ratio * TimelineZoomSize);
- ImVec2 Layer_ScreenPos_Max = TimelineAbsolutePos + TimelineMoveSize + ((Layer_LocalPos_Ratio + Layer_LocalSize_Ratio) * TimelineZoomSize);
- ImVec2 Layer_ScreenSize = Layer_ScreenPos_Max - Layer_ScreenPos_Min;
-
- ImGui::PushID(i);
+ if (Layer->IsSelected)
+ Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End);
+
+ ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset);
+ ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height);
+
+ ImVec2 Layer_LocalPos_Ratio = (Layer_LocalPos * Increment);
+ ImVec2 Layer_LocalSize_Ratio = Layer_LocalSize * Increment;
+ ImVec2 Layer_ScreenPos_Min = TimelineAbsolutePos + TimelineMoveSize + (Layer_LocalPos_Ratio * TimelineZoomSize);
+ ImVec2 Layer_ScreenPos_Max = TimelineAbsolutePos + TimelineMoveSize + ((Layer_LocalPos_Ratio + Layer_LocalSize_Ratio) * TimelineZoomSize);
+ ImVec2 Layer_ScreenSize = Layer_ScreenPos_Max - Layer_ScreenPos_Min;
+
+ // UI
+
+ ImU32 LayerColor = 0;
+ ImU32 BorderColor = 0;
+ LayerColor = ImColor(UI->LayerColors[Layer->ColIndex]);
+ BorderColor = ImColor(0.2, 0.2, 0.2, 1.0f);
+
+ draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max, LayerColor);
+ draw_list->AddRect(Layer_ScreenPos_Min, Layer_ScreenPos_Max, BorderColor, 2);
+ block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Layer->Block_String_Index);
+ char buf[21];
+ sprintf(buf, "%.2f, %.2f", Layer->Vertical_Offset, SortEntry.SortedOffset);
+ // draw_list->AddText(Layer_ScreenPos_Min, 0xFFFFFFFF, buf);
+ if (UI->TimelinePercentZoomed.y <= 1.0f)
+ draw_list->AddText(Layer_ScreenPos_Min, 0xFFFFFFFF, String->Char);
+
+ if (Layer->IsSelected) {
+ draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(0.25f, 0.25f, 0.25f, 0.5f), 2);
+ draw_list->AddRect(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(1.0f, 1.0f, 1.0f, 0.5f), 2);
+ }
+
+ //
+
+ // Main interaction
+
+ ImGui::PushID(i);
+ if (UI->TimelineMode == timeline_mode_default) {
if (UI->BoxSelect && UI->TimelineMode == timeline_mode_default) {
bool32 Test = 0;
@@ -1190,7 +1394,7 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
if (Test) {
if (!Layer->IsSelected) {
- Layer->IsSelected = true;
+ Layer_Select(Memory, State, Index_Physical);
}
} else if (!io.KeyShift) {
Layer->IsSelected = false;
@@ -1210,7 +1414,7 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
}
if (ImGui::IsItemActivated()) {
if (!Layer->IsSelected) {
- if (!io.KeyShift) Layer_DeselectAll(Memory, File->Layer_Count);
+ if (!io.KeyShift) Layer_DeselectAll(File, State, Memory);
Layer_Select(Memory, State, Index_Physical);
}
}
@@ -1254,7 +1458,7 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
if (ImGui::IsItemActivated()) {
if (!Layer->IsSelected) {
- if (!io.KeyShift) Layer_DeselectAll(Memory, File->Layer_Count);
+ if (!io.KeyShift) Layer_DeselectAll(File, State, Memory);
Layer_Select(Memory, State, Index_Physical);
}
}
@@ -1262,47 +1466,7 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
ImGui::OpenPopupOnItemClick("layerpopup", ImGuiPopupFlags_MouseButtonRight);
if (ImGui::BeginPopup("layerpopup")) {
if (ImGui::MenuItem("Pre-compose layer")) {
- History_Entry_Commit(Memory, "Pre-compose layer");
- block_composition *NewComp = Precomp_Init(File, Memory);
- NewComp->Width = Comp->Width;
- NewComp->Height = Comp->Height;
- NewComp->FPS = Comp->FPS;
- NewComp->BytesPerPixel = Comp->BytesPerPixel;
- NewComp->Frame_Count = Comp->Frame_Count;
- NewComp->Frame_Start = Comp->Frame_Start;
- NewComp->Frame_End = Comp->Frame_End;
- int32 TopOffset = 0;
- for (int i = SortedCompInfo.LayerCount - 1; i >= 0; i--)
- {
- sorted_layer SortEntry = SortedLayerInfo[i];
- uint32 Index_Physical = SortEntry.Block_Layer_Index;
- block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
- if (Layer->IsSelected) {
- TopOffset = Layer->Vertical_Offset;
- break;
- }
- }
- for (int i = SortedCompInfo.LayerCount - 1; i >= 0; i--)
- {
- sorted_layer SortEntry = SortedLayerInfo[i];
- uint32 Index_Physical = SortEntry.Block_Layer_Index;
- block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
- if (Layer->IsSelected) {
- History_Action_Swap(Memory, F_File, sizeof(Layer->Block_Composition_Index), &Layer->Block_Composition_Index);
- Layer->Block_Composition_Index = 1;
- }
- }
- block_layer *PrecompLayer = Layer_Init(File, Memory);
- PrecompLayer->IsPrecomp = true;
- PrecompLayer->Block_Source_Index = 1;
- PrecompLayer->Block_Composition_Index = 0;
- PrecompLayer->Vertical_Offset = TopOffset;
- PrecompLayer->Frame_End = NewComp->Frame_End;
- PrecompLayer->ColIndex = 3;
- PrecompLayer->x.CurrentValue = Comp->Width/2;
- PrecompLayer->y.CurrentValue = Comp->Height/2;
- History_Entry_End(Memory);
- State->UpdateFrame = true;
+ Precomp_UICreateButton(File, State, Memory, CompIndex, SortedCompInfo, SortedLayerInfo);
}
if (ImGui::BeginMenu("Layer color"))
{
@@ -1354,12 +1518,12 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
sorted_layer SortEntry = SortedLayerInfo[i];
uint32 Index_Physical = SortEntry.Block_Layer_Index;
block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
+ // NOTE(fox): Some data on the tree could be saved here.
+ History_Action_Swap(Memory, F_File, sizeof(Layer->Vertical_Offset), &Layer->Vertical_Offset);
+ Layer->Vertical_Offset = SortEntry.SortedOffset;
if (Layer->IsSelected) {
- // NOTE(fox): Some data on the tree could be saved here.
- History_Action_Swap(Memory, F_File, sizeof(Layer->Vertical_Offset), &Layer->Vertical_Offset);
History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_Start), &Layer->Frame_Start);
History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_End), &Layer->Frame_End);
- Layer->Vertical_Offset = SortEntry.SortedOffset;
Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Layer->Frame_Start, &Layer->Frame_End);
}
}
@@ -1367,33 +1531,26 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
History_Entry_End(Memory);
}
}
- ImGui::PopID();
- }
-
- }
-
- // Check if any layers are precomps; we want to test hit detection for them _after_ the layers in front.
- for (int i = 0; i < SortedCompInfo.LayerCount; i++)
- {
- ImGui::PushID(i);
- sorted_layer SortEntry = SortedLayerInfo[i];
- uint32 Index_Physical = SortEntry.Block_Layer_Index;
- block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
+ // Keyframe view
+ uint32 Channel = 0;
+ for (int h = 0; h < AmountOf(Layer->Property); h++) {
+ property_channel *Property = &Layer->Property[h];
+ if (Property->IsToggled) {
+ // sorted_property_info *InfoLocation = SortedPropertyInfo + (i * 7) + h;
+ ImVec2 GraphPos(TimelineAbsolutePos.x, Layer_ScreenPos_Min.y + (Layer_ScreenSize.y * 2) + (Layer_ScreenSize.y * Channel));
+ uint16 *ArrayLocation = SortedPropertyArray + (i * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK);
+ ImGui_Timeline_DrawKeySheet(File, State, Memory, UI, io, draw_list, Property, ArrayLocation,
+ Increment, GraphPos, TimelineMoveSize, TimelineZoomSize,
+ TimelineSize, TimelineSizeWithBorder, LayerIncrement);
+ Channel++;
+ }
+ }
+ }
- int32 Frame_Start = Layer->Frame_Start;
- int32 Frame_End = Layer->Frame_End;
- real32 Vertical_Offset = SortEntry.SortedOffset;
- if (Layer->IsSelected)
- Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End);
- ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset);
- ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height);
+ //
- ImVec2 Layer_LocalPos_Ratio = (Layer_LocalPos * Increment);
- ImVec2 Layer_LocalSize_Ratio = Layer_LocalSize * Increment;
- ImVec2 Layer_ScreenPos_Min = TimelineAbsolutePos + TimelineMoveSize + (Layer_LocalPos_Ratio * TimelineZoomSize);
- ImVec2 Layer_ScreenPos_Max = TimelineAbsolutePos + TimelineMoveSize + ((Layer_LocalPos_Ratio + Layer_LocalSize_Ratio) * TimelineZoomSize);
- ImVec2 Layer_ScreenSize = Layer_ScreenPos_Max - Layer_ScreenPos_Min;
+ // Precomp recursion
if (Layer->IsPrecomp && Layer->Precomp_Toggled) {
@@ -1404,7 +1561,9 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
block_layer *Layer_Bottom = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Precomp_SortedLayerInfo[0].Block_Layer_Index);
real32 SmallestY = Layer_Top->Vertical_Offset;
real32 LargestY = Layer_Bottom->Vertical_Offset;
- real32 PrecompHeight = LargestY - SmallestY + 1;
+ // Layer_Evaluate_Display(Layer_Top, SortedLayerArray, SortedCompArray, Precomp_SortedLayerInfo, Precomp_SortedCompInfo.LayerCount - 1, &SmallestY);
+ // Layer_Evaluate_Display(Layer_Bottom, SortedLayerArray, SortedCompArray, Precomp_SortedLayerInfo, 0, &LargestY);
+ real32 PrecompHeight = LargestY - SmallestY + 2;
ImVec2 MinClipPos = ImVec2(Layer_ScreenPos_Min.x, Layer_ScreenPos_Max.y);
ImVec2 MaxClipPos = ImVec2(Layer_ScreenPos_Max.x, MinClipPos.y + (PrecompHeight * Increment.y * TimelineZoomSize.y));
@@ -1412,79 +1571,33 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
ImVec2 Layer_LocalPos_Screen = Layer_LocalPos_Ratio * TimelineZoomSize;
- ImVec2 NestedTimelineAbsolutePos = TimelineAbsolutePos + Layer_LocalPos_Screen - ImVec2(0, SmallestY * Increment.y * TimelineZoomSize.y) + ImVec2(0, Layer_ScreenSize.y);
+ ImVec2 NestedTimelineAbsolutePos = TimelineAbsolutePos + Layer_LocalPos_Screen - ImVec2(0, SmallestY * Increment.y * TimelineZoomSize.y) + ImVec2(0, Layer_ScreenSize.y * 1.5);
ImGui::PushClipRect(MinClipPos, MaxClipPos, true);
draw_list->PushClipRect(MinClipPos, MaxClipPos, true);
ImGui_Timeline_DrawPrecomp(File, State, Memory, UI, io, draw_list, Layer->Block_Source_Index,
Increment, NestedTimelineAbsolutePos, TimelineMoveSize, TimelineZoomSize,
TimelineSize, TimelineSizeWithBorder, LayerIncrement,
- SortedCompArray, SortedLayerArray);
+ SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray);
draw_list->PopClipRect();
ImGui::PopClipRect();
}
- ImGui::PopID();
- }
-
- // TODO(fox): Draw calls are executed in reverse order, so we need another iteration to draw layers on top of precomps.
- // The ImDrawListSplitter API can probably do this without another iteration.
-
- for (int i = 0; i < SortedCompInfo.LayerCount; i++)
- {
- sorted_layer SortEntry = SortedLayerInfo[i];
- uint32 Index_Physical = SortEntry.Block_Layer_Index;
- block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
-
- int32 Frame_Start = Layer->Frame_Start;
- int32 Frame_End = Layer->Frame_End;
- real32 Vertical_Offset = SortEntry.SortedOffset;
- if (Layer->IsSelected)
- Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End);
- ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset);
- ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height);
-
- ImVec2 Layer_LocalPos_Ratio = (Layer_LocalPos * Increment);
- ImVec2 Layer_LocalSize_Ratio = Layer_LocalSize * Increment;
- ImVec2 Layer_ScreenPos_Min = TimelineAbsolutePos + TimelineMoveSize + (Layer_LocalPos_Ratio * TimelineZoomSize);
- ImVec2 Layer_ScreenPos_Max = TimelineAbsolutePos + TimelineMoveSize + ((Layer_LocalPos_Ratio + Layer_LocalSize_Ratio) * TimelineZoomSize);
- ImVec2 Layer_ScreenSize = Layer_ScreenPos_Max - Layer_ScreenPos_Min;
-
- ImU32 LayerColor = 0;
- ImU32 BorderColor = 0;
- LayerColor = ImColor(UI->LayerColors[Layer->ColIndex]);
- BorderColor = ImColor(0.2, 0.2, 0.2, 1.0f);
- /*
- if (UI->TimelineMode == timeline_mode_graph) {
- LayerColor = ImColor(UI->LayerColors[Layer->ColIndex]);
- BorderColor = ImColor(0.3, 0.3, 0.3, 1.0f);
- } else {
- LayerColor = ImColor(UI->LayerColors[Layer->ColIndex]);
- BorderColor = ImColor(0.2, 0.2, 0.2, 1.0f);
- }
- */
- draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max, LayerColor);
- draw_list->AddRect(Layer_ScreenPos_Min, Layer_ScreenPos_Max, BorderColor, 2);
- // block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Layer->Block_String_Index);
- char buf[21];
- sprintf(buf, "%.2f, %.2f", Layer->Vertical_Offset, SortEntry.SortedOffset);
- draw_list->AddText(Layer_ScreenPos_Min, 0xFFFFFFFF, buf);
+ //
- if (Layer->IsSelected) {
- draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(0.25f, 0.25f, 0.25f, 0.5f), 2);
- draw_list->AddRect(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(1.0f, 1.0f, 1.0f, 0.5f), 2);
- }
+ ImGui::PopID();
}
ImGui::PopID();
}
static void
-ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, uint16 *SortedPropertyArray)
+ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io,
+ sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray)
{
if (UI->TimelineMode == timeline_mode_graph)
- ImGui_GraphInfo(File, State, Memory, UI, io);
+ ImGui_GraphInfo(File, State, Memory, UI, io, SortedPropertyInfo, SortedPropertyArray);
ImVec2 FramePadding = ImGui::GetStyle().FramePadding;
ImVec2 ItemSpacing = ImGui::GetStyle().ItemSpacing;
@@ -1556,14 +1669,12 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
DebugWatchVar("TimelineY: ", &TimelineMoveSize.y, d_float);
- ImGui_TimelineHorizontalIncrementDraw(State, UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp, TimelineZoomSize, TimelineMoveSize);
-
ImVec2 Increment = ImVec2((real32)1 / MainComp->Frame_Count, (real32)1 / LayerIncrement);
ImGui_Timeline_DrawPrecomp(File, State, Memory, UI, io, draw_list, File->PrincipalCompIndex,
Increment, TimelineAbsolutePos, TimelineMoveSize, TimelineZoomSize,
TimelineSize, TimelineSizeWithBorder, LayerIncrement,
- SortedCompArray, SortedLayerArray);
+ SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray);
if (UI->TimelineMode == timeline_mode_graph) {
@@ -1582,12 +1693,15 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
DebugWatchVar("movesize: ", &GraphMoveSize.y, d_float);
draw_list->AddRectFilled(WindowMinAbs, WindowMaxAbs,
- IM_COL32(50, 50, 50, 150));
+ IM_COL32(50, 50, 50, 230));
ImGui_Timeline_DrawGraph(File, State, Memory, UI, io, draw_list,
Increment, TimelineAbsolutePos, GraphMoveSize, GraphZoomSize,
- TimelineSize, TimelineSizeWithBorder, LayerIncrement, SortedPropertyArray);
+ TimelineSize, TimelineSizeWithBorder, LayerIncrement, SortedPropertyInfo, SortedPropertyArray);
}
+ ImGui_TimelineHorizontalIncrementDraw(State, UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp, TimelineZoomSize, TimelineMoveSize);
+
+
ImVec2 MouseDelta = io.MouseDelta / TimelineSize;
real32 BarHandleSize = FontHeight;
@@ -1747,10 +1861,15 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
if (LeftClick) {
if (IsItemActivated) {
- if (!io.KeyShift && UI->TimelineMode == timeline_mode_default) Layer_DeselectAll(Memory, File->Layer_Count);
+ if (!io.KeyShift && UI->TimelineMode == timeline_mode_default) Layer_DeselectAll(File, State, Memory);
if (State->Interact_Active == interact_type_keyframe_move ||
State->Interact_Active == interact_type_keyframe_rotate ||
State->Interact_Active == interact_type_keyframe_scale) {
+ // bool32 CommitAction = 0;
+ // if (!CommitAction) {
+ // History_Entry_Commit(Memory, "Delete source");
+ // CommitAction = 1;
+ History_Entry_Commit(Memory, "Add keyframe");
int h = 0, c = 0, i = 0;
while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) {
block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i);
@@ -1765,11 +1884,15 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
if (PointAddress->IsSelected) {
v2 NewPos[3];
Bezier_EvaluateValue(State, PointAddress, NewPos);
- PointAddress->Pos[0].x = NewPos[0].x;
+ History_Action_Swap(Memory, F_Bezier, sizeof(PointAddress->Pos), &PointAddress->Pos);
+ PointAddress->Pos[0] = NewPos[0];
+ PointAddress->Pos[1] = NewPos[1];
+ PointAddress->Pos[2] = NewPos[2];
}
}
}
}
+ History_Entry_End(Memory);
State->Interact_Offset[0] = 0;
State->Interact_Offset[1] = 0;
State->Interact_Offset[2] = 0;
@@ -1844,9 +1967,9 @@ ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Me
State->Interact_Offset[3] = io.MousePos.y;
State->Interact_Active = interact_type_keyframe_move;
} else if (ImGui::IsKeyPressed(ImGuiKey_R)) {
- State->Interact_Offset[2] = io.MousePos.x;
- State->Interact_Offset[3] = io.MousePos.y;
- State->Interact_Active = interact_type_keyframe_rotate;
+ // State->Interact_Offset[2] = io.MousePos.x;
+ // State->Interact_Offset[3] = io.MousePos.y;
+ // State->Interact_Active = interact_type_keyframe_rotate;
} else if (ImGui::IsKeyPressed(ImGuiKey_S)) {
State->Interact_Offset[2] = io.MousePos.x;
State->Interact_Offset[3] = io.MousePos.y;
@@ -1862,6 +1985,7 @@ ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Me
State->Interact_Offset[2] = 0;
State->Interact_Offset[3] = 0;
State->Interact_Active = interact_type_none;
+ State->UpdateFrame = true;
}
}
if (ImGui::IsKeyPressed(ImGuiKey_Space)) {
diff --git a/prenderer.cpp b/prenderer.cpp
index 58e1b22..aa44a5a 100644
--- a/prenderer.cpp
+++ b/prenderer.cpp
@@ -30,9 +30,9 @@ T_CompPosToLayerPos(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uin
static v2
Transform_ScreenSpaceToLocal(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uint32 SourceWidth, uint32 SourceHeight,
- ui UI, ImVec2 ViewportMin, ImVec2 Point)
+ ImVec2 CompPos, ImVec2 CompZoom, ImVec2 ViewportMin, ImVec2 Point)
{
- v2 CompUV = ImGui_ScreenPointToCompUV(ViewportMin, UI.CompPos, UI.CompZoom, Point);
+ v2 CompUV = ImGui_ScreenPointToCompUV(ViewportMin, CompPos, CompZoom, Point);
v2 LayerUV = T_CompUVToLayerUV(T, FileWidth, FileHeight, SourceWidth, SourceHeight, CompUV);
return V2(LayerUV.x * SourceWidth, LayerUV.y * SourceHeight);
}
@@ -260,7 +260,26 @@ Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegio
static void
RenderLayers(render_entry Entry) {
- Fallback_RenderLayer(*(transform_info *)Entry.RenderData, Entry.OutputBuffer, Entry.RenderRegion);
+ switch (Entry.RenderType)
+ {
+ case render_type_main:
+ {
+ Fallback_RenderLayer(*(transform_info *)Entry.RenderData, Entry.OutputBuffer, Entry.RenderRegion);
+ } break;
+ case render_type_direct:
+ {
+ Assert(0);
+ // Fallback_RenderDirect(*(direct_info *)Entry.RenderData, Entry.OutputBuffer, Entry.RenderRegion);
+ } break;
+ case render_type_brush:
+ {
+ PaintTest_AVX2(*(brush_info *)Entry.RenderData, Entry.OutputBuffer, Entry.RenderRegion);
+ } break;
+ default:
+ {
+ Assert(0);
+ }
+ }
#if 0
#if ARM
Fallback_RenderLayer(RenderData->TransformInfo[i], RenderInfo->CompBuffer, RenderRegion);
@@ -274,17 +293,17 @@ RenderLayers(render_entry Entry) {
}
static void
-Renderer_Start(void *Data, void *OutputBuffer, rectangle RenderRegion)
+Renderer_Start(void *Data, void *OutputBuffer, render_type RenderType, rectangle RenderRegion)
{
// CPU
- Threading_BitmapOp(Data, OutputBuffer, RenderRegion);
+ Threading_BitmapOp(Data, OutputBuffer, RenderType, RenderRegion);
}
static void
-Renderer_Check(bool32 *Test)
+Renderer_Check(bool32 *Test, render_type RenderType)
{
// CPU
- *Test = Threading_IsActive();
+ *Test = Threading_IsActive(RenderType);
}
@@ -351,7 +370,6 @@ Transform_Calculate(project_state *State, memory *Memory, project_data *File, bl
if (Points[i].x > MaxX) { MaxX = Points[i].x; }
if (Points[i].y > MaxY) { MaxY = Points[i].y; }
}
-
TransformInfo.XAxisPX = XLengthSq*XAxis.x;
TransformInfo.XAxisPY = XLengthSq*XAxis.y;
TransformInfo.YAxisPX = YLengthSq*YAxis.x;
@@ -373,15 +391,137 @@ Transform_Calculate(project_state *State, memory *Memory, project_data *File, bl
TransformInfo.OriginY = Origin.y;
TransformInfo.BufferPitch = Comp->Width*Comp->BytesPerPixel;
TransformInfo.LayerPitch = Width*BytesPerPixel;
- TransformInfo.ClipRect = {MinX - (MinX & 3), MinY, MaxX + 1, MaxY + 1};
+ TransformInfo.ClipRect = {MinX, MinY, MaxX, MaxY};
TransformInfo.IsAdjustment = Layer->IsAdjustment;
return TransformInfo;
}
+// NOTE(fox): is this too ridiculous? i don't trust inline
+#define Fallback_Blend() \
+ switch (T.BlendMode)\
+ {\
+ case blend_normal:\
+ {\
+ } break;\
+ case blend_multiply:\
+ {\
+ R_Blend = R_Dest * R_Col;\
+ G_Blend = G_Dest * G_Col;\
+ B_Blend = B_Dest * B_Col;\
+ } break;\
+ case blend_colorburn:\
+ {\
+ /* NOTE(fox): Padding to prevent actual crashing from zero division */ \
+ R_Blend = 1.0f - ((1.0f - R_Dest) / (R_Col + 0.001f));\
+ G_Blend = 1.0f - ((1.0f - G_Dest) / (G_Col + 0.001f));\
+ B_Blend = 1.0f - ((1.0f - B_Dest) / (B_Col + 0.001f));\
+ } break;\
+ case blend_linearburn:\
+ {\
+ R_Blend = (R_Dest + R_Col) - 1.0f;\
+ G_Blend = (G_Dest + G_Col) - 1.0f;\
+ B_Blend = (B_Dest + B_Col) - 1.0f;\
+ } break;\
+ case blend_add:\
+ {\
+ R_Blend = R_Dest + R_Col;\
+ G_Blend = G_Dest + G_Col;\
+ B_Blend = B_Dest + B_Col;\
+ } break;\
+ case blend_screen:\
+ {\
+ R_Blend = 1.0f - ((1.0f - R_Dest) * (1.0f - R_Col));\
+ G_Blend = 1.0f - ((1.0f - G_Dest) * (1.0f - G_Col));\
+ B_Blend = 1.0f - ((1.0f - B_Dest) * (1.0f - B_Col));\
+ } break;\
+ case blend_overlay:\
+ {\
+ if (R_Dest < 0.5) {\
+ R_Blend = 2.0f * R_Dest * R_Col;\
+ } else {\
+ R_Blend = 1.0f - (2.0f * (1.0f - R_Dest) * (1.0f - R_Col));\
+ }\
+ if (G_Dest < 0.5) {\
+ G_Blend = 2.0f * G_Dest * G_Col;\
+ } else {\
+ G_Blend = 1.0f - (2.0f * (1.0f - G_Dest) * (1.0f - G_Col));\
+ }\
+ if (B_Dest < 0.5) {\
+ B_Blend = 2.0f * B_Dest * B_Col;\
+ } else {\
+ B_Blend = 1.0f - (2.0f * (1.0f - B_Dest) * (1.0f - B_Col));\
+ }\
+ } break;\
+ case blend_softlight:\
+ {\
+ /* using Pegtop's equation */ \
+ R_Blend = ((1.0f - R_Col * 2) * R_Dest * R_Dest) + (R_Col * 2 * R_Dest);\
+ G_Blend = ((1.0f - G_Col * 2) * G_Dest * G_Dest) + (G_Col * 2 * G_Dest);\
+ B_Blend = ((1.0f - B_Col * 2) * B_Dest * B_Dest) + (B_Col * 2 * B_Dest);\
+ } break;\
+ case blend_hardlight:\
+ {\
+ if (R_Dest > 0.5) {\
+ R_Blend = 2.0f * R_Dest * R_Col;\
+ } else {\
+ R_Blend = 1.0f - (2.0f * (1.0f - R_Dest) * (1.0f - R_Col));\
+ }\
+ if (G_Dest > 0.5) {\
+ G_Blend = 2.0f * G_Dest * G_Col;\
+ } else {\
+ G_Blend = 1.0f - (2.0f * (1.0f - G_Dest) * (1.0f - G_Col));\
+ }\
+ if (B_Dest > 0.5) {\
+ B_Blend = 2.0f * B_Dest * B_Col;\
+ } else {\
+ B_Blend = 1.0f - (2.0f * (1.0f - B_Dest) * (1.0f - B_Col));\
+ }\
+ } break;\
+ case blend_subtract:\
+ {\
+ R_Blend = R_Dest - R_Col;\
+ G_Blend = G_Dest - G_Col;\
+ B_Blend = B_Dest - B_Col;\
+ } break;\
+ case blend_divide:\
+ {\
+ R_Blend = R_Dest / (R_Col + 0.001f);\
+ G_Blend = G_Dest / (G_Col + 0.001f);\
+ B_Blend = B_Dest / (B_Col + 0.001f);\
+ } break;\
+ case blend_difference:\
+ {\
+ if (R_Col - R_Dest > 0) {\
+ R_Blend = R_Col - R_Dest;\
+ } else {\
+ R_Blend = R_Dest - R_Col;\
+ }\
+ if (G_Col - G_Dest > 0) {\
+ G_Blend = G_Col - G_Dest;\
+ } else {\
+ G_Blend = G_Dest - G_Col;\
+ }\
+ if (B_Col - B_Dest > 0) {\
+ B_Blend = B_Col - B_Dest;\
+ } else {\
+ B_Blend = B_Dest - B_Col;\
+ }\
+ } break;\
+ }\
+\
+ R_Blend = (R_Dest * (1.0f - LayerAlpha)) + (R_Blend * LayerAlpha);\
+ G_Blend = (G_Dest * (1.0f - LayerAlpha)) + (G_Blend * LayerAlpha);\
+ B_Blend = (B_Dest * (1.0f - LayerAlpha)) + (B_Blend * LayerAlpha);\
+\
+ if (T.BlendMode == blend_normal)\
+ A_Blend = A_Dest + LayerAlpha;\
+ else\
+ A_Blend = A_Dest;\
+
static void
-Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegion)
+Fallback_RenderDirect(transform_info T, void *OutputBuffer, rectangle RenderRegion)
{
rectangle LayerBounds = ClipRectangle( T.ClipRect, RenderRegion);
@@ -390,15 +530,84 @@ Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegio
for (int16 Y = LayerBounds.Min.y; Y < LayerBounds.Max.y; Y++)
{
- real32 StartVectorY = (real32)Y - T.OriginY;
-
for (int16 X = LayerBounds.Min.x; X < LayerBounds.Max.x; X++)
{
+ uint16 LX = X;
+ uint16 LY = Y;
+ uint16 LXPlus = Ceil(X+1, (uint32)T.LayerWidth - 1);
+ uint16 LYPlus = Ceil(Y+1, (uint32)T.LayerHeight - 1);
+
+ uint8 *TexPTR0 = ((uint8 *)T.SourceBuffer + ((uint16)T.LayerPitch * LY) + (LX * (uint16)T.LayerBytesPerPixel));
+ uint32 PixelA = *(uint32 *)TexPTR0;
+
+ real32 TexRA = (real32)(*(uint32 *)(TexPTR0 + T.LayerBits.ByteOffset * 0) & T.LayerBits.MaskPixel) * T.LayerBits.Normalized;
+ real32 TexGA = (real32)(*(uint32 *)(TexPTR0 + T.LayerBits.ByteOffset * 1) & T.LayerBits.MaskPixel) * T.LayerBits.Normalized;
+ real32 TexBA = (real32)(*(uint32 *)(TexPTR0 + T.LayerBits.ByteOffset * 2) & T.LayerBits.MaskPixel) * T.LayerBits.Normalized;
+ real32 TexAA = (real32)(*(uint32 *)(TexPTR0 + T.LayerBits.ByteOffset * 3) & T.LayerBits.MaskPixel) * T.LayerBits.Normalized;
+
+ real32 LayerAlpha = TexAA * 1; // brush opacity
+
+ real32 R_Col = TexRA;
+ real32 G_Col = TexGA;
+ real32 B_Col = TexBA;
+ real32 A_Col = TexAA;
+
+ real32 R_Blend = TexRA;
+ real32 G_Blend = TexGA;
+ real32 B_Blend = TexBA;
+ real32 A_Blend = TexAA;
+
+ uint8 *DestPixel =((uint8 *)OutputBuffer + ((uint16)Y * (uint16)T.BufferPitch) + ((uint16)X * (uint16)T.BufferBytesPerPixel));
+
+ uint32 *R_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 0);
+ uint32 *G_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 1);
+ uint32 *B_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 2);
+ uint32 *A_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 3);
+
+ if (LayerAlpha != 1.0f || T.BlendMode != blend_normal) {
+
+ real32 R_Dest = (real32)(*R_DestAddress & T.BufferBits.MaskPixel) * T.BufferBits.Normalized;
+ real32 G_Dest = (real32)(*G_DestAddress & T.BufferBits.MaskPixel) * T.BufferBits.Normalized;
+ real32 B_Dest = (real32)(*B_DestAddress & T.BufferBits.MaskPixel) * T.BufferBits.Normalized;
+ real32 A_Dest = (real32)(*A_DestAddress & T.BufferBits.MaskPixel) * T.BufferBits.Normalized;
+
+ Fallback_Blend();
+ }
+
+ uint32 R_Out = (uint32)(Normalize(R_Blend) * T.BufferBits.Bits);
+ uint32 G_Out = (uint32)(Normalize(G_Blend) * T.BufferBits.Bits);
+ uint32 B_Out = (uint32)(Normalize(B_Blend) * T.BufferBits.Bits);
+ uint32 A_Out = (uint32)(Normalize(A_Blend) * T.BufferBits.Bits);
+
+ *R_DestAddress = (*R_DestAddress & ~T.BufferBits.MaskPixel) | R_Out;
+ *G_DestAddress = (*G_DestAddress & ~T.BufferBits.MaskPixel) | G_Out;
+ *B_DestAddress = (*B_DestAddress & ~T.BufferBits.MaskPixel) | B_Out;
+ *A_DestAddress = (*A_DestAddress & ~T.BufferBits.MaskPixel) | A_Out;
+ }
+ }
+}
+static void
+Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegion)
+{
+ rectangle LayerBounds = ClipRectangle( T.ClipRect, RenderRegion);
+
+ Assert(LayerBounds.Max.x <= T.BufferWidth);
+ Assert(LayerBounds.Max.y <= T.BufferHeight);
+
+ for (int Y = LayerBounds.Min.y; Y < LayerBounds.Max.y; Y++)
+ {
+ real32 StartVectorY = (real32)Y - T.OriginY;
+
+ for (int X = LayerBounds.Min.x; X < LayerBounds.Max.x; X++)
+ {
real32 StartVectorX = X - T.OriginX;
real32 U = (StartVectorX * T.XAxisPX) + (StartVectorY * T.XAxisPY);
real32 V = (StartVectorX * T.YAxisPX) + (StartVectorY * T.YAxisPY);
+ if (X == T.BufferWidth)
+ int why = 0;
+
if (U < 1.0f && U >= 0.0f && V < 1.0f && V >= 0.0f) {
real32 TexXFull = U * T.LayerWidth;
@@ -418,15 +627,15 @@ Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegio
uint32 XLookup, YLookup, PixelToSeek;
- uint16 LX = TexXInt;
- uint16 LY = TexYInt;
- uint16 LXPlus = Ceil(TexXInt+1, (uint32)T.LayerWidth - 1);
- uint16 LYPlus = Ceil(TexYInt+1, (uint32)T.LayerHeight - 1);
+ uint32 LX = TexXInt;
+ uint32 LY = TexYInt;
+ uint32 LXPlus = Ceil(TexXInt+1, (uint32)T.LayerWidth - 1);
+ uint32 LYPlus = Ceil(TexYInt+1, (uint32)T.LayerHeight - 1);
- uint8 *TexPTR0 = ((uint8 *)T.SourceBuffer + ((uint16)T.LayerPitch * LY) + (LX * (uint16)T.LayerBytesPerPixel));
- uint8 *TexPTR1 = ((uint8 *)T.SourceBuffer + ((uint16)T.LayerPitch * LY) + (LXPlus * (uint16)T.LayerBytesPerPixel));
- uint8 *TexPTR2 = ((uint8 *)T.SourceBuffer + ((uint16)T.LayerPitch * LYPlus) + (LX * (uint16)T.LayerBytesPerPixel));
- uint8 *TexPTR3 = ((uint8 *)T.SourceBuffer + ((uint16)T.LayerPitch * LYPlus) + (LXPlus * (uint16)T.LayerBytesPerPixel));
+ uint8 *TexPTR0 = ((uint8 *)T.SourceBuffer + ((uint32)T.LayerPitch * LY) + (LX * (uint32)T.LayerBytesPerPixel));
+ uint8 *TexPTR1 = ((uint8 *)T.SourceBuffer + ((uint32)T.LayerPitch * LY) + (LXPlus * (uint32)T.LayerBytesPerPixel));
+ uint8 *TexPTR2 = ((uint8 *)T.SourceBuffer + ((uint32)T.LayerPitch * LYPlus) + (LX * (uint32)T.LayerBytesPerPixel));
+ uint8 *TexPTR3 = ((uint8 *)T.SourceBuffer + ((uint32)T.LayerPitch * LYPlus) + (LXPlus * (uint32)T.LayerBytesPerPixel));
uint32 PixelA = *(uint32 *)TexPTR0;
uint32 PixelB = *(uint32 *)TexPTR1;
@@ -515,12 +724,13 @@ Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegio
real32 B_Blend = B_Col;
real32 A_Blend = A_Col;
- uint8 *DestPixel =((uint8 *)OutputBuffer + ((uint16)Y * (uint16)T.BufferPitch) + ((uint16)X * (uint16)T.BufferBytesPerPixel));
+ uint8 *DestPixel =((uint8 *)OutputBuffer + ((uint32)Y * (uint32)T.BufferPitch) + ((uint32)X * (uint32)T.BufferBytesPerPixel));
+ Assert(X != (T.BufferWidth));
- uint32 *R_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 0);
- uint32 *G_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 1);
- uint32 *B_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 2);
- uint32 *A_DestAddress = (uint32 *)(DestPixel + T.BufferBits.ByteOffset * 3);
+ uint8 *R_DestAddress = (DestPixel + T.BufferBits.ByteOffset * 0);
+ uint8 *G_DestAddress = (DestPixel + T.BufferBits.ByteOffset * 1);
+ uint8 *B_DestAddress = (DestPixel + T.BufferBits.ByteOffset * 2);
+ uint8 *A_DestAddress = (DestPixel + T.BufferBits.ByteOffset * 3);
if (LayerAlpha != 1.0f || T.BlendMode != blend_normal) {
@@ -529,136 +739,18 @@ Fallback_RenderLayer(transform_info T, void *OutputBuffer, rectangle RenderRegio
real32 B_Dest = (real32)(*B_DestAddress & T.BufferBits.MaskPixel) * T.BufferBits.Normalized;
real32 A_Dest = (real32)(*A_DestAddress & T.BufferBits.MaskPixel) * T.BufferBits.Normalized;
- switch (T.BlendMode)
- {
- case blend_normal:
- {
- } break;
- case blend_multiply:
- {
- R_Blend = R_Dest * R_Col;
- G_Blend = G_Dest * G_Col;
- B_Blend = B_Dest * B_Col;
- } break;
- case blend_colorburn:
- {
- // NOTE(fox): Padding to prevent actual crashing from zero division
- R_Blend = 1.0f - ((1.0f - R_Dest) / (R_Col + 0.001f));
- G_Blend = 1.0f - ((1.0f - G_Dest) / (G_Col + 0.001f));
- B_Blend = 1.0f - ((1.0f - B_Dest) / (B_Col + 0.001f));
- } break;
- case blend_linearburn:
- {
- R_Blend = (R_Dest + R_Col) - 1.0f;
- G_Blend = (G_Dest + G_Col) - 1.0f;
- B_Blend = (B_Dest + B_Col) - 1.0f;
- } break;
- case blend_add:
- {
- R_Blend = R_Dest + R_Col;
- G_Blend = G_Dest + G_Col;
- B_Blend = B_Dest + B_Col;
- } break;
- case blend_screen:
- {
- R_Blend = 1.0f - ((1.0f - R_Dest) * (1.0f - R_Col));
- G_Blend = 1.0f - ((1.0f - G_Dest) * (1.0f - G_Col));
- B_Blend = 1.0f - ((1.0f - B_Dest) * (1.0f - B_Col));
- } break;
- case blend_overlay:
- {
- if (R_Dest < 0.5) {
- R_Blend = 2.0f * R_Dest * R_Col;
- } else {
- R_Blend = 1.0f - (2.0f * (1.0f - R_Dest) * (1.0f - R_Col));
- }
- if (G_Dest < 0.5) {
- G_Blend = 2.0f * G_Dest * G_Col;
- } else {
- G_Blend = 1.0f - (2.0f * (1.0f - G_Dest) * (1.0f - G_Col));
- }
- if (B_Dest < 0.5) {
- B_Blend = 2.0f * B_Dest * B_Col;
- } else {
- B_Blend = 1.0f - (2.0f * (1.0f - B_Dest) * (1.0f - B_Col));
- }
- } break;
- case blend_softlight:
- {
- // using Pegtop's equation
- R_Blend = ((1.0f - R_Col * 2) * R_Dest * R_Dest) + (R_Col * 2 * R_Dest);
- G_Blend = ((1.0f - G_Col * 2) * G_Dest * G_Dest) + (G_Col * 2 * G_Dest);
- B_Blend = ((1.0f - B_Col * 2) * B_Dest * B_Dest) + (B_Col * 2 * B_Dest);
- } break;
- case blend_hardlight:
- {
- if (R_Dest > 0.5) {
- R_Blend = 2.0f * R_Dest * R_Col;
- } else {
- R_Blend = 1.0f - (2.0f * (1.0f - R_Dest) * (1.0f - R_Col));
- }
- if (G_Dest > 0.5) {
- G_Blend = 2.0f * G_Dest * G_Col;
- } else {
- G_Blend = 1.0f - (2.0f * (1.0f - G_Dest) * (1.0f - G_Col));
- }
- if (B_Dest > 0.5) {
- B_Blend = 2.0f * B_Dest * B_Col;
- } else {
- B_Blend = 1.0f - (2.0f * (1.0f - B_Dest) * (1.0f - B_Col));
- }
- } break;
- case blend_subtract:
- {
- R_Blend = R_Dest - R_Col;
- G_Blend = G_Dest - G_Col;
- B_Blend = B_Dest - B_Col;
- } break;
- case blend_divide:
- {
- R_Blend = R_Dest / (R_Col + 0.001f);
- G_Blend = G_Dest / (G_Col + 0.001f);
- B_Blend = B_Dest / (B_Col + 0.001f);
- } break;
- case blend_difference:
- {
- if (R_Col - R_Dest > 0) {
- R_Blend = R_Col - R_Dest;
- } else {
- R_Blend = R_Dest - R_Col;
- }
- if (G_Col - G_Dest > 0) {
- G_Blend = G_Col - G_Dest;
- } else {
- G_Blend = G_Dest - G_Col;
- }
- if (B_Col - B_Dest > 0) {
- B_Blend = B_Col - B_Dest;
- } else {
- B_Blend = B_Dest - B_Col;
- }
- } break;
- }
-
- R_Blend = (R_Dest * (1.0f - LayerAlpha)) + (R_Blend * LayerAlpha);
- G_Blend = (G_Dest * (1.0f - LayerAlpha)) + (G_Blend * LayerAlpha);
- B_Blend = (B_Dest * (1.0f - LayerAlpha)) + (B_Blend * LayerAlpha);
-
- if (T.BlendMode == blend_normal)
- A_Blend = A_Dest + LayerAlpha;
- else
- A_Blend = A_Dest;
+ Fallback_Blend();
}
- uint32 R_Out = (uint32)(Normalize(R_Blend) * T.BufferBits.Bits);
- uint32 G_Out = (uint32)(Normalize(G_Blend) * T.BufferBits.Bits);
- uint32 B_Out = (uint32)(Normalize(B_Blend) * T.BufferBits.Bits);
- uint32 A_Out = (uint32)(Normalize(A_Blend) * T.BufferBits.Bits);
+ uint8 R_Out = (uint8)(Normalize(R_Blend) * T.BufferBits.Bits);
+ uint8 G_Out = (uint8)(Normalize(G_Blend) * T.BufferBits.Bits);
+ uint8 B_Out = (uint8)(Normalize(B_Blend) * T.BufferBits.Bits);
+ uint8 A_Out = (uint8)(Normalize(A_Blend) * T.BufferBits.Bits);
- *R_DestAddress = (*R_DestAddress & ~T.BufferBits.MaskPixel) | R_Out;
- *G_DestAddress = (*G_DestAddress & ~T.BufferBits.MaskPixel) | G_Out;
- *B_DestAddress = (*B_DestAddress & ~T.BufferBits.MaskPixel) | B_Out;
- *A_DestAddress = (*A_DestAddress & ~T.BufferBits.MaskPixel) | A_Out;
+ *R_DestAddress = R_Out;
+ *G_DestAddress = G_Out;
+ *B_DestAddress = B_Out;
+ *A_DestAddress = A_Out;
// *R_DestAddress = 255;
// *G_DestAddress = 255;
// *B_DestAddress = 255;
@@ -1781,274 +1873,5 @@ SSE2_RenderLayer(transform_info T, comp_buffer *Buffer, rectangle RenderRegion)
}
}
-
-#endif
-
-static void
-Fallback_RenderLayer(transform_info T, comp_buffer *Buffer, rectangle RenderRegion)
-{
- rectangle LayerBounds = ClipRectangle( T.ClipRect, RenderRegion);
-
- Assert(LayerBounds.Max.x <= Buffer->Width);
- Assert(LayerBounds.Max.y <= Buffer->Height);
-
- uint16 WidthP, HeightP;
- Bitmap_CalcPackedDimensions(Buffer->Width, Buffer->Height, &WidthP, &HeightP);
-
- real32 Normalized255 = 1 / 255.0f;
-
- for (int16 Y = LayerBounds.Min.y; Y < LayerBounds.Max.y; Y++)
- {
- real32 StartVectorY = (real32)Y - T.OriginY;
-
- for (int16 X = LayerBounds.Min.x; X < LayerBounds.Max.x; X++)
- {
-
- real32 StartVectorX = X - T.OriginX;
- real32 U = (StartVectorX * T.XAxisPX) + (StartVectorY * T.XAxisPY);
- real32 V = (StartVectorX * T.YAxisPX) + (StartVectorY * T.YAxisPY);
-
- if (U < 1.0f && U >= 0.0f && V < 1.0f && V >= 0.0f) {
-
- real32 TexXFull = U * T.LayerWidth;
- uint32 TexXInt = (uint32)TexXFull;
- real32 TexX = TexXFull - TexXInt;
-
- real32 TexYFull = V * T.LayerHeight;
- uint32 TexYInt = (uint32)TexYFull;
- real32 TexY = TexYFull - TexYInt;
-
- real32 TexXInv = 1 - TexX;
- real32 TexYInv = 1 - TexY;
- real32 TexBothXInv = TexXInv * TexY;
- real32 TexBothYInv = TexX * TexYInv;
- real32 TexBoth = TexY * TexX;
- real32 TexBothInv = TexXInv * TexYInv;
-
- uint32 XLookup, YLookup, PixelToSeek;
-
- uint16 LX = TexXInt;
- uint16 LY = TexYInt;
- uint16 LXPlus = Ceil(TexXInt+1, (uint32)T.LayerWidth - 1);
- uint16 LYPlus = Ceil(TexYInt+1, (uint32)T.LayerHeight - 1);
-
-#if PACKEDRGB
- // TODO(fox): Be careful with the BytesPerPixel here! It's the
- // buffer's, not the layer's (currently everything is 4 bytes
- // per pixel).
- XLookup = (LX >> 2)*16 + (LX % 4);
- YLookup = (LY >> 2)*(T.FullLayerWidth*4) + (LY % 4)*4;
- PixelToSeek = XLookup + YLookup;
- uint32 PixelA = *(uint32 *)((uint8 *)T.SourceBuffer + PixelToSeek*Buffer->BytesPerPixel);
-
- XLookup = (LXPlus >> 2)*16 + (LXPlus % 4);
- YLookup = (LY >> 2)*(T.FullLayerWidth*4) + (LY % 4)*4;
- PixelToSeek = XLookup + YLookup;
- uint32 PixelB = *(uint32 *)((uint8 *)T.SourceBuffer + PixelToSeek*Buffer->BytesPerPixel);
-
- XLookup = (LX >> 2)*16 + (LX % 4);
- YLookup = (LYPlus >> 2)*(T.FullLayerWidth*4) + (LYPlus % 4)*4;
- PixelToSeek = XLookup + YLookup;
- uint32 PixelC = *(uint32 *)((uint8 *)T.SourceBuffer + PixelToSeek*Buffer->BytesPerPixel);
-
- XLookup = (LXPlus >> 2)*16 + (LXPlus % 4);
- YLookup = (LYPlus >> 2)*(T.FullLayerWidth*4) + (LYPlus % 4)*4;
- PixelToSeek = XLookup + YLookup;
- uint32 PixelD = *(uint32 *)((uint8 *)T.SourceBuffer + PixelToSeek*Buffer->BytesPerPixel);
-
- XLookup = (X >> 2)*16 + (X % 4);
- YLookup = (Y >> 2)*(WidthP*4) + (Y % 4)*4;
- PixelToSeek = XLookup + YLookup;
- uint32 *Pixel = (uint32 *)((uint8 *)Buffer->PackedBuffer + PixelToSeek*Buffer->BytesPerPixel);
-
-#else
- uint8 *TexPTR0 = ((uint8 *)T.SourceBuffer + (uint16)T.LayerPitch*LY + LX*Buffer->BytesPerPixel);
- uint8 *TexPTR1 = ((uint8 *)T.SourceBuffer + (uint16)T.LayerPitch*LY + LXPlus*Buffer->BytesPerPixel);
- uint8 *TexPTR2 = ((uint8 *)T.SourceBuffer + (uint16)T.LayerPitch*LYPlus + LX*Buffer->BytesPerPixel);
- uint8 *TexPTR3 = ((uint8 *)T.SourceBuffer + (uint16)T.LayerPitch*LYPlus + LXPlus*Buffer->BytesPerPixel);
-
- uint32 PixelA = *(uint32 *)TexPTR0;
- uint32 PixelB = *(uint32 *)TexPTR1;
- uint32 PixelC = *(uint32 *)TexPTR2;
- uint32 PixelD = *(uint32 *)TexPTR3;
-
- uint32 *Pixel = (uint32 *)((uint8 *)Buffer->UnpackedBuffer + Y*T.BufferPitch + X*Buffer->BytesPerPixel);
#endif
- real32 TexRA = (real32)(PixelA & 0xFF) * Normalized255;
- real32 TexRB = (real32)(PixelB & 0xFF) * Normalized255;
- real32 TexRC = (real32)(PixelC & 0xFF) * Normalized255;
- real32 TexRD = (real32)(PixelD & 0xFF) * Normalized255;
-
- real32 TexGA = (real32)((PixelA >> 8) & 0xFF) * Normalized255;
- real32 TexGB = (real32)((PixelB >> 8) & 0xFF) * Normalized255;
- real32 TexGC = (real32)((PixelC >> 8) & 0xFF) * Normalized255;
- real32 TexGD = (real32)((PixelD >> 8) & 0xFF) * Normalized255;
-
- real32 TexBA = (real32)((PixelA >> 16) & 0xFF) * Normalized255;
- real32 TexBB = (real32)((PixelB >> 16) & 0xFF) * Normalized255;
- real32 TexBC = (real32)((PixelC >> 16) & 0xFF) * Normalized255;
- real32 TexBD = (real32)((PixelD >> 16) & 0xFF) * Normalized255;
-
- real32 TexAA = (real32)((PixelA >> 24) & 0xFF) * Normalized255;
- real32 TexAB = (real32)((PixelB >> 24) & 0xFF) * Normalized255;
- real32 TexAC = (real32)((PixelC >> 24) & 0xFF) * Normalized255;
- real32 TexAD = (real32)((PixelD >> 24) & 0xFF) * Normalized255;
-
- real32 R_Col = (TexBothInv * TexRA) + (TexBothYInv * TexRB)
- + (TexBothXInv * TexRC) + (TexBoth * TexRD);
- real32 G_Col = (TexBothInv * TexGA) + (TexBothYInv * TexGB)
- + (TexBothXInv * TexGC) + (TexBoth * TexGD);
- real32 B_Col = (TexBothInv * TexBA) + (TexBothYInv * TexBB)
- + (TexBothXInv * TexBC) + (TexBoth * TexBD);
- real32 A_Col = (TexBothInv * TexAA) + (TexBothYInv * TexAB)
- + (TexBothXInv * TexAC) + (TexBoth * TexAD);
-
- real32 LayerAlpha = A_Col * T.LayerOpacity;
-
- real32 R_Blend = R_Col;
- real32 G_Blend = G_Col;
- real32 B_Blend = B_Col;
- real32 A_Blend = A_Col;
-
- if (LayerAlpha != 1.0f || T.BlendMode != blend_normal) {
-
- real32 R_Dest = (real32)((*Pixel >> 0) & 0xFF) * Normalized255;
- real32 G_Dest = (real32)((*Pixel >> 8) & 0xFF) * Normalized255;
- real32 B_Dest = (real32)((*Pixel >> 16) & 0xFF) * Normalized255;
- real32 A_Dest = (real32)((*Pixel >> 24) & 0xFF) * Normalized255;
-
- switch (T.BlendMode)
- {
- case blend_normal:
- {
- } break;
- case blend_multiply:
- {
- R_Blend = R_Dest * R_Col;
- G_Blend = G_Dest * G_Col;
- B_Blend = B_Dest * B_Col;
- } break;
- case blend_colorburn:
- {
- // NOTE(fox): Padding to prevent actual crashing from zero division
- R_Blend = 1.0f - ((1.0f - R_Dest) / (R_Col + 0.001f));
- G_Blend = 1.0f - ((1.0f - G_Dest) / (G_Col + 0.001f));
- B_Blend = 1.0f - ((1.0f - B_Dest) / (B_Col + 0.001f));
- } break;
- case blend_linearburn:
- {
- R_Blend = (R_Dest + R_Col) - 1.0f;
- G_Blend = (G_Dest + G_Col) - 1.0f;
- B_Blend = (B_Dest + B_Col) - 1.0f;
- } break;
- case blend_add:
- {
- R_Blend = R_Dest + R_Col;
- G_Blend = G_Dest + G_Col;
- B_Blend = B_Dest + B_Col;
- } break;
- case blend_screen:
- {
- R_Blend = 1.0f - ((1.0f - R_Dest) * (1.0f - R_Col));
- G_Blend = 1.0f - ((1.0f - G_Dest) * (1.0f - G_Col));
- B_Blend = 1.0f - ((1.0f - B_Dest) * (1.0f - B_Col));
- } break;
- case blend_overlay:
- {
- if (R_Dest < 0.5) {
- R_Blend = 2.0f * R_Dest * R_Col;
- } else {
- R_Blend = 1.0f - (2.0f * (1.0f - R_Dest) * (1.0f - R_Col));
- }
- if (G_Dest < 0.5) {
- G_Blend = 2.0f * G_Dest * G_Col;
- } else {
- G_Blend = 1.0f - (2.0f * (1.0f - G_Dest) * (1.0f - G_Col));
- }
- if (B_Dest < 0.5) {
- B_Blend = 2.0f * B_Dest * B_Col;
- } else {
- B_Blend = 1.0f - (2.0f * (1.0f - B_Dest) * (1.0f - B_Col));
- }
- } break;
- case blend_softlight:
- {
- // using Pegtop's equation
- R_Blend = ((1.0f - R_Col * 2) * R_Dest * R_Dest) + (R_Col * 2 * R_Dest);
- G_Blend = ((1.0f - G_Col * 2) * G_Dest * G_Dest) + (G_Col * 2 * G_Dest);
- B_Blend = ((1.0f - B_Col * 2) * B_Dest * B_Dest) + (B_Col * 2 * B_Dest);
- } break;
- case blend_hardlight:
- {
- if (R_Dest > 0.5) {
- R_Blend = 2.0f * R_Dest * R_Col;
- } else {
- R_Blend = 1.0f - (2.0f * (1.0f - R_Dest) * (1.0f - R_Col));
- }
- if (G_Dest > 0.5) {
- G_Blend = 2.0f * G_Dest * G_Col;
- } else {
- G_Blend = 1.0f - (2.0f * (1.0f - G_Dest) * (1.0f - G_Col));
- }
- if (B_Dest > 0.5) {
- B_Blend = 2.0f * B_Dest * B_Col;
- } else {
- B_Blend = 1.0f - (2.0f * (1.0f - B_Dest) * (1.0f - B_Col));
- }
- } break;
- case blend_subtract:
- {
- R_Blend = R_Dest - R_Col;
- G_Blend = G_Dest - G_Col;
- B_Blend = B_Dest - B_Col;
- } break;
- case blend_divide:
- {
- R_Blend = R_Dest / (R_Col + 0.001f);
- G_Blend = G_Dest / (G_Col + 0.001f);
- B_Blend = B_Dest / (B_Col + 0.001f);
- } break;
- case blend_difference:
- {
- if (R_Col - R_Dest > 0) {
- R_Blend = R_Col - R_Dest;
- } else {
- R_Blend = R_Dest - R_Col;
- }
- if (G_Col - G_Dest > 0) {
- G_Blend = G_Col - G_Dest;
- } else {
- G_Blend = G_Dest - G_Col;
- }
- if (B_Col - B_Dest > 0) {
- B_Blend = B_Col - B_Dest;
- } else {
- B_Blend = B_Dest - B_Col;
- }
- } break;
- }
-
- R_Blend = (R_Dest * (1.0f - LayerAlpha)) + (R_Blend * LayerAlpha);
- G_Blend = (G_Dest * (1.0f - LayerAlpha)) + (G_Blend * LayerAlpha);
- B_Blend = (B_Dest * (1.0f - LayerAlpha)) + (B_Blend * LayerAlpha);
-
- if (T.BlendMode == blend_normal)
- A_Blend = A_Dest + LayerAlpha;
- else
- A_Blend = A_Dest;
- }
-
- uint8 R_Out = (uint8)(Normalize(R_Blend) * 255.0f);
- uint8 G_Out = (uint8)(Normalize(G_Blend) * 255.0f);
- uint8 B_Out = (uint8)(Normalize(B_Blend) * 255.0f);
- uint8 A_Out = (uint8)(Normalize(A_Blend) * 255.0f);
-
- *Pixel = ((A_Out << 24) |
- (B_Out << 16) |
- (G_Out << 8) |
- (R_Out << 0));
- }
- }
- }
-}
#endif
diff --git a/stable_diffusion.cpp b/stable_diffusion.cpp
new file mode 100644
index 0000000..0c42f03
--- /dev/null
+++ b/stable_diffusion.cpp
@@ -0,0 +1,28 @@
+
+static void
+SD_Txt2Txt(sd_state *SD)
+{
+ char JSONPayload[1024];
+ char CurlCommand[1024];
+ char *Test[] = { "prompt", "negative_prompt", "steps", "width", "height", "cfg_scale" };
+ void *Test2[6] = { (void *)SD->Prompt, (void *)SD->NegPrompt,
+ (void *)&SD->Steps, (void *)&SD->Width,
+ (void *)&SD->Height, (void *)&SD->CFG };
+ int Type[6] = { 0, 0, 1, 1, 1, 2};
+ sprintf(JSONPayload, "%s{\n", JSONPayload);
+ for (int i = 0; i < 6; i++) {
+ if (Type[i] == 0) {
+ sprintf(JSONPayload, "%s\"%s\": \"%s\",\n", JSONPayload, Test[i], (char *)Test2[i]);
+ } else if (Type[i] == 1) {
+ sprintf(JSONPayload, "%s\"%s\": %i,\n", JSONPayload, Test[i], *(int *)Test2[i]);
+ } else if (Type[i] == 2) {
+ sprintf(JSONPayload, "%s\"%s\": %.2f,\n", JSONPayload, Test[i], *(real32 *)Test2[i]);
+ } else {
+ Assert(0);
+ }
+ }
+ sprintf(JSONPayload, "%s}\n", JSONPayload);
+ sprintf(CurlCommand, "curl -X POST -H 'Content-Type: application/json' -i '%s/sdapi/v1/txt2img' --data '%s'",
+ SD->ServerAddress, JSONPayload);
+ printf("%s\n", CurlCommand);
+};
diff --git a/stable_diffusion.h b/stable_diffusion.h
new file mode 100644
index 0000000..6e7dd54
--- /dev/null
+++ b/stable_diffusion.h
@@ -0,0 +1,25 @@
+
+
+// curl -X POST -H 'Content-Type: application/json' -i 'http://127.0.0.1:7860/sdapi/v1/txt2img' --data '{
+// "prompt": "cute dinosaur sticker with polka dots",
+// "steps": 50,
+// "sampler_index": "DDIM"
+// }'
+
+#define SD_LEN_PROMPT 256
+#define SD_LEN_ADDRESS 128
+
+struct sd_state
+{
+ char Prompt[256];
+ char NegPrompt[256];
+ char ServerAddress[128];
+ int32 Steps = 25;
+ int32 Width = 512;
+ int32 Height = 512;
+ int32 SamplerIndex = 0;
+ real32 CFG = 7;
+ real32 DenoisingStrength = 0.7;
+ int32 Seed = -1;
+};
+
diff --git a/strings.cpp b/strings.cpp
index ab410b2..0842576 100644
--- a/strings.cpp
+++ b/strings.cpp
@@ -27,7 +27,7 @@ static uint16
String_AddToFile(memory *Memory, char *Char)
{
uint16 FileIndex = Memory_Block_AllocateNew(Memory, F_Strings);
- block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, FileIndex);
+ block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, FileIndex, 0);
History_Action_Block_Swap(Memory, F_Strings, String);
String->Occupied = 1;
uint16 i = 0;
diff --git a/threading.cpp b/threading.cpp
index 84e5463..f1d7284 100644
--- a/threading.cpp
+++ b/threading.cpp
@@ -34,50 +34,58 @@ TestThread(void *ptr)
}
static bool32
-Threading_IsActive()
+Threading_IsActive(render_type RenderType)
{
+ int32 Threads = 16;
+ if (RenderType == render_type_brush)
+ Threads = 4;
uint32 C = SDL_AtomicGet(&CompletedEntries);
- Assert(C < 17);
- return (C == 16) ? false : true;
+ Assert(C < Threads + 1);
+ return (C == Threads) ? false : true;
}
static void
-Threading_BitmapOp(void *Data, void *OutputBuffer, rectangle InitialRenderRegion)
+Threading_BitmapOp(void *Data, void *OutputBuffer, render_type RenderType, rectangle InitialRenderRegion)
{
- uint16 TileWidth = (InitialRenderRegion.Max.x - InitialRenderRegion.Min.x) / 4;
- uint16 TileHeight = (InitialRenderRegion.Max.y - InitialRenderRegion.Min.y) / 4;
+ int i = (RenderType != render_type_brush) ? 4 : 2;
+ uint16 TileWidth = (InitialRenderRegion.Max.x - InitialRenderRegion.Min.x) / i;
+ uint16 TileHeight = (InitialRenderRegion.Max.y - InitialRenderRegion.Min.y) / i;
SDL_AtomicSet(&QueuedEntries, 0);
SDL_AtomicSet(&CurrentEntry, 0);
SDL_AtomicSet(&CompletedEntries, 0);
- for (int y = 0; y < 4; y++) {
- for (int x = 0; x < 4; x++) {
- // if (x == y) {
- rectangle RenderRegion = { TileWidth*x, TileHeight*y, TileWidth + TileWidth*x, TileHeight + TileHeight*y };
+ for (int y = 0; y < i; y++) {
+ for (int x = 0; x < i; x++) {
+ // if ((x == 0 && y == 0)|| RenderType != render_type_brush) {
- RenderRegion.Min.x -= RenderRegion.Min.x % 8;
- RenderRegion.Min.y -= RenderRegion.Min.y % 8;
- RenderRegion.Max.x -= RenderRegion.Max.x % 8;
- RenderRegion.Max.y -= RenderRegion.Max.y % 8;
+ rectangle RenderRegion = { TileWidth*x, TileHeight*y,
+ TileWidth + TileWidth*x, TileHeight + TileHeight*y };
- if (RenderRegion.Max.x > InitialRenderRegion.Max.x)
- RenderRegion.Max.x = InitialRenderRegion.Max.x;
- if (RenderRegion.Max.y > InitialRenderRegion.Max.y)
- RenderRegion.Max.y = InitialRenderRegion.Max.y;
+ if (RenderType == render_type_brush) {
+ RenderRegion.Min.x += InitialRenderRegion.Min.x;
+ RenderRegion.Min.y += InitialRenderRegion.Min.y;
+ RenderRegion.Max.x += InitialRenderRegion.Min.x;
+ RenderRegion.Max.y += InitialRenderRegion.Min.y;
+ }
- if (x == 3)
- RenderRegion.Max.x = InitialRenderRegion.Max.x;
- if (y == 3)
- RenderRegion.Max.y = InitialRenderRegion.Max.y;
+ if (RenderRegion.Max.x > InitialRenderRegion.Max.x)
+ RenderRegion.Max.x = InitialRenderRegion.Max.x;
+ if (RenderRegion.Max.y > InitialRenderRegion.Max.y)
+ RenderRegion.Max.y = InitialRenderRegion.Max.y;
- render_entry Entry = { Data, OutputBuffer, RenderRegion };
+ if (x == i-1)
+ RenderRegion.Max.x = InitialRenderRegion.Max.x;
+ if (y == i-1)
+ RenderRegion.Max.y = InitialRenderRegion.Max.y;
- uint32 Q = SDL_AtomicGet(&QueuedEntries);
- *(Entries + Q) = Entry;
- SDL_AtomicAdd(&QueuedEntries, 1);
- SDL_SemPost(Semaphore);
- }
- // }
+ render_entry Entry = { Data, OutputBuffer, RenderType, RenderRegion };
+
+ uint32 Q = SDL_AtomicGet(&QueuedEntries);
+ *(Entries + Q) = Entry;
+ SDL_AtomicAdd(&QueuedEntries, 1);
+ SDL_SemPost(Semaphore);
+ // }
+ }
}
}