summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFox Caminiti <fox@foxcam.net>2023-01-06 17:44:22 -0500
committerFox Caminiti <fox@foxcam.net>2023-01-06 17:44:22 -0500
commit84d04d391bc4bf9481106d4f5ac4d3dd8f27ed87 (patch)
treeba91aaf8a4245b939b4d04aca66cd0c5bb5687c0
parent1de48570b220acc1ca7063e2a9cda1e89178c0f9 (diff)
round edges
-rw-r--r--src/bezier.cpp42
-rw-r--r--src/createcalls.cpp13
-rw-r--r--src/imgui_ui.cpp1
-rw-r--r--src/imgui_ui_viewport.cpp92
-rw-r--r--src/include/main.h7
-rw-r--r--src/include/my_math.h1
-rw-r--r--src/layer.cpp2
7 files changed, 80 insertions, 78 deletions
diff --git a/src/bezier.cpp b/src/bezier.cpp
index 6bb1541..1585495 100644
--- a/src/bezier.cpp
+++ b/src/bezier.cpp
@@ -34,6 +34,48 @@ Bezier_SolveYForX(v2 Point_P0, v2 Point_P1, v2 Point_P2, v2 Point_P3, real32 Tar
return Y;
}
+// TODO(fox): Incorporate sorting for non-continuous shapes.
+static uint32
+Bezier_Shape_Sort(memory *Memory, shape_layer *Shape, bezier_point *PointData)
+{
+ real32 Radius = Shape->Opt.Roundness;
+ bezier_point *PointStart = PointData;
+ for (int i = 0; i < Shape->Point_Count; i++) {
+ bezier_point *Point = Bezier_LookupAddress(Memory, Shape->Block_Bezier_Index, i, 1);
+ if (Radius <= 0 && Point->Type == interpolation_type_linear) {
+ v2 Pos = Point->Pos[0];
+ int Index_Prev = (i != 0) ? i-1 : Shape->Point_Count-1;
+ int Index_Next = (i != Shape->Point_Count-1) ? i+1 : 0;
+ v2 Pos_Prev = Bezier_LookupAddress(Memory, Shape->Block_Bezier_Index, Index_Prev, 1)->Pos[0];
+ v2 Pos_Next = Bezier_LookupAddress(Memory, Shape->Block_Bezier_Index, Index_Next, 1)->Pos[0];
+ v2 Vector_Prev = Pos - Pos_Prev;
+ v2 Vector_Next = Pos - Pos_Next;
+ real32 Length_Prev = sqrtf(LengthSq(Vector_Prev));
+ real32 Length_Next = sqrtf(LengthSq(Vector_Next));
+
+ // real32 RadAngle = acos(Inner(Vector_Prev, VectorR) / (LengthL * LengthR)) * PI / 180;
+ // real32 AngleKappa = (4.f/3) * tan(RadAngle * 1/4);
+
+ real32 Ratio_Prev = Radius / Length_Prev;
+ real32 Ratio_Prev_Inv = 1.0f - Ratio_Prev;
+
+ real32 Ratio_Next = Radius / Length_Next;
+ real32 Ratio_Next_Inv = 1.0f - Ratio_Next;
+
+ v2 Point_1 = Pos_Prev + V2(Vector_Prev.x * Ratio_Prev_Inv, (Vector_Prev.y * Ratio_Prev_Inv));
+ v2 Point_2 = Vector_Prev * Ratio_Prev * (1-KAPPA);
+ v2 Point_3 = Pos_Next + V2(Vector_Next.x * Ratio_Next_Inv, Vector_Next.y * Ratio_Next_Inv);
+ v2 Point_4 = Vector_Next * Ratio_Next * (1-KAPPA);
+
+ *PointData++ = { 1, { Point_1, Point_2, V2(0, 0) }, interpolation_type_bezier, 0 };
+ *PointData++ = { 1, { Point_3, V2(0, 0), Point_4 }, interpolation_type_bezier, 0 };
+ } else {
+ *PointData++ = *Point;
+ }
+ }
+ return PointData - PointStart;
+}
+
static bezier_point *
Bezier_LookupAddress(memory *Memory, uint16 *Block_Bezier_Index, uint16 Index, bool32 AssertExists)
{
diff --git a/src/createcalls.cpp b/src/createcalls.cpp
index cd8f3d5..4334dc8 100644
--- a/src/createcalls.cpp
+++ b/src/createcalls.cpp
@@ -627,6 +627,18 @@ Project_ShapeLayer_New(project_data *File, project_state *State, memory *Memory)
Layer->Frame_End = MainComp->Frame_End;
Layer_Select(Memory, State, Memory_Block_LazyIndexAtAddress(Memory, F_Layers, Layer));
+ shape_layer *Shape = &File->UI.Shape;
+ v2 Min = {}, Max = {};
+ void *Data = Memory_PushScratch(Memory, sizeof(nvg_point) * 128);
+ layer_transforms T = {};
+ NVG_FlattenPath(Memory, Shape, (nvg_point *)Data, State, T, 0, 0, 0, 0, 0, &Min, &Max);
+ Memory_PopScratch(Memory, sizeof(nvg_point) * 128);
+ Shape->Width = Max.x - Min.x;
+ Shape->Height = Max.y - Min.y;
+ Layer->x.CurrentValue = Min.x + (Shape->Width / 2);
+ Layer->y.CurrentValue = Min.y + (Shape->Height / 2);
+
+ /*
v2 Min = V2(10000, 10000);
v2 Max = V2(-10000, -10000);
shape_layer *Shape = &File->UI.Shape;
@@ -644,6 +656,7 @@ Project_ShapeLayer_New(project_data *File, project_state *State, memory *Memory)
v2 ShapeSize = (Max - Min);
Layer->x.CurrentValue = Min.x + (ShapeSize.x / 2);
Layer->y.CurrentValue = Min.y + (ShapeSize.y / 2);
+ */
for (int i = 0; i < Shape->Point_Count; i++) {
bezier_point *Point = Bezier_LookupAddress(Memory, Shape->Block_Bezier_Index, i, 1);
Point->Pos[0] = Point->Pos[0] - Min;
diff --git a/src/imgui_ui.cpp b/src/imgui_ui.cpp
index 50d25a4..0a7f310 100644
--- a/src/imgui_ui.cpp
+++ b/src/imgui_ui.cpp
@@ -23,6 +23,7 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ImGuiIO io,
ImGui::Begin("Files");
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
+
if (ImGui::IsKeyPressed(ImGuiKey_Backspace)) {
// TODO(fox): Delete sources code!
diff --git a/src/imgui_ui_viewport.cpp b/src/imgui_ui_viewport.cpp
index fae7bd4..774b305 100644
--- a/src/imgui_ui_viewport.cpp
+++ b/src/imgui_ui_viewport.cpp
@@ -82,7 +82,7 @@ ImGui_Viewport_ShapeUI(project_state *State, memory *Memory, ui *UI, ImGuiIO &io
if (Point_1->Type == interpolation_type_bezier)
draw_list->AddLine(ScreenPoint_0[1], ScreenPoint_0[2], wcol, 2.0f);
- ImU32 PointCol = (Point_1->IsSelected) ? ImColor(0.8f, 0.5f, 0.0f, 1.0f) : ImColor(0.1f, 0.1f, 0.1f, 1.0f);
+ ImU32 PointCol = (Point_1->IsSelected) ? ImColor(0.8f, 0.5f, 0.0f, 1.0f) : ImColor(0.1f, 0.1f, 0.1f, 0.2f);
ImGui::PushID(i);
for (int a = 0; a < 3; a++) {
ImGui::PushID(a);
@@ -100,6 +100,12 @@ ImGui_Viewport_ShapeUI(project_state *State, memory *Memory, ui *UI, ImGuiIO &io
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
}
if (IsItemActivated) {
+ if (!io.KeyShift) {
+ for (int p = 0; p < Shape->Point_Count; p++) {
+ bezier_point *Point = Bezier_LookupAddress(Memory, Shape->Block_Bezier_Index, p, 1);
+ Point->IsSelected = 0;
+ }
+ }
Point_1->IsSelected = 1;
}
if (IsItemActive) {
@@ -111,12 +117,12 @@ ImGui_Viewport_ShapeUI(project_state *State, memory *Memory, ui *UI, ImGuiIO &io
Assert(State->Interact_Active == interact_type_keyframe_move);
ImVec2 DragDelta = io.MousePos - ImVec2(State->Interact_Offset[2], State->Interact_Offset[3]);
if (io.MouseDelta.x || io.MouseDelta.y) {
+ if (State->Interact_Active == interact_type_keyframe_move) {
+ State->Interact_Offset[0] = DragDelta.x * (MainComp->Width / UI->CompZoom.x);
+ State->Interact_Offset[1] = DragDelta.y * (MainComp->Height / UI->CompZoom.y);
+ }
State->UpdateFrame = true;
}
- if (State->Interact_Active == interact_type_keyframe_move) {
- State->Interact_Offset[0] = DragDelta.x * (MainComp->Width / UI->CompZoom.x);
- State->Interact_Offset[1] = DragDelta.y * (MainComp->Height / UI->CompZoom.y);
- }
}
}
if (IsItemDeactivated) {
@@ -126,85 +132,23 @@ ImGui_Viewport_ShapeUI(project_state *State, memory *Memory, ui *UI, ImGuiIO &io
Shape->IsClosed = true;
History_Entry_End(Memory);
} else if (Layer != NULL) {
- layer_transforms T = Layer_GetTransforms(Layer);
History_Entry_Commit(Memory, "Move point");
- void *Data = Memory_PushScratch(Memory, sizeof(nvg_point) * 128);
- v2 Min_Old = {}, Max_Old = {};
- NVG_FlattenPath(Memory, Shape, (nvg_point *)Data, State, T, 0, 0, Width, Height, 0, &Min_Old, &Max_Old);
- v2 TestMin = Min_Old, TestMax = Max_Old;
+ layer_transforms T = Layer_GetTransforms(Layer);
for (int p = 0; p < Shape->Point_Count; p++) {
bezier_point *Point = Bezier_LookupAddress(Memory, Shape->Block_Bezier_Index, p, 1);
if (Point->IsSelected) {
v2 *Pos = &Point->Pos[Point->IsSelected-1];
History_Action_Swap(Memory, F_Bezier, sizeof(*Pos), Pos);
+ *Pos = TransformPoint(T, Shape->Width, Shape->Height, *Pos);
Pos->x += State->Interact_Offset[0];
Pos->y += State->Interact_Offset[1];
- if (Pos->x < TestMin.x) {
- TestMin.x = Pos->x;
- }
- if (Pos->y < TestMin.y) {
- TestMin.y = Pos->y;
- }
- if (Pos->x > TestMax.x) {
- TestMax.x = Pos->x;
- }
- if (Pos->y > TestMax.y) {
- TestMax.y = Pos->y;
- }
+ *Pos = T_CompPosToLayerPos(T, MainComp->Width, MainComp->Height, Shape->Width, Shape->Height, Pos->x, Pos->y);
}
}
- v2 MinDiff = TestMin - Min_Old;
- v2 MaxDiff = TestMax - Max_Old;
- for (int p = 0; p < Shape->Point_Count; p++) {
- bezier_point *Point = Bezier_LookupAddress(Memory, Shape->Block_Bezier_Index, p, 1);
- v2 *Pos = &Point->Pos[0];
- History_Action_Swap(Memory, F_Bezier, sizeof(*Pos), Pos);
- if (MinDiff.x)
- Pos->x -= State->Interact_Offset[0];
- if (MinDiff.y)
- Pos->y -= State->Interact_Offset[1];
- if (MaxDiff.x)
- // Pos->x -= State->Interact_Offset[0];
- if (MaxDiff.y)
- // Pos->y += State->Interact_Offset[1];
- int FU = 0;
- }
- State->Interact_Active = interact_type_none;
- v2 Min_New = {}, Max_New = {};
- NVG_FlattenPath(Memory, Shape, (nvg_point *)Data, State, T, Shape->Width, Shape->Height, Width, Height, 1, &Min_New, &Max_New);
-
- Memory_PopScratch(Memory, sizeof(nvg_point) * 128);
-
- int Width_Old = Max_Old.x - Min_Old.x;
- int Width_New = Max_New.x - Min_New.x;
- int Height_New = Max_New.y - Min_New.y;
- if (MinDiff.x) {
- History_Action_Swap(Memory, F_Layers, sizeof(Layer->ax.CurrentValue), &Layer->ax.CurrentValue);
- Layer->ax.CurrentValue -= (real32)(State->Interact_Offset[0]) * (1.0f - Layer->ax.CurrentValue) / Width_New;
- } if (MinDiff.y) {
- History_Action_Swap(Memory, F_Layers, sizeof(Layer->ay.CurrentValue), &Layer->ay.CurrentValue);
- Layer->ay.CurrentValue -= (real32)(State->Interact_Offset[1]) * (1.0f - Layer->ay.CurrentValue) / Height_New;
- } if (MaxDiff.x) {
- History_Action_Swap(Memory, F_Layers, sizeof(Layer->ax.CurrentValue), &Layer->ax.CurrentValue);
- Layer->ax.CurrentValue -= (real32)(State->Interact_Offset[0]) * (Layer->ax.CurrentValue) / Width_New;
- } if (MaxDiff.y) {
- History_Action_Swap(Memory, F_Layers, sizeof(Layer->ay.CurrentValue), &Layer->ay.CurrentValue);
- Layer->ay.CurrentValue -= (real32)(State->Interact_Offset[1]) * (Layer->ay.CurrentValue) / Height_New;
- }
- /*
- if (Min_New.y < Min_Old.y) {
- Layer->y.CurrentValue += Min_New.y - Min_Old.y;
- }
- if (Max_New.x > Max_Old.x) {
- Layer->x.CurrentValue += Max_New.x - Max_Old.x;
- }
- if (Max_New.y > Max_Old.y) {
- Layer->y.CurrentValue += Max_New.y - Max_Old.y;
- }
- */
- Shape->Width = Width_New;
- Shape->Height = Height_New;
History_Entry_End(Memory);
+ State->Interact_Active = interact_type_none;
+ State->Interact_Offset[0] = 0;
+ State->Interact_Offset[1] = 0;
}
}
draw_list->AddNgon(ScreenPoint_1[a], 4, PointCol, 8, 5.0f);
@@ -735,7 +679,7 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory,
}
shape_layer *Shape = &UI->Shape;
- if (State->Tool == tool_pen && State->MostRecentlySelectedLayer == -1)
+ if ((State->Tool == tool_pen || State->Tool == tool_square) && State->MostRecentlySelectedLayer == -1)
ImGui_Viewport_ShapeUI(State, Memory, UI, io, NULL, 0, 0, Shape, MainComp, draw_list);
// Interactions for dragging and zooming
diff --git a/src/include/main.h b/src/include/main.h
index db384ce..7d3299e 100644
--- a/src/include/main.h
+++ b/src/include/main.h
@@ -188,9 +188,10 @@ struct shape_options {
int Visibility;
v4 FillCol = {1, 1, 1, 1};
v4 StrokeCol = {0, 1, 0, 1};
- float StrokeWidth = 10;
+ float StrokeWidth = 25;
nvg_line_cap LineJoinType = NVG_ROUND;
nvg_line_cap LineCapType = NVG_ROUND;
+ real32 Roundness;
};
struct shape_layer {
@@ -248,7 +249,8 @@ char *ToolName[] {
"Move",
"Crop",
"Brush",
- "Pen"
+ "Pen",
+ "Square"
};
enum tool {
@@ -256,6 +258,7 @@ enum tool {
tool_crop,
tool_brush,
tool_pen,
+ tool_square,
tool_count
};
diff --git a/src/include/my_math.h b/src/include/my_math.h
index 865f11c..72c6b99 100644
--- a/src/include/my_math.h
+++ b/src/include/my_math.h
@@ -1,4 +1,5 @@
#define PI 3.141592653589793238
+#define KAPPA 0.5522847493f
union v2
{
diff --git a/src/layer.cpp b/src/layer.cpp
index 7d40310..6159467 100644
--- a/src/layer.cpp
+++ b/src/layer.cpp
@@ -114,8 +114,6 @@ Layer_UpdateMasksEffects(project_state *State, block_layer *Layer, memory *Memor
v2 Min = {}, Max = {};
if (State->Interact_Active == interact_type_keyframe_move) {
NVG_FlattenPath(Memory, Shape, (nvg_point *)Data, State, T, 0, 0, Width, Height, 0, &Min, &Max);
- Shape->Width = Max.x - Min.x;
- Shape->Height = Max.y - Min.y;
}
uint32 NumberOfVerts = NVG_FlattenPath(Memory, Shape, (nvg_point *)Data,
State, T, Shape->Width, Shape->Height, Width, Height, 1, &Min, &Max);