WIP: Rewrite asset browser as separate editor #107576

Draft
Julian Eisel wants to merge 95 commits from asset-browser-frontend-split into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
19 changed files with 501 additions and 223 deletions
Showing only changes of commit 8f48dd8f72 - Show all commits

View File

@ -1485,7 +1485,8 @@ class CyclesPreferences(bpy.types.AddonPreferences):
if sys.platform[:3] == "win":
col.label(text="and AMD Radeon Pro 21.Q4 driver or newer", icon='BLANK1')
elif device_type == 'METAL':
col.label(text="Requires Apple Silicon and macOS 12.0 or newer", icon='BLANK1')
col.label(text="Requires Apple Silicon with macOS 12.2 or newer", icon='BLANK1')
col.label(text="or AMD with macOS 12.3 or newer", icon='BLANK1')
return
for device in devices:

View File

@ -97,7 +97,10 @@ void Session::start()
{
/* Signal session thread to start rendering. */
thread_scoped_lock session_thread_lock(session_thread_mutex_);
assert(session_thread_state_ == SESSION_THREAD_WAIT);
if (session_thread_state_ == SESSION_THREAD_RENDER) {
/* Already rendering, nothing to do. */
return;
}
session_thread_state_ = SESSION_THREAD_RENDER;
}

View File

@ -1696,10 +1696,12 @@ static bool lib_override_library_resync(Main *bmain,
BKE_id_multi_tagged_delete(bmain);
/* At this point, `id_root` has very likely been deleted, we need to update it to its new
* version.
/* At this point, `id_root` may have been resynced, therefore deleted. In that case we need to
* update it to its new version.
*/
id_root = id_root_reference->newid;
if (id_root_reference->newid != NULL) {
id_root = id_root_reference->newid;
}
if (user_edited_overrides_deletion_count > 0) {
BKE_reportf(reports != NULL ? reports->reports : NULL,

View File

@ -1037,7 +1037,12 @@ static Mesh *mesh_new_from_mesh(Object *object, Mesh *mesh)
{
/* While we could copy this into the new mesh,
* add the data to 'mesh' so future calls to this function don't need to re-convert the data. */
BKE_mesh_wrapper_ensure_mdata(mesh);
if (mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
BKE_mesh_wrapper_ensure_mdata(mesh);
}
else {
BKE_mesh_wrapper_ensure_subdivision(object, mesh);
}
Mesh *mesh_result = (Mesh *)BKE_id_copy_ex(
nullptr, &mesh->id, nullptr, LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT);
@ -1074,6 +1079,7 @@ static Mesh *mesh_new_from_mesh_object_with_layers(Depsgraph *depsgraph,
mask.pmask |= CD_MASK_ORIGINDEX;
}
Mesh *result = mesh_create_eval_final(depsgraph, scene, &object_for_eval, &mask);
BKE_mesh_wrapper_ensure_subdivision(object, result);
return result;
}

View File

@ -8,6 +8,7 @@
#pragma once
struct DRWSubdivCache;
struct MeshRenderData;
struct TaskGraph;
#include "DNA_customdata_types.h"
@ -332,7 +333,7 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
MeshBufferCache *mbc,
struct DRWSubdivCache *subdiv_cache,
const struct ToolSettings *ts);
struct MeshRenderData *mr);
#ifdef __cplusplus
}

View File

@ -776,7 +776,7 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
MeshBufferCache *mbc,
DRWSubdivCache *subdiv_cache,
const ToolSettings *ts)
MeshRenderData *mr)
{
/* Create an array containing all the extractors that needs to be executed. */
ExtractorRunDatas extractors;
@ -832,10 +832,7 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
return;
}
MeshRenderData mr;
memset(&mr, 0, sizeof(MeshRenderData));
draw_subdiv_init_mesh_render_data(subdiv_cache, &mr, ts);
mesh_render_data_update_loose_geom(&mr, mbc, MR_ITER_LEDGE | MR_ITER_LVERT, MR_DATA_LOOSE_GEOM);
mesh_render_data_update_loose_geom(mr, mbc, MR_ITER_LEDGE | MR_ITER_LVERT, MR_DATA_LOOSE_GEOM);
void *data_stack = MEM_mallocN(extractors.data_size_total(), __func__);
uint32_t data_offset = 0;
@ -844,17 +841,17 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
void *buffer = mesh_extract_buffer_get(extractor, mbuflist);
void *data = POINTER_OFFSET(data_stack, data_offset);
extractor->init_subdiv(subdiv_cache, &mr, cache, buffer, data);
extractor->init_subdiv(subdiv_cache, mr, cache, buffer, data);
if (extractor->iter_subdiv_mesh || extractor->iter_subdiv_bm) {
int *subdiv_loop_poly_index = subdiv_cache->subdiv_loop_poly_index;
if (subdiv_cache->bm) {
if (mr->extract_type == MR_EXTRACT_BMESH) {
for (uint i = 0; i < subdiv_cache->num_subdiv_quads; i++) {
/* Multiply by 4 to have the start index of the quad's loop, as subdiv_loop_poly_index is
* based on the subdivision loops. */
const int poly_origindex = subdiv_loop_poly_index[i * 4];
const BMFace *efa = bm_original_face_get(&mr, poly_origindex);
extractor->iter_subdiv_bm(subdiv_cache, &mr, data, i, efa);
const BMFace *efa = BM_face_at_index(mr->bm, poly_origindex);
extractor->iter_subdiv_bm(subdiv_cache, mr, data, i, efa);
}
}
else {
@ -862,18 +859,18 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
/* Multiply by 4 to have the start index of the quad's loop, as subdiv_loop_poly_index is
* based on the subdivision loops. */
const int poly_origindex = subdiv_loop_poly_index[i * 4];
const MPoly *mp = &mr.mpoly[poly_origindex];
extractor->iter_subdiv_mesh(subdiv_cache, &mr, data, i, mp);
const MPoly *mp = &mr->mpoly[poly_origindex];
extractor->iter_subdiv_mesh(subdiv_cache, mr, data, i, mp);
}
}
}
if (extractor->iter_loose_geom_subdiv) {
extractor->iter_loose_geom_subdiv(subdiv_cache, &mr, &mbc->loose_geom, buffer, data);
extractor->iter_loose_geom_subdiv(subdiv_cache, mr, &mbc->loose_geom, buffer, data);
}
if (extractor->finish_subdiv) {
extractor->finish_subdiv(subdiv_cache, &mr, cache, buffer, data);
extractor->finish_subdiv(subdiv_cache, mr, cache, buffer, data);
}
}
MEM_freeN(data_stack);
@ -921,9 +918,9 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
MeshBufferCache *mbc,
DRWSubdivCache *subdiv_cache,
const ToolSettings *ts)
MeshRenderData *mr)
{
blender::draw::mesh_buffer_cache_create_requested_subdiv(cache, mbc, subdiv_cache, ts);
blender::draw::mesh_buffer_cache_create_requested_subdiv(cache, mbc, subdiv_cache, mr);
}
} // extern "C"

View File

@ -2062,7 +2062,20 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
}
if (do_subdivision) {
DRW_create_subdivision(scene, ob, me, cache, &cache->final, ts);
DRW_create_subdivision(scene,
ob,
me,
cache,
&cache->final,
is_editmode,
is_paint_mode,
is_mode_active,
ob->obmat,
true,
false,
use_subsurf_fdots,
ts,
use_hide);
}
else {
/* The subsurf modifier may have been recently removed, or another modifier was added after it,

View File

@ -552,7 +552,6 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache)
GPU_VERTBUF_DISCARD_SAFE(cache->extra_coarse_face_data);
MEM_SAFE_FREE(cache->subdiv_loop_subdiv_vert_index);
MEM_SAFE_FREE(cache->subdiv_loop_poly_index);
MEM_SAFE_FREE(cache->point_indices);
MEM_SAFE_FREE(cache->subdiv_polygon_offset);
GPU_VERTBUF_DISCARD_SAFE(cache->subdiv_vertex_face_adjacency_offsets);
GPU_VERTBUF_DISCARD_SAFE(cache->subdiv_vertex_face_adjacency);
@ -593,7 +592,9 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache)
SUBDIV_COARSE_FACE_FLAG_ACTIVE) \
<< SUBDIV_COARSE_FACE_FLAG_OFFSET)
static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cache, Mesh *mesh)
static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cache,
Mesh *mesh,
MeshRenderData *mr)
{
if (cache->extra_coarse_face_data == nullptr) {
cache->extra_coarse_face_data = GPU_vertbuf_calloc();
@ -602,12 +603,14 @@ static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cach
GPU_vertformat_attr_add(&format, "data", GPU_COMP_U32, 1, GPU_FETCH_INT);
}
GPU_vertbuf_init_with_format_ex(cache->extra_coarse_face_data, &format, GPU_USAGE_DYNAMIC);
GPU_vertbuf_data_alloc(cache->extra_coarse_face_data, mesh->totpoly);
GPU_vertbuf_data_alloc(cache->extra_coarse_face_data,
mr->extract_type == MR_EXTRACT_BMESH ? cache->bm->totface :
mesh->totpoly);
}
uint32_t *flags_data = (uint32_t *)(GPU_vertbuf_get_data(cache->extra_coarse_face_data));
if (cache->bm) {
if (mr->extract_type == MR_EXTRACT_BMESH) {
BMesh *bm = cache->bm;
BMFace *f;
BMIter iter;
@ -622,13 +625,34 @@ static void draw_subdiv_cache_update_extra_coarse_face_data(DRWSubdivCache *cach
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
flag |= SUBDIV_COARSE_FACE_FLAG_SELECT;
}
if (f == bm->act_face) {
if (f == mr->efa_act) {
flag |= SUBDIV_COARSE_FACE_FLAG_ACTIVE;
}
const int loopstart = BM_elem_index_get(f->l_first);
flags_data[index] = (uint)(loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
}
}
else if (mr->extract_type == MR_EXTRACT_MAPPED) {
for (int i = 0; i < mesh->totpoly; i++) {
BMFace *f = bm_original_face_get(mr, i);
uint32_t flag = 0;
if (f) {
if (BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
flag |= SUBDIV_COARSE_FACE_FLAG_SMOOTH;
}
if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
flag |= SUBDIV_COARSE_FACE_FLAG_SELECT;
}
if (f == mr->efa_act) {
flag |= SUBDIV_COARSE_FACE_FLAG_ACTIVE;
}
const int loopstart = BM_elem_index_get(f->l_first);
flag = (uint)(loopstart) | (flag << SUBDIV_COARSE_FACE_FLAG_OFFSET);
}
flags_data[i] = flag;
}
}
else {
for (int i = 0; i < mesh->totpoly; i++) {
uint32_t flag = 0;
@ -669,6 +693,7 @@ static DRWSubdivCache *mesh_batch_cache_ensure_subdiv_cache(MeshBatchCache *mbc)
struct DRWCacheBuildingContext {
const Mesh *coarse_mesh;
const Subdiv *subdiv;
const SubdivToMeshSettings *settings;
DRWSubdivCache *cache;
@ -679,7 +704,6 @@ struct DRWCacheBuildingContext {
int *subdiv_loop_subdiv_vert_index;
int *subdiv_loop_edge_index;
int *subdiv_loop_poly_index;
int *point_indices;
/* Temporary buffers used during traversal. */
int *vert_origindex_map;
@ -737,20 +761,12 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
cache->subdiv_loop_poly_index = static_cast<int *>(
MEM_mallocN(cache->num_subdiv_loops * sizeof(int), "subdiv_loop_poly_index"));
const int num_coarse_vertices = ctx->coarse_mesh->totvert;
cache->point_indices = static_cast<int *>(
MEM_mallocN(num_coarse_vertices * sizeof(int), "point_indices"));
for (int i = 0; i < num_coarse_vertices; i++) {
cache->point_indices[i] = -1;
}
/* Initialize context pointers and temporary buffers. */
ctx->patch_coords = (CompressedPatchCoord *)GPU_vertbuf_get_data(cache->patch_coords);
ctx->subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(cache->verts_orig_index);
ctx->subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(cache->edges_orig_index);
ctx->subdiv_loop_subdiv_vert_index = cache->subdiv_loop_subdiv_vert_index;
ctx->subdiv_loop_poly_index = cache->subdiv_loop_poly_index;
ctx->point_indices = cache->point_indices;
ctx->v_origindex = static_cast<int *>(
CustomData_get_layer(&ctx->coarse_mesh->vdata, CD_ORIGINDEX));
@ -839,17 +855,6 @@ static void draw_subdiv_loop_cb(const SubdivForeachContext *foreach_context,
int coarse_vertex_index = ctx->vert_origindex_map[subdiv_vertex_index];
if (coarse_vertex_index != -1) {
if (ctx->v_origindex) {
coarse_vertex_index = ctx->v_origindex[coarse_vertex_index];
}
/* Double check as vorigindex may have modified the index. */
if (coarse_vertex_index != -1) {
ctx->point_indices[coarse_vertex_index] = subdiv_loop_index;
}
}
ctx->subdiv_loop_subdiv_vert_index[subdiv_loop_index] = subdiv_vertex_index;
/* For now index the subdiv_edge_index, it will be replaced by the actual coarse edge index
* at the end of the traversal as some edges are only then traversed. */
@ -1012,7 +1017,6 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache,
cache->face_ptex_offset_buffer = draw_subdiv_build_origindex_buffer(cache->face_ptex_offset,
mesh_eval->totpoly + 1);
cache->num_coarse_poly = mesh_eval->totpoly;
cache->point_indices = cache_building_context.point_indices;
build_vertex_face_adjacency_maps(cache);
@ -1085,7 +1089,7 @@ static void draw_subdiv_init_ubo_storage(const DRWSubdivCache *cache,
ubo->max_patch_face = cache->gpu_patch_map.max_patch_face;
ubo->max_depth = cache->gpu_patch_map.max_depth;
ubo->patches_are_triangular = cache->gpu_patch_map.patches_are_triangular;
ubo->coarse_poly_count = cache->num_coarse_poly;
ubo->coarse_poly_count = cache->bm ? cache->bm->totface : cache->num_coarse_poly;
ubo->optimal_display = cache->optimal_display;
ubo->num_subdiv_loops = cache->num_subdiv_loops;
ubo->edge_loose_offset = cache->num_subdiv_loops * 2;
@ -1649,50 +1653,6 @@ void draw_subdiv_build_edituv_stretch_angle_buffer(const DRWSubdivCache *cache,
/* -------------------------------------------------------------------- */
void draw_subdiv_init_mesh_render_data(DRWSubdivCache *cache,
MeshRenderData *mr,
const ToolSettings *toolsettings)
{
Mesh *mesh = cache->mesh;
/* Setup required data for loose geometry. */
mr->me = mesh;
mr->medge = mesh->medge;
mr->mvert = mesh->mvert;
mr->mpoly = mesh->mpoly;
mr->mloop = mesh->mloop;
mr->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
mr->vert_len = mesh->totvert;
mr->edge_len = mesh->totedge;
mr->poly_len = mesh->totpoly;
mr->loop_len = mesh->totloop;
mr->extract_type = MR_EXTRACT_MESH;
mr->toolsettings = toolsettings;
mr->v_origindex = static_cast<int *>(CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX));
mr->e_origindex = static_cast<int *>(CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX));
mr->p_origindex = static_cast<int *>(CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX));
/* MeshRenderData is only used for generating edit mode data here. */
if (!cache->bm) {
return;
}
BMesh *bm = cache->bm;
BM_mesh_elem_table_ensure(bm, BM_EDGE | BM_FACE | BM_VERT);
mr->bm = bm;
mr->eed_act = BM_mesh_active_edge_get(bm);
mr->efa_act = BM_mesh_active_face_get(bm, false, true);
mr->eve_act = BM_mesh_active_vert_get(bm);
mr->edge_crease_ofs = CustomData_get_offset(&bm->edata, CD_CREASE);
mr->vert_crease_ofs = CustomData_get_offset(&bm->vdata, CD_CREASE);
mr->bweight_ofs = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
#ifdef WITH_FREESTYLE
mr->freestyle_edge_ofs = CustomData_get_offset(&bm->edata, CD_FREESTYLE_EDGE);
mr->freestyle_face_ofs = CustomData_get_offset(&bm->pdata, CD_FREESTYLE_FACE);
#endif
}
/**
* For material assignments we want indices for triangles that share a common material to be laid
* out contiguously in memory. To achieve this, we sort the indices based on which material the
@ -1796,7 +1756,15 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
Mesh *mesh,
struct MeshBatchCache *batch_cache,
MeshBufferCache *mbc,
const ToolSettings *toolsettings,
const bool is_editmode,
const bool is_paint_mode,
const bool is_mode_active,
const float obmat[4][4],
const bool do_final,
const bool do_uvedit,
const bool use_subsurf_fdots,
const ToolSettings *ts,
const bool use_hide,
OpenSubdiv_EvaluatorCache *evaluator_cache)
{
SubsurfModifierData *smd = BKE_object_get_last_subsurf_modifier(ob);
@ -1849,9 +1817,14 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
draw_subdiv_cache_ensure_mat_offsets(draw_cache, mesh_eval, batch_cache->mat_len);
}
draw_subdiv_cache_update_extra_coarse_face_data(draw_cache, mesh_eval);
MeshRenderData *mr = mesh_render_data_create(
ob, mesh, is_editmode, is_paint_mode, is_mode_active, obmat, do_final, do_uvedit, ts);
mesh_buffer_cache_create_requested_subdiv(batch_cache, mbc, draw_cache, toolsettings);
draw_subdiv_cache_update_extra_coarse_face_data(draw_cache, mesh_eval, mr);
mesh_buffer_cache_create_requested_subdiv(batch_cache, mbc, draw_cache, mr);
mesh_render_data_free(mr);
return true;
}
@ -1863,7 +1836,15 @@ void DRW_create_subdivision(const Scene *scene,
Mesh *mesh,
struct MeshBatchCache *batch_cache,
MeshBufferCache *mbc,
const ToolSettings *toolsettings)
const bool is_editmode,
const bool is_paint_mode,
const bool is_mode_active,
const float obmat[4][4],
const bool do_final,
const bool do_uvedit,
const bool use_subsurf_fdots,
const ToolSettings *ts,
const bool use_hide)
{
if (g_evaluator_cache == nullptr) {
g_evaluator_cache = openSubdiv_createEvaluatorCache(OPENSUBDIV_EVALUATOR_GLSL_COMPUTE);
@ -1875,8 +1856,21 @@ void DRW_create_subdivision(const Scene *scene,
const double begin_time = PIL_check_seconds_timer();
#endif
if (!draw_subdiv_create_requested_buffers(
scene, ob, mesh, batch_cache, mbc, toolsettings, g_evaluator_cache)) {
if (!draw_subdiv_create_requested_buffers(scene,
ob,
mesh,
batch_cache,
mbc,
is_editmode,
is_paint_mode,
is_mode_active,
obmat,
do_final,
do_uvedit,
use_subsurf_fdots,
ts,
use_hide,
g_evaluator_cache)) {
return;
}

View File

@ -128,7 +128,17 @@ void DRW_create_subdivision(const struct Scene *scene,
struct Mesh *mesh,
struct MeshBatchCache *batch_cache,
struct MeshBufferCache *mbc,
const struct ToolSettings *toolsettings);
const bool is_editmode,
const bool is_paint_mode,
const bool is_mode_active,
const float obmat[4][4],
const bool do_final,
const bool do_uvedit,
const bool use_subsurf_fdots,
const ToolSettings *ts,
const bool use_hide);
void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, struct MeshBufferCache *cache);
void DRW_subdiv_cache_free(struct Subdiv *subdiv);

View File

@ -147,16 +147,55 @@ static void extract_points_init_subdiv(const DRWSubdivCache *subdiv_cache,
void *data)
{
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
/* Copy the points as the data upload will free them. */
elb->data = (uint *)MEM_dupallocN(subdiv_cache->point_indices);
elb->index_len = mr->vert_len;
elb->index_min = 0;
elb->index_max = subdiv_cache->num_subdiv_loops + mr->loop_loose_len;
elb->prim_type = GPU_PRIM_POINTS;
GPU_indexbuf_init(
elb, GPU_PRIM_POINTS, mr->vert_len, subdiv_cache->num_subdiv_loops + mr->loop_loose_len);
}
static void extract_points_iter_subdiv_common(GPUIndexBufBuilder *elb,
const MeshRenderData *mr,
const DRWSubdivCache *subdiv_cache,
uint subdiv_quad_index)
{
int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index);
uint start_loop_idx = subdiv_quad_index * 4;
uint end_loop_idx = (subdiv_quad_index + 1) * 4;
for (uint i = start_loop_idx; i < end_loop_idx; i++) {
int coarse_vertex_index = subdiv_loop_vert_index[i];
if (coarse_vertex_index == -1) {
continue;
}
if (mr->v_origindex && mr->v_origindex[coarse_vertex_index] == -1) {
continue;
}
GPU_indexbuf_set_point_vert(elb, coarse_vertex_index, i);
}
}
static void extract_points_iter_subdiv_bm(const DRWSubdivCache *subdiv_cache,
const MeshRenderData *mr,
void *_data,
uint subdiv_quad_index,
const BMFace *UNUSED(coarse_quad))
{
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data);
extract_points_iter_subdiv_common(elb, mr, subdiv_cache, subdiv_quad_index);
}
static void extract_points_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache,
const MeshRenderData *mr,
void *_data,
uint subdiv_quad_index,
const MPoly *UNUSED(coarse_quad))
{
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_data);
extract_points_iter_subdiv_common(elb, mr, subdiv_cache, subdiv_quad_index);
}
static void extract_points_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
const MeshRenderData *UNUSED(mr),
const MeshRenderData *mr,
const MeshExtractLooseGeom *loose_geom,
void *UNUSED(buffer),
void *data)
@ -167,28 +206,38 @@ static void extract_points_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
}
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
const Mesh *coarse_mesh = subdiv_cache->mesh;
const MEdge *coarse_edges = coarse_mesh->medge;
uint offset = subdiv_cache->num_subdiv_loops;
for (int i = 0; i < loose_geom->edge_len; i++) {
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
if (elb->data[loose_edge->v1] == -1u) {
GPU_indexbuf_set_point_vert(elb, loose_edge->v1, offset);
}
if (elb->data[loose_edge->v2] == -1u) {
GPU_indexbuf_set_point_vert(elb, loose_edge->v2, offset + 1);
}
offset += 2;
}
if (mr->extract_type == MR_EXTRACT_MESH) {
const Mesh *coarse_mesh = subdiv_cache->mesh;
const MEdge *coarse_edges = coarse_mesh->medge;
for (int i = 0; i < loose_geom->vert_len; i++) {
if (elb->data[loose_geom->verts[i]] == -1u) {
GPU_indexbuf_set_point_vert(elb, loose_geom->verts[i], offset);
for (int i = 0; i < loose_geom->edge_len; i++) {
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
vert_set_mesh(elb, mr, loose_edge->v1, offset);
vert_set_mesh(elb, mr, loose_edge->v2, offset + 1);
offset += 2;
}
for (int i = 0; i < loose_geom->vert_len; i++) {
vert_set_mesh(elb, mr, loose_geom->verts[i], offset);
offset += 1;
}
}
else {
BMesh *bm = mr->bm;
for (int i = 0; i < loose_geom->edge_len; i++) {
const BMEdge *loose_edge = BM_edge_at_index(bm, loose_geom->edges[i]);
vert_set_bm(elb, loose_edge->v1, offset);
vert_set_bm(elb, loose_edge->v2, offset + 1);
offset += 2;
}
for (int i = 0; i < loose_geom->vert_len; i++) {
const BMVert *loose_vert = BM_vert_at_index(bm, loose_geom->verts[i]);
vert_set_bm(elb, loose_vert, offset);
offset += 1;
}
offset += 1;
}
}
@ -216,6 +265,8 @@ constexpr MeshExtract create_extractor_points()
extractor.task_reduce = extract_points_task_reduce;
extractor.finish = extract_points_finish;
extractor.init_subdiv = extract_points_init_subdiv;
extractor.iter_subdiv_bm = extract_points_iter_subdiv_bm;
extractor.iter_subdiv_mesh = extract_points_iter_subdiv_mesh;
extractor.iter_loose_geom_subdiv = extract_points_loose_geom_subdiv;
extractor.finish_subdiv = extract_points_finish_subdiv;
extractor.use_threading = true;

View File

@ -272,21 +272,24 @@ static void extract_edit_data_iter_subdiv_bm(const DRWSubdivCache *subdiv_cache,
memset(edit_loop_data, 0, sizeof(EditLoopData));
if (vert_origindex != -1) {
const BMVert *eve = bm_original_vert_get(mr, vert_origindex);
const BMVert *eve = mr->v_origindex ? bm_original_vert_get(mr, vert_origindex) :
BM_vert_at_index(mr->bm, vert_origindex);
if (eve) {
mesh_render_data_vert_flag(mr, eve, edit_loop_data);
}
}
if (edge_origindex != -1) {
const BMEdge *eed = bm_original_edge_get(mr, edge_origindex);
if (eed) {
mesh_render_data_edge_flag(mr, eed, edit_loop_data);
}
/* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
const BMEdge *eed = BM_edge_at_index(mr->bm, edge_origindex);
mesh_render_data_edge_flag(mr, eed, edit_loop_data);
}
/* The -1 parameter is for edit_uvs, which we don't do here. */
mesh_render_data_face_flag(mr, coarse_quad, -1, edit_loop_data);
/* coarse_quad can be null when called by the mesh iteration below. */
if (coarse_quad) {
/* The -1 parameter is for edit_uvs, which we don't do here. */
mesh_render_data_face_flag(mr, coarse_quad, -1, edit_loop_data);
}
}
}
@ -317,7 +320,9 @@ static void extract_edit_data_loose_geom_subdiv(const DRWSubdivCache *subdiv_cac
const int offset = subdiv_cache->num_subdiv_loops + ledge_index * 2;
EditLoopData *data = &vbo_data[offset];
memset(data, 0, sizeof(EditLoopData));
BMEdge *eed = bm_original_edge_get(mr, loose_geom->edges[ledge_index]);
const int edge_index = loose_geom->edges[ledge_index];
BMEdge *eed = mr->e_origindex ? bm_original_edge_get(mr, edge_index) :
BM_edge_at_index(mr->bm, edge_index);
mesh_render_data_edge_flag(mr, eed, &data[0]);
data[1] = data[0];
mesh_render_data_vert_flag(mr, eed->v1, &data[0]);

View File

@ -143,7 +143,7 @@ static void extract_edituv_data_iter_subdiv_bm(const DRWSubdivCache *subdiv_cach
memset(edit_loop_data, 0, sizeof(EditLoopData));
if (vert_origindex != -1 && edge_origindex != -1) {
BMEdge *eed = bm_original_edge_get(mr, edge_origindex);
BMEdge *eed = BM_edge_at_index(mr->bm, edge_origindex);
/* Loop on an edge endpoint. */
BMLoop *l = BM_face_edge_share_loop(const_cast<BMFace *>(coarse_quad), eed);
mesh_render_data_loop_flag(mr, l, data->cd_ofs, edit_loop_data);

View File

@ -249,9 +249,6 @@ static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache
}
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
const Mesh *coarse_mesh = subdiv_cache->mesh;
const MEdge *coarse_edges = coarse_mesh->medge;
const MVert *coarse_verts = coarse_mesh->mvert;
uint offset = subdiv_cache->num_subdiv_loops;
/* TODO(@kevindietrich): replace this when compressed normals are supported. */
@ -261,38 +258,75 @@ static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache
float flag;
};
SubdivPosNorLoop edge_data[2];
for (int i = 0; i < loose_geom->edge_len; i++) {
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
const MVert *loose_vert1 = &coarse_verts[loose_edge->v1];
const MVert *loose_vert2 = &coarse_verts[loose_edge->v2];
if (mr->extract_type == MR_EXTRACT_MESH) {
const Mesh *coarse_mesh = subdiv_cache->mesh;
const MEdge *coarse_edges = coarse_mesh->medge;
const MVert *coarse_verts = coarse_mesh->mvert;
copy_v3_v3(edge_data[0].pos, loose_vert1->co);
copy_v3_v3(edge_data[0].nor, mr->vert_normals[loose_edge->v1]);
edge_data[0].flag = 0.0f;
SubdivPosNorLoop edge_data[2];
memset(&edge_data, 0, sizeof(SubdivPosNorLoop) * 2);
for (int i = 0; i < loose_geom->edge_len; i++) {
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
const MVert *loose_vert1 = &coarse_verts[loose_edge->v1];
const MVert *loose_vert2 = &coarse_verts[loose_edge->v2];
copy_v3_v3(edge_data[1].pos, loose_vert2->co);
copy_v3_v3(edge_data[1].nor, mr->vert_normals[loose_edge->v2]);
edge_data[1].flag = 0.0f;
copy_v3_v3(edge_data[0].pos, loose_vert1->co);
copy_v3_v3(edge_data[1].pos, loose_vert2->co);
GPU_vertbuf_update_sub(
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data);
GPU_vertbuf_update_sub(
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data);
offset += 2;
offset += 2;
}
SubdivPosNorLoop vert_data;
memset(&vert_data, 0, sizeof(SubdivPosNorLoop));
for (int i = 0; i < loose_geom->vert_len; i++) {
const MVert *loose_vertex = &coarse_verts[loose_geom->verts[i]];
copy_v3_v3(vert_data.pos, loose_vertex->co);
GPU_vertbuf_update_sub(
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data);
offset += 1;
}
}
else {
BMesh *bm = subdiv_cache->bm;
SubdivPosNorLoop vert_data;
vert_data.flag = 0.0f;
for (int i = 0; i < loose_geom->vert_len; i++) {
const MVert *loose_vertex = &coarse_verts[loose_geom->verts[i]];
SubdivPosNorLoop edge_data[2];
memset(&edge_data, 0, sizeof(SubdivPosNorLoop) * 2);
for (int i = 0; i < loose_geom->edge_len; i++) {
const BMEdge *loose_edge = BM_edge_at_index(bm, loose_geom->edges[i]);
const BMVert *loose_vert1 = loose_edge->v1;
const BMVert *loose_vert2 = loose_edge->v2;
copy_v3_v3(vert_data.pos, loose_vertex->co);
copy_v3_v3(vert_data.nor, mr->vert_normals[loose_geom->verts[i]]);
copy_v3_v3(edge_data[0].pos, loose_vert1->co);
copy_v3_v3(edge_data[0].nor, loose_vert1->no);
GPU_vertbuf_update_sub(
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data);
copy_v3_v3(edge_data[1].pos, loose_vert2->co);
copy_v3_v3(edge_data[1].nor, loose_vert2->no);
offset += 1;
GPU_vertbuf_update_sub(
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data);
offset += 2;
}
SubdivPosNorLoop vert_data;
memset(&vert_data, 0, sizeof(SubdivPosNorLoop));
for (int i = 0; i < loose_geom->vert_len; i++) {
const BMVert *loose_vertex = BM_vert_at_index(bm, loose_geom->verts[i]);
copy_v3_v3(vert_data.pos, loose_vertex->co);
copy_v3_v3(vert_data.nor, loose_vertex->no);
GPU_vertbuf_update_sub(
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data);
offset += 1;
}
}
}

View File

@ -190,13 +190,28 @@ static void extract_vert_idx_init_subdiv(const DRWSubdivCache *subdiv_cache,
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
/* Each element points to an element in the ibo.points. */
draw_subdiv_init_origindex_buffer(vbo,
subdiv_cache->subdiv_loop_subdiv_vert_index,
(int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index),
subdiv_cache->num_subdiv_loops,
mr->loop_loose_len);
if (!mr->v_origindex) {
return;
}
/* Remap the vertex indices to those pointed by the origin indices layer. At this point, the
* VBO data is a copy of #verts_orig_index which contains the coarse vertices indices, so
* the memory can both be accessed for lookup and immediately overwritten. */
int *vbo_data = static_cast<int *>(GPU_vertbuf_get_data(vbo));
for (int i = 0; i < subdiv_cache->num_subdiv_loops; i++) {
if (vbo_data[i] == -1) {
continue;
}
vbo_data[i] = mr->v_origindex[vbo_data[i]];
}
}
static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
const MeshRenderData *UNUSED(mr),
const MeshRenderData *mr,
const MeshExtractLooseGeom *loose_geom,
void *buffer,
void *UNUSED(data))
@ -208,20 +223,37 @@ static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cach
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
uint *vert_idx_data = (uint *)GPU_vertbuf_get_data(vbo);
const Mesh *coarse_mesh = subdiv_cache->mesh;
const MEdge *coarse_edges = coarse_mesh->medge;
uint offset = subdiv_cache->num_subdiv_loops;
for (int i = 0; i < loose_geom->edge_len; i++) {
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
vert_idx_data[offset] = loose_edge->v1;
vert_idx_data[offset + 1] = loose_edge->v2;
offset += 2;
}
if (mr->extract_type == MR_EXTRACT_MESH) {
const Mesh *coarse_mesh = subdiv_cache->mesh;
const MEdge *coarse_edges = coarse_mesh->medge;
for (int i = 0; i < loose_geom->edge_len; i++) {
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
vert_idx_data[offset] = loose_edge->v1;
vert_idx_data[offset + 1] = loose_edge->v2;
offset += 2;
}
for (int i = 0; i < loose_geom->vert_len; i++) {
vert_idx_data[offset] = loose_geom->verts[i];
offset += 1;
for (int i = 0; i < loose_geom->vert_len; i++) {
vert_idx_data[offset] = loose_geom->verts[i];
offset += 1;
}
}
else {
BMesh *bm = mr->bm;
for (int i = 0; i < loose_geom->edge_len; i++) {
const BMEdge *loose_edge = BM_edge_at_index(bm, loose_geom->edges[i]);
vert_idx_data[offset] = BM_elem_index_get(loose_edge->v1);
vert_idx_data[offset + 1] = BM_elem_index_get(loose_edge->v2);
offset += 2;
}
for (int i = 0; i < loose_geom->vert_len; i++) {
const BMVert *loose_vert = BM_vert_at_index(bm, loose_geom->verts[i]);
vert_idx_data[offset] = BM_elem_index_get(loose_vert);
offset += 1;
}
}
}
@ -262,7 +294,7 @@ static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cach
}
static void extract_poly_idx_init_subdiv(const DRWSubdivCache *subdiv_cache,
const MeshRenderData *UNUSED(mr),
const MeshRenderData *mr,
MeshBatchCache *UNUSED(cache),
void *buf,
void *UNUSED(data))
@ -270,6 +302,18 @@ static void extract_poly_idx_init_subdiv(const DRWSubdivCache *subdiv_cache,
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
draw_subdiv_init_origindex_buffer(
vbo, subdiv_cache->subdiv_loop_poly_index, subdiv_cache->num_subdiv_loops, 0);
if (!mr->p_origindex) {
return;
}
/* Remap the polygon indices to those pointed by the origin indices layer. At this point, the
* VBO data is a copy of #subdiv_loop_poly_index which contains the coarse polygon indices, so
* the memory can both be accessed for lookup and immediately overwritten. */
int *vbo_data = static_cast<int *>(GPU_vertbuf_get_data(vbo));
for (int i = 0; i < subdiv_cache->num_subdiv_loops; i++) {
vbo_data[i] = mr->p_origindex[vbo_data[i]];
}
}
constexpr MeshExtract create_extractor_poly_idx()

View File

@ -1004,7 +1004,6 @@ static void gpencil_invert_image(tGPDfill *tgpf)
ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
const int maxpixel = (ibuf->x * ibuf->y) - 1;
const int center = ibuf->x / 2;
for (int v = maxpixel; v != 0; v--) {
float color[4];
@ -1016,15 +1015,6 @@ static void gpencil_invert_image(tGPDfill *tgpf)
/* Red->Green */
else if (color[0] == 1.0f) {
set_pixel(ibuf, v, fill_col[1]);
/* Add thickness of 2 pixels to avoid too thin lines, but avoid extremes of the pixel line.
*/
int row = v / ibuf->x;
int lowpix = row * ibuf->x;
int highpix = lowpix + ibuf->x - 1;
if ((v > lowpix) && (v < highpix)) {
int offset = (v % ibuf->x < center) ? 1 : -1;
set_pixel(ibuf, v + offset, fill_col[1]);
}
}
else {
/* Set to Transparent. */
@ -1120,11 +1110,14 @@ static void gpencil_erase_processed_area(tGPDfill *tgpf)
*/
static bool dilate_shape(ImBuf *ibuf)
{
#define IS_RED (color[0] == 1.0f)
#define IS_GREEN (color[1] == 1.0f)
bool done = false;
BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
const float green[4] = {0.0f, 1.0f, 0.0f, 1.0f};
// const int maxpixel = (ibuf->x * ibuf->y) - 1;
const int max_size = (ibuf->x * ibuf->y) - 1;
/* detect pixels and expand into red areas */
for (int row = 0; row < ibuf->y; row++) {
if (!is_row_filled(ibuf, row)) {
@ -1137,7 +1130,7 @@ static bool dilate_shape(ImBuf *ibuf)
float color[4];
int index;
get_pixel(ibuf, v, color);
if (color[1] == 1.0f) {
if (IS_GREEN) {
int tp = 0;
int bm = 0;
int lt = 0;
@ -1147,7 +1140,7 @@ static bool dilate_shape(ImBuf *ibuf)
if (v - 1 >= 0) {
index = v - 1;
get_pixel(ibuf, index, color);
if (color[0] == 1.0f) {
if (IS_RED) {
BLI_stack_push(stack, &index);
lt = index;
}
@ -1156,25 +1149,25 @@ static bool dilate_shape(ImBuf *ibuf)
if (v + 1 <= maxpixel) {
index = v + 1;
get_pixel(ibuf, index, color);
if (color[0] == 1.0f) {
if (IS_RED) {
BLI_stack_push(stack, &index);
rt = index;
}
}
/* pixel top */
if (v + (ibuf->x * 1) <= maxpixel) {
index = v + (ibuf->x * 1);
if (v + ibuf->x <= max_size) {
index = v + ibuf->x;
get_pixel(ibuf, index, color);
if (color[0] == 1.0f) {
if (IS_RED) {
BLI_stack_push(stack, &index);
tp = index;
}
}
/* pixel bottom */
if (v - (ibuf->x * 1) >= 0) {
index = v - (ibuf->x * 1);
if (v - ibuf->x >= 0) {
index = v - ibuf->x;
get_pixel(ibuf, index, color);
if (color[0] == 1.0f) {
if (IS_RED) {
BLI_stack_push(stack, &index);
bm = index;
}
@ -1183,7 +1176,7 @@ static bool dilate_shape(ImBuf *ibuf)
if (tp && lt) {
index = tp - 1;
get_pixel(ibuf, index, color);
if (color[0] == 1.0f) {
if (IS_RED) {
BLI_stack_push(stack, &index);
}
}
@ -1191,7 +1184,7 @@ static bool dilate_shape(ImBuf *ibuf)
if (tp && rt) {
index = tp + 1;
get_pixel(ibuf, index, color);
if (color[0] == 1.0f) {
if (IS_RED) {
BLI_stack_push(stack, &index);
}
}
@ -1199,7 +1192,7 @@ static bool dilate_shape(ImBuf *ibuf)
if (bm && lt) {
index = bm - 1;
get_pixel(ibuf, index, color);
if (color[0] == 1.0f) {
if (IS_RED) {
BLI_stack_push(stack, &index);
}
}
@ -1207,7 +1200,7 @@ static bool dilate_shape(ImBuf *ibuf)
if (bm && rt) {
index = bm + 1;
get_pixel(ibuf, index, color);
if (color[0] == 1.0f) {
if (IS_RED) {
BLI_stack_push(stack, &index);
}
}
@ -1224,6 +1217,88 @@ static bool dilate_shape(ImBuf *ibuf)
BLI_stack_free(stack);
return done;
#undef IS_RED
#undef IS_GREEN
}
/**
* Contract
*
* Contract green areas to scale down the size.
* Using stack prevents creep when replacing colors directly.
*/
static bool contract_shape(ImBuf *ibuf)
{
#define IS_GREEN (color[1] == 1.0f)
#define IS_NOT_GREEN (color[1] != 1.0f)
bool done = false;
BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__);
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
const int max_size = (ibuf->x * ibuf->y) - 1;
/* Detect if pixel is near of no green pixels and mark green to be cleared. */
for (int row = 0; row < ibuf->y; row++) {
if (!is_row_filled(ibuf, row)) {
continue;
}
int maxpixel = (ibuf->x * (row + 1)) - 1;
int minpixel = ibuf->x * row;
for (int v = maxpixel; v != minpixel; v--) {
float color[4];
get_pixel(ibuf, v, color);
if (IS_GREEN) {
/* pixel left */
if (v - 1 >= 0) {
get_pixel(ibuf, v - 1, color);
if (IS_NOT_GREEN) {
BLI_stack_push(stack, &v);
continue;
}
}
/* pixel right */
if (v + 1 <= maxpixel) {
get_pixel(ibuf, v + 1, color);
if (IS_NOT_GREEN) {
BLI_stack_push(stack, &v);
continue;
}
}
/* pixel top */
if (v + ibuf->x <= max_size) {
get_pixel(ibuf, v + ibuf->x, color);
if (IS_NOT_GREEN) {
BLI_stack_push(stack, &v);
continue;
}
}
/* pixel bottom */
if (v - ibuf->x >= 0) {
get_pixel(ibuf, v - ibuf->x, color);
if (IS_NOT_GREEN) {
BLI_stack_push(stack, &v);
continue;
}
}
}
}
}
/* Clear pixels. */
while (!BLI_stack_is_empty(stack)) {
int v;
BLI_stack_pop(stack, &v);
set_pixel(ibuf, v, clear);
done = true;
}
BLI_stack_free(stack);
return done;
#undef IS_GREEN
#undef IS_NOT_GREEN
}
/* Get the outline points of a shape using Moore Neighborhood algorithm
@ -1265,10 +1340,15 @@ static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate)
ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
int imagesize = ibuf->x * ibuf->y;
/* Dilate. */
/* Dilate or contract. */
if (dilate) {
for (int i = 0; i < brush->gpencil_settings->dilate_pixels; i++) {
dilate_shape(ibuf);
for (int i = 0; i < abs(brush->gpencil_settings->dilate_pixels); i++) {
if (brush->gpencil_settings->dilate_pixels > 0) {
dilate_shape(ibuf);
}
else {
contract_shape(ibuf);
}
}
}
@ -1975,6 +2055,24 @@ static void gpencil_zoom_level_set(tGPDfill *tgpf)
}
}
static bool gpencil_find_and_mark_empty_areas(tGPDfill *tgpf)
{
ImBuf *ibuf;
void *lock;
const float blue_col[4] = {0.0f, 0.0f, 1.0f, 1.0f};
ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock);
const int maxpixel = (ibuf->x * ibuf->y) - 1;
float rgba[4];
for (int i = 0; i < maxpixel; i++) {
get_pixel(ibuf, i, rgba);
if (rgba[3] == 0.0f) {
set_pixel(ibuf, i, blue_col);
return true;
}
}
return false;
}
static bool gpencil_do_frame_fill(tGPDfill *tgpf, const bool is_inverted)
{
wmWindow *win = CTX_wm_window(tgpf->C);
@ -1995,6 +2093,9 @@ static bool gpencil_do_frame_fill(tGPDfill *tgpf, const bool is_inverted)
/* Invert direction if press Ctrl. */
if (is_inverted) {
gpencil_invert_image(tgpf);
while (gpencil_find_and_mark_empty_areas(tgpf)) {
gpencil_boundaryfill_area(tgpf);
}
}
/* Clean borders to avoid infinite loops. */

View File

@ -6329,6 +6329,10 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float color[4])
void uiTemplateCacheFileVelocity(uiLayout *layout, PointerRNA *fileptr)
{
if (RNA_pointer_is_null(fileptr)) {
return;
}
/* Ensure that the context has a CacheFile as this may not be set inside of modifiers panels. */
uiLayoutSetContextPointer(layout, "edit_cachefile", fileptr);
@ -6338,6 +6342,10 @@ void uiTemplateCacheFileVelocity(uiLayout *layout, PointerRNA *fileptr)
void uiTemplateCacheFileProcedural(uiLayout *layout, const bContext *C, PointerRNA *fileptr)
{
if (RNA_pointer_is_null(fileptr)) {
return;
}
/* Ensure that the context has a CacheFile as this may not be set inside of modifiers panels. */
uiLayoutSetContextPointer(layout, "edit_cachefile", fileptr);
@ -6384,6 +6392,10 @@ void uiTemplateCacheFileProcedural(uiLayout *layout, const bContext *C, PointerR
void uiTemplateCacheFileTimeSettings(uiLayout *layout, PointerRNA *fileptr)
{
if (RNA_pointer_is_null(fileptr)) {
return;
}
/* Ensure that the context has a CacheFile as this may not be set inside of modifiers panels. */
uiLayoutSetContextPointer(layout, "edit_cachefile", fileptr);
@ -6434,6 +6446,10 @@ uiListType *UI_UL_cache_file_layers()
void uiTemplateCacheFileLayers(uiLayout *layout, const bContext *C, PointerRNA *fileptr)
{
if (RNA_pointer_is_null(fileptr)) {
return;
}
/* Ensure that the context has a CacheFile as this may not be set inside of modifiers panels. */
uiLayoutSetContextPointer(layout, "edit_cachefile", fileptr);

View File

@ -1615,12 +1615,13 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
prop, "Stroke Extension", "Strokes end extension for closing gaps, use zero to disable");
RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
/* Number of pixels to dilate fill area. */
/* Number of pixels to dilate fill area. Negative values contract the filled area. */
prop = RNA_def_property(srna, "dilate", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "dilate_pixels");
RNA_def_property_range(prop, 0, 20);
RNA_def_property_range(prop, -40, 40);
RNA_def_property_int_default(prop, 1);
RNA_def_property_ui_text(prop, "Dilate", "Number of pixels to dilate fill area");
RNA_def_property_ui_text(
prop, "Dilate/Contract", "Number of pixels to expand or contract fill area");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);

View File

@ -331,6 +331,7 @@ const EnumPropertyItem rna_enum_object_axis_items[] = {
# include "BKE_key.h"
# include "BKE_material.h"
# include "BKE_mesh.h"
# include "BKE_mesh_wrapper.h"
# include "BKE_modifier.h"
# include "BKE_object.h"
# include "BKE_particle.h"
@ -510,6 +511,17 @@ void rna_Object_data_update(Main *bmain, Scene *scene, PointerRNA *ptr)
rna_Object_internal_update_data_dependency(bmain, scene, ptr);
}
static PointerRNA rna_Object_data_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->data;
if (ob->type == OB_MESH) {
Mesh *me = (Mesh *)ob->data;
me = BKE_mesh_wrapper_ensure_subdivision(ob, me);
return rna_pointer_inherit_refine(ptr, &RNA_Mesh, me);
}
return rna_pointer_inherit_refine(ptr, &RNA_ID, ob->data);
}
static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, struct ReportList *reports)
{
Object *ob = (Object *)ptr->data;
@ -3041,8 +3053,11 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ID");
RNA_def_property_pointer_funcs(
prop, NULL, "rna_Object_data_set", "rna_Object_data_typef", "rna_Object_data_poll");
RNA_def_property_pointer_funcs(prop,
"rna_Object_data_get",
"rna_Object_data_set",
"rna_Object_data_typef",
"rna_Object_data_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
RNA_def_property_ui_text(prop, "Data", "Object data");
RNA_def_property_update(prop, 0, "rna_Object_data_update");

View File

@ -329,10 +329,6 @@ static void velocity_panel_draw(const bContext *UNUSED(C), Panel *panel)
return;
}
if (RNA_pointer_is_null(&fileptr)) {
return;
}
uiLayoutSetPropSep(layout, true);
uiTemplateCacheFileVelocity(layout, &fileptr);
uiItemR(layout, ptr, "velocity_scale", 0, NULL, ICON_NONE);
@ -350,10 +346,6 @@ static void time_panel_draw(const bContext *UNUSED(C), Panel *panel)
return;
}
if (RNA_pointer_is_null(&fileptr)) {
return;
}
uiLayoutSetPropSep(layout, true);
uiTemplateCacheFileTimeSettings(layout, &fileptr);
}
@ -370,10 +362,6 @@ static void render_procedural_panel_draw(const bContext *C, Panel *panel)
return;
}
if (RNA_pointer_is_null(&fileptr)) {
return;
}
uiLayoutSetPropSep(layout, true);
uiTemplateCacheFileProcedural(layout, C, &fileptr);
}
@ -390,10 +378,6 @@ static void override_layers_panel_draw(const bContext *C, Panel *panel)
return;
}
if (RNA_pointer_is_null(&fileptr)) {
return;
}
uiLayoutSetPropSep(layout, true);
uiTemplateCacheFileLayers(layout, C, &fileptr);
}