[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