Draw manager: Implement point selection modes for particle edit mode
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 9 May 2018 12:59:29 +0000 (14:59 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 9 May 2018 13:00:29 +0000 (15:00 +0200)
source/blender/draw/intern/draw_cache.c
source/blender/draw/intern/draw_cache.h
source/blender/draw/intern/draw_cache_impl.h
source/blender/draw/intern/draw_cache_impl_particles.c
source/blender/draw/modes/particle_mode.c
source/blender/editors/space_view3d/space_view3d.c

index 95193bebaea57e34ac31afd493734d7b7c9ccf17..38ec9cff7f476b47539e38ad00c282d377e8de90 100644 (file)
@@ -2891,9 +2891,14 @@ Gwn_Batch *DRW_cache_particles_get_edit_strands(struct PTCacheEdit *edit)
        return DRW_particles_batch_cache_get_edit_strands(edit);
 }
 
-Gwn_Batch *DRW_cache_particles_get_edit_points(struct PTCacheEdit *edit)
+Gwn_Batch *DRW_cache_particles_get_edit_inner_points(struct PTCacheEdit *edit)
 {
-       return DRW_particles_batch_cache_get_edit_points(edit);
+       return DRW_particles_batch_cache_get_edit_inner_points(edit);
+}
+
+Gwn_Batch *DRW_cache_particles_get_edit_tip_points(struct PTCacheEdit *edit)
+{
+       return DRW_particles_batch_cache_get_edit_tip_points(edit);
 }
 
 Gwn_Batch *DRW_cache_particles_get_prim(int type)
index e726e25431f40bb4039dbdac8f1b00e610a106e7..66db405786dcb31466ccbb97fbfec6ea4266273d 100644 (file)
@@ -170,7 +170,8 @@ struct Gwn_Batch *DRW_cache_lattice_vert_overlay_get(struct Object *ob);
 struct Gwn_Batch *DRW_cache_particles_get_hair(struct ParticleSystem *psys, struct ModifierData *md);
 struct Gwn_Batch *DRW_cache_particles_get_dots(struct Object *object, struct ParticleSystem *psys);
 struct Gwn_Batch *DRW_cache_particles_get_edit_strands(struct PTCacheEdit *edit);
-struct Gwn_Batch *DRW_cache_particles_get_edit_points(struct PTCacheEdit *edit);
+struct Gwn_Batch *DRW_cache_particles_get_edit_inner_points(struct PTCacheEdit *edit);
+struct Gwn_Batch *DRW_cache_particles_get_edit_tip_points(struct PTCacheEdit *edit);
 struct Gwn_Batch *DRW_cache_particles_get_prim(int type);
 
 /* Metaball */
index 84c7825c6f9c09cb29d794aaec3170ed93ec52c3..4e3c56eb4279e68ee1fd05db113b5eb3fb093503 100644 (file)
@@ -126,6 +126,7 @@ void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me);
 struct Gwn_Batch *DRW_particles_batch_cache_get_hair(struct ParticleSystem *psys, struct ModifierData *md);
 struct Gwn_Batch *DRW_particles_batch_cache_get_dots(struct Object *object, struct ParticleSystem *psys);
 struct Gwn_Batch *DRW_particles_batch_cache_get_edit_strands(struct PTCacheEdit *edit);
-struct Gwn_Batch *DRW_particles_batch_cache_get_edit_points(struct PTCacheEdit *edit);
+struct Gwn_Batch *DRW_particles_batch_cache_get_edit_inner_points(struct PTCacheEdit *edit);
+struct Gwn_Batch *DRW_particles_batch_cache_get_edit_tip_points(struct PTCacheEdit *edit);
 
 #endif /* __DRAW_CACHE_IMPL_H__ */
index 065628f3f683ff08075b1d33a202a654cbb1d5c0..0bf2ea4f26ccd6efde53123770994769e0c49df8 100644 (file)
@@ -70,9 +70,13 @@ typedef struct ParticleBatchCache {
        int point_count;
 
        /* Control points when in edit mode. */
-       Gwn_VertBuf *edit_pos;
-       Gwn_Batch *edit_points;
-       int edit_point_count;
+       Gwn_VertBuf *edit_inner_pos;
+       Gwn_Batch *edit_inner_points;
+       int edit_inner_point_count;
+
+       Gwn_VertBuf *edit_tip_pos;
+       Gwn_Batch *edit_tip_points;
+       int edit_tip_point_count;
 
        /* Settings to determine if cache is invalid. */
        bool is_dirty;
@@ -153,8 +157,10 @@ static void particle_batch_cache_clear(ParticleSystem *psys)
        GWN_VERTBUF_DISCARD_SAFE(cache->pos);
        GWN_INDEXBUF_DISCARD_SAFE(cache->indices);
 
-       GWN_BATCH_DISCARD_SAFE(cache->edit_points);
-       GWN_VERTBUF_DISCARD_SAFE(cache->edit_pos);
+       GWN_BATCH_DISCARD_SAFE(cache->edit_inner_points);
+       GWN_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos);
+       GWN_BATCH_DISCARD_SAFE(cache->edit_tip_points);
+       GWN_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos);
 }
 
 void DRW_particle_batch_cache_free(ParticleSystem *psys)
@@ -600,30 +606,42 @@ Gwn_Batch *DRW_particles_batch_cache_get_edit_strands(PTCacheEdit *edit)
        return cache->hairs;
 }
 
-static void ensure_edit_points_count(const PTCacheEdit *edit,
-                                     ParticleBatchCache *cache)
+static void ensure_edit_inner_points_count(const PTCacheEdit *edit,
+                                           ParticleBatchCache *cache)
 {
-       if (cache->edit_pos != NULL) {
+       if (cache->edit_inner_pos != NULL) {
                return;
        }
-       cache->edit_point_count = 0;
+       cache->edit_inner_point_count = 0;
        for (int point_index = 0; point_index < edit->totpoint; point_index++) {
                const PTCacheEditPoint *point = &edit->points[point_index];
-               cache->edit_point_count += point->totkey;
+               BLI_assert(point->totkey >= 1);
+               cache->edit_inner_point_count += (point->totkey - 1);
        }
 }
 
-static void particle_batch_cache_ensure_edit_pos(PTCacheEdit *edit,
-                                                 ParticleBatchCache *cache)
+static void edit_colors_get(PTCacheEdit *edit,
+                            float selected_color[4],
+                            float normal_color[4])
 {
-       if (cache->edit_pos != NULL) {
+       rgb_uchar_to_float(selected_color, edit->sel_col);
+       rgb_uchar_to_float(normal_color, edit->nosel_col);
+       selected_color[3] = 1.0f;
+       normal_color[3] = 1.0f;
+}
+
+static void particle_batch_cache_ensure_edit_inner_pos(
+        PTCacheEdit *edit,
+        ParticleBatchCache *cache)
+{
+       if (cache->edit_inner_pos != NULL) {
                return;
        }
 
        static Gwn_VertFormat format = { 0 };
        static unsigned pos_id, color_id;
 
-       GWN_VERTBUF_DISCARD_SAFE(cache->edit_pos);
+       GWN_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos);
 
        if (format.attrib_ct == 0) {
                /* initialize vertex format */
@@ -631,43 +649,102 @@ static void particle_batch_cache_ensure_edit_pos(PTCacheEdit *edit,
                color_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
        }
 
-       cache->edit_pos = GWN_vertbuf_create_with_format(&format);
-       GWN_vertbuf_data_alloc(cache->edit_pos, cache->edit_point_count);
+       cache->edit_inner_pos = GWN_vertbuf_create_with_format(&format);
+       GWN_vertbuf_data_alloc(cache->edit_inner_pos, cache->edit_inner_point_count);
 
-       /* Convert theme colors from uchar[3] to float[4]. */
-       float selected_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
-       float normal_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
-       rgb_uchar_to_float(selected_color, edit->sel_col);
-       rgb_uchar_to_float(normal_color, edit->nosel_col);
+       float selected_color[4], normal_color[4];
+       edit_colors_get(edit, selected_color, normal_color);
 
        int global_key_index = 0;
        for (int point_index = 0; point_index < edit->totpoint; point_index++) {
                const PTCacheEditPoint *point = &edit->points[point_index];
-               for (int key_index = 0; key_index < point->totkey; key_index++) {
+               for (int key_index = 0; key_index < point->totkey - 1; key_index++) {
                        PTCacheEditKey *key = &point->keys[key_index];
-                       GWN_vertbuf_attr_set(cache->edit_pos, pos_id, global_key_index, key->world_co);
+                       GWN_vertbuf_attr_set(cache->edit_inner_pos, pos_id, global_key_index, key->world_co);
                        if (key->flag & PEK_SELECT) {
-                               GWN_vertbuf_attr_set(cache->edit_pos, color_id, global_key_index, selected_color);
+                               GWN_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, selected_color);
                        }
                        else {
-                               GWN_vertbuf_attr_set(cache->edit_pos, color_id, global_key_index, normal_color);
+                               GWN_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, normal_color);
                        }
                        global_key_index++;
                }
        }
 }
 
-Gwn_Batch *DRW_particles_batch_cache_get_edit_points(PTCacheEdit *edit)
+Gwn_Batch *DRW_particles_batch_cache_get_edit_inner_points(PTCacheEdit *edit)
+{
+       ParticleSystem *psys = edit->psys;
+       ParticleBatchCache *cache = particle_batch_cache_get(psys);
+       if (cache->edit_inner_points != NULL) {
+               return cache->edit_inner_points;
+       }
+       ensure_edit_inner_points_count(edit, cache);
+       particle_batch_cache_ensure_edit_inner_pos(edit, cache);
+       cache->edit_inner_points = GWN_batch_create(GWN_PRIM_POINTS,
+                                                   cache->edit_inner_pos,
+                                                   NULL);
+       return cache->edit_inner_points;
+}
+
+static void ensure_edit_tip_points_count(const PTCacheEdit *edit,
+                                           ParticleBatchCache *cache)
+{
+       if (cache->edit_tip_pos != NULL) {
+               return;
+       }
+       cache->edit_tip_point_count = edit->totpoint;
+}
+
+static void particle_batch_cache_ensure_edit_tip_pos(
+        PTCacheEdit *edit,
+        ParticleBatchCache *cache)
+{
+       if (cache->edit_tip_pos != NULL) {
+               return;
+       }
+
+       static Gwn_VertFormat format = { 0 };
+       static unsigned pos_id, color_id;
+
+       GWN_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos);
+
+       if (format.attrib_ct == 0) {
+               /* initialize vertex format */
+               pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+               color_id = GWN_vertformat_attr_add(&format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+       }
+
+       cache->edit_tip_pos = GWN_vertbuf_create_with_format(&format);
+       GWN_vertbuf_data_alloc(cache->edit_tip_pos, cache->edit_tip_point_count);
+
+       float selected_color[4], normal_color[4];
+       edit_colors_get(edit, selected_color, normal_color);
+
+       for (int point_index = 0; point_index < edit->totpoint; point_index++) {
+               const PTCacheEditPoint *point = &edit->points[point_index];
+               PTCacheEditKey *key = &point->keys[point->totkey - 1];
+               GWN_vertbuf_attr_set(cache->edit_tip_pos, pos_id, point_index, key->world_co);
+               if (key->flag & PEK_SELECT) {
+                       GWN_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, selected_color);
+               }
+               else {
+                       GWN_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, normal_color);
+               }
+       }
+}
+
+Gwn_Batch *DRW_particles_batch_cache_get_edit_tip_points(PTCacheEdit *edit)
 {
        ParticleSystem *psys = edit->psys;
        ParticleBatchCache *cache = particle_batch_cache_get(psys);
-       if (cache->edit_points != NULL) {
-               return cache->edit_points;
-       }
-       ensure_edit_points_count(edit, cache);
-       particle_batch_cache_ensure_edit_pos(edit, cache);
-       cache->edit_points = GWN_batch_create(GWN_PRIM_POINTS,
-                                             cache->edit_pos,
-                                             NULL);
-       return cache->edit_points;
+       if (cache->edit_tip_points != NULL) {
+               return cache->edit_tip_points;
+       }
+       ensure_edit_tip_points_count(edit, cache);
+       particle_batch_cache_ensure_edit_tip_pos(edit, cache);
+       cache->edit_tip_points = GWN_batch_create(GWN_PRIM_POINTS,
+                                                 cache->edit_tip_pos,
+                                                 NULL);
+       return cache->edit_tip_points;
 }
index 52d72da0151b2987b384702073d69266892091b0..91d005894493bfc9f47674f427bd01b16c4de56c 100644 (file)
@@ -85,7 +85,8 @@ static struct {
 
 typedef struct PARTICLE_PrivateData {
        DRWShadingGroup *strands_group;
-       DRWShadingGroup *points_group;
+       DRWShadingGroup *inner_points_group;
+       DRWShadingGroup *tip_points_group;
 } PARTICLE_PrivateData; /* Transient data */
 
 /* *********** FUNCTIONS *********** */
@@ -125,25 +126,35 @@ static void particle_cache_init(void *vedata)
 
        stl->g_data->strands_group = DRW_shgroup_create(
                e_data.strands_shader, psl->psys_edit_pass);
-       stl->g_data->points_group = DRW_shgroup_create(
+       stl->g_data->inner_points_group = DRW_shgroup_create(
+               e_data.points_shader, psl->psys_edit_pass);
+       stl->g_data->tip_points_group = DRW_shgroup_create(
                e_data.points_shader, psl->psys_edit_pass);
 
        static float size = 5.0f;
-       DRW_shgroup_uniform_float(stl->g_data->points_group, "size", &size, 1);
        static float outline_width = 1.0f;
-       DRW_shgroup_uniform_float(stl->g_data->points_group, "outlineWidth", &outline_width, 1);
+       DRW_shgroup_uniform_float(stl->g_data->inner_points_group, "size", &size, 1);
+       DRW_shgroup_uniform_float(stl->g_data->inner_points_group, "outlineWidth", &outline_width, 1);
+       DRW_shgroup_uniform_float(stl->g_data->tip_points_group, "size", &size, 1);
+       DRW_shgroup_uniform_float(stl->g_data->tip_points_group, "outlineWidth", &outline_width, 1);
 }
 
 static void particle_edit_cache_populate(void *vedata, PTCacheEdit *edit)
 {
        PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl;
+       const DRWContextState *draw_ctx = DRW_context_state_get();
+       ParticleEditSettings *pset= PE_settings(draw_ctx->scene);
        {
                struct Gwn_Batch *strands = DRW_cache_particles_get_edit_strands(edit);
                DRW_shgroup_call_add(stl->g_data->strands_group, strands, NULL);
        }
-       {
-               struct Gwn_Batch *points = DRW_cache_particles_get_edit_points(edit);
-               DRW_shgroup_call_add(stl->g_data->points_group, points, NULL);
+       if (pset->selectmode == SCE_SELECT_POINT) {
+               struct Gwn_Batch *points = DRW_cache_particles_get_edit_inner_points(edit);
+               DRW_shgroup_call_add(stl->g_data->inner_points_group, points, NULL);
+       }
+       if (ELEM(pset->selectmode, SCE_SELECT_POINT, SCE_SELECT_END)) {
+               struct Gwn_Batch *points = DRW_cache_particles_get_edit_tip_points(edit);
+               DRW_shgroup_call_add(stl->g_data->tip_points_group, points, NULL);
        }
 }
 
index d9ba59de887d3ea69156def2b3f9054f225dd417..406d522cc371b575fdbb6a783135a8c547c06a8f 100644 (file)
@@ -1017,7 +1017,7 @@ static void view3d_main_region_listener(
 }
 
 static void view3d_main_region_message_subscribe(
-        const struct bContext *UNUSED(C),
+        const struct bContext *C,
         struct WorkSpace *workspace, struct Scene *scene,
         struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
         struct wmMsgBus *mbus)
@@ -1091,6 +1091,18 @@ static void view3d_main_region_message_subscribe(
 
        WM_msg_subscribe_rna_anon_type(mbus, SceneDisplay, &msg_sub_value_region_tag_redraw);
 
+       ViewLayer *view_layer = CTX_data_view_layer(C);
+       Object *obact = OBACT(view_layer);
+       if (obact != NULL) {
+               switch (obact->mode) {
+                       case OB_MODE_PARTICLE_EDIT:
+                               WM_msg_subscribe_rna_anon_type(mbus, ParticleEdit, &msg_sub_value_region_tag_redraw);
+                               break;
+                       default:
+                               break;
+               }
+       }
+
        if (workspace->tool.spacetype == SPACE_VIEW3D) {
                wmMsgSubscribeValue msg_sub_value_region_tag_refresh = {
                        .owner = ar,