[Bf-blender-cvs] [fed66c4ec46] asset-greasepencil: GPencil: Basic 2D cage drawing
Antonio Vazquez
noreply at git.blender.org
Fri Jul 16 16:52:29 CEST 2021
Commit: fed66c4ec4659663ccc75df9a79e53af082feb4c
Author: Antonio Vazquez
Date: Fri Jul 16 16:52:18 2021 +0200
Branches: asset-greasepencil
https://developer.blender.org/rBfed66c4ec4659663ccc75df9a79e53af082feb4c
GPencil: Basic 2D cage drawing
===================================================================
M source/blender/editors/gpencil/gpencil_asset.c
===================================================================
diff --git a/source/blender/editors/gpencil/gpencil_asset.c b/source/blender/editors/gpencil/gpencil_asset.c
index d7a750c50a7..5d13f98b3e7 100644
--- a/source/blender/editors/gpencil/gpencil_asset.c
+++ b/source/blender/editors/gpencil/gpencil_asset.c
@@ -42,6 +42,7 @@
#include "BKE_report.h"
#include "UI_interface.h"
+#include "UI_resources.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -50,9 +51,15 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "GPU_framebuffer.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
+
#include "ED_asset.h"
#include "ED_gpencil.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -85,18 +92,31 @@ typedef struct tGPDasset {
/** Transform mode. */
short mode;
- /* Drop initial position. */
+ /** Drop initial position. */
int drop_x, drop_y;
- /* Mouse last click position. */
+ /** Mouse last click position. */
int mouse[2];
-
- /* Hash of new created layers. */
+ /** 2D Cage vertices. */
+ rctf rect_cage;
+ /** 2D cage manipulator points *
+ * 0----1----2
+ * | |
+ * 7 3
+ * | |
+ * 6----5----4
+ */
+ float manipulator[7][2];
+
+ /** Hash of new created layers. */
struct GHash *asset_layers;
- /* Hash of new created frames. */
+ /** Hash of new created frames. */
struct GHash *asset_frames;
- /* Hash of new created strokes. */
+ /** Hash of new created strokes. */
struct GHash *asset_strokes;
+ /** Handle for drawing while operator is running. */
+ void *draw_handle_3d;
+
} tGPDasset;
typedef enum eGP_AssetTransformMode {
@@ -295,6 +315,11 @@ static void gpencil_asset_import_exit(bContext *C, wmOperator *op)
BLI_ghash_free(tgpa->asset_strokes, NULL, NULL);
}
+ /* Remove drawing handler. */
+ if (tgpa->draw_handle_3d) {
+ ED_region_draw_cb_exit(tgpa->region->type, tgpa->draw_handle_3d);
+ }
+
MEM_SAFE_FREE(tgpa);
}
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
@@ -389,6 +414,68 @@ static int gpencil_asset_import_init(bContext *C, wmOperator *op)
return 1;
}
+/* Helper: Compute 2D cage size in screen pixels. */
+static void gpencil_2d_cage_prepare(tGPDasset *tgpa)
+{
+ /* Add some oversize. */
+ const float oversize = 5.0f;
+
+ float diff_mat[4][4];
+ unit_m4(diff_mat);
+
+ float cage_min[2];
+ float cage_max[2];
+ INIT_MINMAX2(cage_min, cage_max);
+
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, tgpa->asset_strokes) {
+ // TODO: All strokes or only active frame?
+ bGPDstroke *gps = (bGPDstroke *)BLI_ghashIterator_getKey(&gh_iter);
+ if (is_zero_v3(gps->boundbox_min)) {
+ BKE_gpencil_stroke_boundingbox_calc(gps);
+ }
+ float boundbox_min[2];
+ float boundbox_max[2];
+ ED_gpencil_projected_2d_bound_box(&tgpa->gsc, gps, diff_mat, boundbox_min, boundbox_max);
+ minmax_v2v2_v2(cage_min, cage_max, boundbox_min);
+ minmax_v2v2_v2(cage_min, cage_max, boundbox_max);
+ }
+
+ tgpa->rect_cage.xmin = cage_min[0] - oversize;
+ tgpa->rect_cage.ymin = cage_min[1] - oversize;
+ tgpa->rect_cage.xmax = cage_max[0] + oversize;
+ tgpa->rect_cage.ymax = cage_max[1] + oversize;
+
+ /* Manipulator points */
+ tgpa->manipulator[0][0] = tgpa->rect_cage.xmin;
+ tgpa->manipulator[0][1] = tgpa->rect_cage.ymax;
+
+ tgpa->manipulator[1][0] = tgpa->rect_cage.xmin +
+ ((tgpa->rect_cage.xmax - tgpa->rect_cage.xmin) * 0.5f);
+ tgpa->manipulator[1][1] = tgpa->rect_cage.ymax;
+
+ tgpa->manipulator[2][0] = tgpa->rect_cage.xmax;
+ tgpa->manipulator[2][1] = tgpa->rect_cage.ymax;
+
+ tgpa->manipulator[3][0] = tgpa->rect_cage.xmax;
+ tgpa->manipulator[3][1] = tgpa->rect_cage.ymin +
+ ((tgpa->rect_cage.ymax - tgpa->rect_cage.ymin) * 0.5f);
+
+ tgpa->manipulator[4][0] = tgpa->rect_cage.xmax;
+ tgpa->manipulator[4][1] = tgpa->rect_cage.ymin;
+
+ tgpa->manipulator[5][0] = tgpa->rect_cage.xmin +
+ ((tgpa->rect_cage.xmax - tgpa->rect_cage.xmin) * 0.5f);
+ tgpa->manipulator[5][1] = tgpa->rect_cage.ymin;
+
+ tgpa->manipulator[6][0] = tgpa->rect_cage.xmin;
+ tgpa->manipulator[6][1] = tgpa->rect_cage.ymin;
+
+ tgpa->manipulator[7][0] = tgpa->rect_cage.xmin;
+ tgpa->manipulator[7][1] = tgpa->rect_cage.ymin +
+ ((tgpa->rect_cage.ymax - tgpa->rect_cage.ymin) * 0.5f);
+}
+
/* Helper: Load all strokes in the target datablock. */
static void gpencil_asset_add_strokes(tGPDasset *tgpa)
{
@@ -417,19 +504,109 @@ static void gpencil_asset_add_strokes(tGPDasset *tgpa)
/* Add to the hash to remove if operator is canceled. */
if (!BLI_ghash_haskey(tgpa->asset_frames, gpf_target)) {
- BLI_ghash_insert(tgpa->asset_frames, gpf_target, gpf_target);
+ /* Add the hash key with a reference to the layer. */
+ BLI_ghash_insert(tgpa->asset_frames, gpf_target, gpl_target);
}
}
/* Loop all strokes and duplicate. */
LISTBASE_FOREACH (bGPDstroke *, gps_asset, &gpf_asset->strokes) {
bGPDstroke *gps_target = BKE_gpencil_stroke_duplicate(gps_asset, true, true);
BLI_addtail(&gpf_target->strokes, gps_target);
- BLI_ghash_insert(tgpa->asset_strokes, gps_target, gps_target);
+ /* Add the hash key with a reference to the frame. */
+ BLI_ghash_insert(tgpa->asset_strokes, gps_target, gpf_target);
}
}
}
+ /* Prepare 2D cage. */
+ gpencil_2d_cage_prepare(tgpa);
}
+/* Draw a cage for manipulate asset */
+static void gpencil_draw_cage(tGPDasset *tgpa)
+{
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ GPU_blend(GPU_BLEND_ALPHA);
+
+ /* Draw dash box. */
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ GPU_line_width(1.0f);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ float box_color[4];
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, box_color);
+ immUniformColor4fv(box_color);
+ imm_draw_box_wire_2d(
+ pos, tgpa->rect_cage.xmin, tgpa->rect_cage.ymin, tgpa->rect_cage.xmax, tgpa->rect_cage.ymax);
+ immUnbindProgram();
+
+ /* Draw Points. */
+ GPU_program_point_size(true);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+
+ float point_color[4];
+ UI_GetThemeColor4fv(TH_SELECT, point_color);
+ immUniformColor4fv(point_color);
+
+ immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * 1.5f * U.dpi_fac);
+ immBegin(GPU_PRIM_POINTS, 8);
+ for (int i = 0; i < 8; i++) {
+ immVertex2fv(pos, tgpa->manipulator[i]);
+ }
+ immEnd();
+ immUnbindProgram();
+ GPU_program_point_size(false);
+
+ GPU_blend(GPU_BLEND_NONE);
+}
+
+// TODO
+#if 0
+static void draw_mouse_position(tGPDfill *tgpf)
+{
+ if (tgpf->gps_mouse == NULL) {
+ return;
+ }
+ uchar mouse_color[4] = {0, 0, 255, 255};
+
+ bGPDspoint *pt = &tgpf->gps_mouse->points[0];
+ float point_size = (tgpf->zoom == 1.0f) ? 4.0f * tgpf->fill_factor :
+ (0.5f * tgpf->zoom) + tgpf->fill_factor;
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+
+ /* Draw mouse click position in Blue. */
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
+ GPU_point_size(point_size);
+ immBegin(GPU_PRIM_POINTS, 1);
+ immAttr4ubv(col, mouse_color);
+ immVertex3fv(pos, &pt->x);
+ immEnd();
+ immUnbindProgram();
+}
+#endif
+
+/* Drawing callback for modal operator. */
+static void gpencil_asset_draw(const bContext *C, ARegion *UNUSED(region), void *arg)
+{
+ tGPDasset *tgpa = (tGPDasset *)arg;
+ /* Draw only in the region that originated operator. This is required for multi-window. */
+ ARegion *region = CTX_wm_region(C);
+ if (region != tgpa->region) {
+ return;
+ }
+ gpencil_draw_cage(tgpa);
+}
/* ----------------------- */
/* Invoke handler: Initialize the operator */
@@ -455,6 +632,9 @@ static int gpencil_asset_import_invoke(bContext *C, wmOperator *op, const wmEven
/* Do an initial load of the strokes in the target datablock. */
gpencil_asset_add_strokes(tgpa);
+ tgpa->draw_handle_3d = ED_region_draw_cb_activate(
+ tgpa->region->type, gpencil_asset_draw, tgpa, REGION_DRAW_POST_PIXEL);
+
/* set cursor to indicate modal */
WM_cursor_modal_set(win, WM_CURSOR_EW_SCROLL);
More information about the Bf-blender-cvs
mailing list