diff options
Diffstat (limited to 'source/blender')
83 files changed, 1944 insertions, 1164 deletions
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index a8915c178d4..4076bca3b19 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -207,17 +207,15 @@ bool BKE_animsys_read_rna_setting(struct PathResolvedRNA *anim_rna, float *r_val bool BKE_animsys_write_rna_setting(struct PathResolvedRNA *anim_rna, const float value); /* Evaluation loop for evaluating animation data */ -void BKE_animsys_evaluate_animdata(struct Scene *scene, - struct ID *id, +void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, float ctime, - short recalc, + eAnimData_Recalc recalc, const bool flush_to_original); /* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only */ void BKE_animsys_evaluate_all_animation(struct Main *main, struct Depsgraph *depsgraph, - struct Scene *scene, float ctime); /* ------------ Specialized API --------------- */ diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index c9a4d81604b..bc64f78ffae 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -26,8 +26,8 @@ * * \note Use #STRINGIFY() rather than defining with quotes. */ -#define BLENDER_VERSION 283 -#define BLENDER_SUBVERSION 13 +#define BLENDER_VERSION 290 +#define BLENDER_SUBVERSION 0 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 @@ -36,7 +36,7 @@ /** Can be left blank, otherwise a,b,c... etc with no quotes. */ #define BLENDER_VERSION_CHAR /** alpha/beta/rc/release, docs use this. */ -#define BLENDER_VERSION_CYCLE beta +#define BLENDER_VERSION_CYCLE alpha /** Optionally set to 1,2,... for example to get alpha1 or rc2. */ #define BLENDER_VERSION_CYCLE_NUMBER diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 164867b228b..adc94a833c3 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -111,6 +111,8 @@ void BKE_curve_material_index_clear(struct Curve *cu); bool BKE_curve_material_index_validate(struct Curve *cu); void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsigned int remap_len); +void BKE_curve_smooth_flag_set(struct Curve *cu, bool set); + ListBase *BKE_curve_nurbs_get(struct Curve *cu); int BKE_curve_nurb_vert_index_get(const struct Nurb *nu, const void *vert); diff --git a/source/blender/blenkernel/BKE_fluid.h b/source/blender/blenkernel/BKE_fluid.h index e8b4c819c62..e06a1a9fb92 100644 --- a/source/blender/blenkernel/BKE_fluid.h +++ b/source/blender/blenkernel/BKE_fluid.h @@ -61,6 +61,7 @@ void BKE_fluid_reallocate_copy_fluid(struct FluidDomainSettings *mds, int o_max[3], int o_shift[3], int n_shift[3]); +void BKE_fluid_cache_free_all(struct FluidDomainSettings *mds, struct Object *ob); void BKE_fluid_cache_free(struct FluidDomainSettings *mds, struct Object *ob, int cache_map); void BKE_fluid_cache_new_name_for_current_session(int maxlen, char *r_name); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index ba77538bfb6..4f51e23496c 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1665,6 +1665,6 @@ void what_does_obaction( adt.action = act; /* execute effects of Action on to workob (or it's PoseChannels) */ - BKE_animsys_evaluate_animdata(NULL, &workob->id, &adt, cframe, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata(&workob->id, &adt, cframe, ADT_RECALC_ANIM, false); } } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 18320ef0f8d..de8d5af22ae 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -2500,7 +2500,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) * have been set already by the depsgraph. Now, we use the recalc */ void BKE_animsys_evaluate_animdata( - Scene *scene, ID *id, AnimData *adt, float ctime, short recalc, const bool flush_to_original) + ID *id, AnimData *adt, float ctime, eAnimData_Recalc recalc, const bool flush_to_original) { PointerRNA id_ptr; @@ -2547,13 +2547,6 @@ void BKE_animsys_evaluate_animdata( * - It is best that we execute this every time, so that no errors are likely to occur. */ animsys_evaluate_overrides(&id_ptr, adt); - - /* execute and clear all cached property update functions */ - if (scene) { - Main *bmain = G.main; // xxx - to get passed in! - RNA_property_update_cache_flush(bmain, scene); - RNA_property_update_cache_free(); - } } /* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only @@ -2563,10 +2556,7 @@ void BKE_animsys_evaluate_animdata( * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a * standard 'root') block are overridden by a larger 'user' */ -void BKE_animsys_evaluate_all_animation(Main *main, - Depsgraph *depsgraph, - Scene *scene, - float ctime) +void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float ctime) { ID *id; @@ -2585,7 +2575,7 @@ void BKE_animsys_evaluate_all_animation(Main *main, for (id = first; id; id = id->next) { \ if (ID_REAL_USERS(id) > 0) { \ AnimData *adt = BKE_animdata_from_id(id); \ - BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag, flush_to_original); \ + BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \ } \ } \ (void)0 @@ -2604,9 +2594,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, if (ntp->nodetree) { \ AnimData *adt2 = BKE_animdata_from_id((ID *)ntp->nodetree); \ BKE_animsys_evaluate_animdata( \ - scene, (ID *)ntp->nodetree, adt2, ctime, ADT_RECALC_ANIM, flush_to_original); \ + &ntp->nodetree->id, adt2, ctime, ADT_RECALC_ANIM, flush_to_original); \ } \ - BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag, flush_to_original); \ + BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \ } \ } \ (void)0 @@ -2718,10 +2708,9 @@ void BKE_animsys_eval_animdata(Depsgraph *depsgraph, ID *id) AnimData *adt = BKE_animdata_from_id(id); /* XXX: this is only needed for flushing RNA updates, * which should get handled as part of the dependency graph instead. */ - Scene *scene = NULL; DEG_debug_print_eval_time(depsgraph, __func__, id->name, id, ctime); const bool flush_to_original = DEG_is_active(depsgraph); - BKE_animsys_evaluate_animdata(scene, id, adt, ctime, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM, flush_to_original); } void BKE_animsys_update_driver_array(ID *id) diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 2a53a0b69a4..0d5d35e3508 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -258,9 +258,6 @@ static void setup_app_data(bContext *C, // CTX_wm_manager_set(C, NULL); BKE_blender_globals_clear(); - /* clear old property update cache, in case some old references are left dangling */ - RNA_property_update_cache_free(); - bmain = G_MAIN = bfd->main; bfd->main = NULL; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index f82b8b6675c..3da384a2745 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1383,8 +1383,6 @@ typedef struct ScopesUpdateData { struct ColormanageProcessor *cm_processor; const unsigned char *display_buffer; const int ycc_mode; - - unsigned int *bin_lum, *bin_r, *bin_g, *bin_b, *bin_a; } ScopesUpdateData; typedef struct ScopesUpdateDataChunk { @@ -1495,23 +1493,24 @@ static void scopes_update_cb(void *__restrict userdata, } } -static void scopes_update_finalize(void *__restrict userdata, void *__restrict userdata_chunk) +static void scopes_update_reduce(const void *__restrict UNUSED(userdata), + void *__restrict chunk_join, + void *__restrict chunk) { - const ScopesUpdateData *data = userdata; - const ScopesUpdateDataChunk *data_chunk = userdata_chunk; - - unsigned int *bin_lum = data->bin_lum; - unsigned int *bin_r = data->bin_r; - unsigned int *bin_g = data->bin_g; - unsigned int *bin_b = data->bin_b; - unsigned int *bin_a = data->bin_a; + ScopesUpdateDataChunk *join_chunk = chunk_join; + const ScopesUpdateDataChunk *data_chunk = chunk; + + unsigned int *bin_lum = join_chunk->bin_lum; + unsigned int *bin_r = join_chunk->bin_r; + unsigned int *bin_g = join_chunk->bin_g; + unsigned int *bin_b = join_chunk->bin_b; + unsigned int *bin_a = join_chunk->bin_a; const unsigned int *bin_lum_c = data_chunk->bin_lum; const unsigned int *bin_r_c = data_chunk->bin_r; const unsigned int *bin_g_c = data_chunk->bin_g; const unsigned int *bin_b_c = data_chunk->bin_b; const unsigned int *bin_a_c = data_chunk->bin_a; - float(*minmax)[2] = data->scopes->minmax; const float *min = data_chunk->min; const float *max = data_chunk->max; @@ -1524,11 +1523,11 @@ static void scopes_update_finalize(void *__restrict userdata, void *__restrict u } for (int c = 3; c--;) { - if (min[c] < minmax[c][0]) { - minmax[c][0] = min[c]; + if (min[c] < join_chunk->min[c]) { + join_chunk->min[c] = min[c]; } - if (max[c] > minmax[c][1]) { - minmax[c][1] = max[c]; + if (max[c] > join_chunk->max[c]) { + join_chunk->max[c] = max[c]; } } } @@ -1542,7 +1541,6 @@ void BKE_scopes_update(Scopes *scopes, unsigned int nl, na, nr, ng, nb; double divl, diva, divr, divg, divb; const unsigned char *display_buffer = NULL; - uint bin_lum[256] = {0}, bin_r[256] = {0}, bin_g[256] = {0}, bin_b[256] = {0}, bin_a[256] = {0}; int ycc_mode = -1; void *cache_handle = NULL; struct ColormanageProcessor *cm_processor = NULL; @@ -1638,11 +1636,6 @@ void BKE_scopes_update(Scopes *scopes, .cm_processor = cm_processor, .display_buffer = display_buffer, .ycc_mode = ycc_mode, - .bin_lum = bin_lum, - .bin_r = bin_r, - .bin_g = bin_g, - .bin_b = bin_b, - .bin_a = bin_a, }; ScopesUpdateDataChunk data_chunk = {{0}}; INIT_MINMAX(data_chunk.min, data_chunk.max); @@ -1652,26 +1645,26 @@ void BKE_scopes_update(Scopes *scopes, settings.use_threading = (ibuf->y > 256); settings.userdata_chunk = &data_chunk; settings.userdata_chunk_size = sizeof(data_chunk); - settings.func_finalize = scopes_update_finalize; + settings.func_reduce = scopes_update_reduce; BLI_task_parallel_range(0, ibuf->y, &data, scopes_update_cb, &settings); /* convert hist data to float (proportional to max count) */ nl = na = nr = nb = ng = 0; for (a = 0; a < 256; a++) { - if (bin_lum[a] > nl) { - nl = bin_lum[a]; + if (data_chunk.bin_lum[a] > nl) { + nl = data_chunk.bin_lum[a]; } - if (bin_r[a] > nr) { - nr = bin_r[a]; + if (data_chunk.bin_r[a] > nr) { + nr = data_chunk.bin_r[a]; } - if (bin_g[a] > ng) { - ng = bin_g[a]; + if (data_chunk.bin_g[a] > ng) { + ng = data_chunk.bin_g[a]; } - if (bin_b[a] > nb) { - nb = bin_b[a]; + if (data_chunk.bin_b[a] > nb) { + nb = data_chunk.bin_b[a]; } - if (bin_a[a] > na) { - na = bin_a[a]; + if (data_chunk.bin_a[a] > na) { + na = data_chunk.bin_a[a]; } } divl = nl ? 1.0 / (double)nl : 1.0; @@ -1681,11 +1674,11 @@ void BKE_scopes_update(Scopes *scopes, divb = nb ? 1.0 / (double)nb : 1.0; for (a = 0; a < 256; a++) { - scopes->hist.data_luma[a] = bin_lum[a] * divl; - scopes->hist.data_r[a] = bin_r[a] * divr; - scopes->hist.data_g[a] = bin_g[a] * divg; - scopes->hist.data_b[a] = bin_b[a] * divb; - scopes->hist.data_a[a] = bin_a[a] * diva; + scopes->hist.data_luma[a] = data_chunk.bin_lum[a] * divl; + scopes->hist.data_r[a] = data_chunk.bin_r[a] * divr; + scopes->hist.data_g[a] = data_chunk.bin_g[a] * divg; + scopes->hist.data_b[a] = data_chunk.bin_b[a] * divb; + scopes->hist.data_a[a] = data_chunk.bin_a[a] * diva; } if (cm_processor) { diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index b4a8625c0bb..76dec63903b 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -5506,6 +5506,20 @@ void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int #undef MAT_NR_REMAP } +void BKE_curve_smooth_flag_set(Curve *cu, const bool use_smooth) +{ + if (use_smooth) { + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + nu->flag |= CU_SMOOTH; + } + } + else { + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + nu->flag &= ~CU_SMOOTH; + } + } +} + void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect) diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 4c78c88d168..3a8b846a41d 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -653,15 +653,15 @@ static void grid_bound_insert_cb_ex(void *__restrict userdata, boundInsert(grid_bound, bData->realCoord[bData->s_pos[i]].v); } -static void grid_bound_insert_finalize(void *__restrict userdata, void *__restrict userdata_chunk) +static void grid_bound_insert_reduce(const void *__restrict UNUSED(userdata), + void *__restrict chunk_join, + void *__restrict chunk) { - PaintBakeData *bData = userdata; - VolumeGrid *grid = bData->grid; - - Bounds3D *grid_bound = userdata_chunk; + Bounds3D *join = chunk_join; + Bounds3D *grid_bound = chunk; - boundInsert(&grid->grid_bounds, grid_bound->min); - boundInsert(&grid->grid_bounds, grid_bound->max); + boundInsert(join, grid_bound->min); + boundInsert(join, grid_bound->max); } static void grid_cell_points_cb_ex(void *__restrict userdata, @@ -685,17 +685,20 @@ static void grid_cell_points_cb_ex(void *__restrict userdata, s_num[temp_t_index[i]]++; } -static void grid_cell_points_finalize(void *__restrict userdata, void *__restrict userdata_chunk) +static void grid_cell_points_reduce(const void *__restrict userdata, + void *__restrict chunk_join, + void *__restrict chunk) { - PaintBakeData *bData = userdata; - VolumeGrid *grid = bData->grid; + const PaintBakeData *bData = userdata; + const VolumeGrid *grid = bData->grid; const int grid_cells = grid->dim[0] * grid->dim[1] * grid->dim[2]; - int *s_num = userdata_chunk; + int *join_s_num = chunk_join; + int *s_num = chunk; /* calculate grid indexes */ for (int i = 0; i < grid_cells; i++) { - grid->s_num[i] += s_num[i]; + join_s_num[i] += s_num[i]; } } @@ -753,7 +756,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) settings.use_threading = (sData->total_points > 1000); settings.userdata_chunk = &grid->grid_bounds; settings.userdata_chunk_size = sizeof(grid->grid_bounds); - settings.func_finalize = grid_bound_insert_finalize; + settings.func_reduce = grid_bound_insert_reduce; BLI_task_parallel_range(0, sData->total_points, bData, grid_bound_insert_cb_ex, &settings); } /* get dimensions */ @@ -814,7 +817,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) settings.use_threading = (sData->total_points > 1000); settings.userdata_chunk = grid->s_num; settings.userdata_chunk_size = sizeof(*grid->s_num) * grid_cells; - settings.func_finalize = grid_cell_points_finalize; + settings.func_reduce = grid_cell_points_reduce; BLI_task_parallel_range(0, sData->total_points, bData, grid_cell_points_cb_ex, &settings); } @@ -4880,7 +4883,7 @@ static void dynamicPaint_prepareAdjacencyData(DynamicPaintSurface *surface, cons 0, sData->total_points, sData, dynamic_paint_prepare_adjacency_cb, &settings); /* calculate average values (single thread). - * Note: tried to put this in threaded callback (using _finalize feature), + * Note: tried to put this in threaded callback (using _reduce feature), * but gave ~30% slower result! */ bData->average_dist = 0.0; for (index = 0; index < sData->total_points; index++) { diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 8697cd03827..578a6a13bb7 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -334,6 +334,14 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *mds, manta_free(fluid_old); } +void BKE_fluid_cache_free_all(FluidDomainSettings *mds, Object *ob) +{ + int cache_map = (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE | + FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES | + FLUID_DOMAIN_OUTDATED_GUIDE); + BKE_fluid_cache_free(mds, ob, cache_map); +} + void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map) { char temp_dir[FILE_MAX]; @@ -1130,7 +1138,18 @@ static void obstacles_from_mesh(Object *coll_ob, } } +static void ensure_obstaclefields(FluidDomainSettings *mds) +{ + if (mds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE) { + manta_ensure_obstacle(mds->fluid, mds->mmd); + } + if (mds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE) { + manta_ensure_guiding(mds->fluid, mds->mmd); + } +} + static void update_obstacleflags(FluidDomainSettings *mds, + Object *domain, Object **coll_ob_array, int coll_ob_array_len) { @@ -1157,6 +1176,11 @@ static void update_obstacleflags(FluidDomainSettings *mds, if (!mes) { break; } + if (mes->flags & FLUID_EFFECTOR_NEEDS_UPDATE) { + mes->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE; + BKE_fluid_cache_free_all(mds, domain); + mds->cache_flag |= FLUID_DOMAIN_OUTDATED_DATA; + } if (mes->type == FLUID_EFFECTOR_TYPE_COLLISION) { active_fields |= FLUID_DOMAIN_ACTIVE_OBSTACLE; } @@ -1165,13 +1189,6 @@ static void update_obstacleflags(FluidDomainSettings *mds, } } } - /* Finally, initialize new data fields if any */ - if (active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE) { - manta_ensure_obstacle(mds->fluid, mds->mmd); - } - if (active_fields & FLUID_DOMAIN_ACTIVE_GUIDE) { - manta_ensure_guiding(mds->fluid, mds->mmd); - } mds->active_fields = active_fields; } @@ -1193,7 +1210,8 @@ static void update_obstacles(Depsgraph *depsgraph, depsgraph, ob, mds->effector_group, &numeffecobjs, eModifierType_Fluid); /* Update all effector related flags and ensure that corresponding grids get initialized. */ - update_obstacleflags(mds, effecobjs, numeffecobjs); + update_obstacleflags(mds, ob, effecobjs, numeffecobjs); + ensure_obstaclefields(mds); /* Initialize effector maps for each flow. */ bb_maps = MEM_callocN(sizeof(struct FluidObjectBB) * numeffecobjs, "fluid_effector_bb_maps"); @@ -2573,21 +2591,49 @@ BLI_INLINE void apply_inflow_fields(FluidFlowSettings *mfs, } } -static void update_flowsflags(FluidDomainSettings *mds, Object **flowobjs, int numflowobj) +static void ensure_flowsfields(FluidDomainSettings *mds) +{ + if (mds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL) { + manta_ensure_invelocity(mds->fluid, mds->mmd); + } + if (mds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW) { + manta_ensure_outflow(mds->fluid, mds->mmd); + } + if (mds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT) { + manta_smoke_ensure_heat(mds->fluid, mds->mmd); + } + if (mds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE) { + manta_smoke_ensure_fire(mds->fluid, mds->mmd); + } + if (mds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) { + /* initialize all smoke with "active_color" */ + manta_smoke_ensure_colors(mds->fluid, mds->mmd); + } + if (mds->type == FLUID_DOMAIN_TYPE_LIQUID && + (mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY || + mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM || + mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER)) { + manta_liquid_ensure_sndparts(mds->fluid, mds->mmd); + } +} + +static void update_flowsflags(FluidDomainSettings *mds, + Object *domain, + Object **flowobjs, + int numflowobj) { int active_fields = mds->active_fields; uint flow_index; /* First, remove all flags that we want to update. */ int prev_flags = (FLUID_DOMAIN_ACTIVE_INVEL | FLUID_DOMAIN_ACTIVE_OUTFLOW | - FLUID_DOMAIN_ACTIVE_HEAT | FLUID_DOMAIN_ACTIVE_FIRE | - FLUID_DOMAIN_ACTIVE_COLOR_SET | FLUID_DOMAIN_ACTIVE_COLORS); + FLUID_DOMAIN_ACTIVE_HEAT | FLUID_DOMAIN_ACTIVE_FIRE); active_fields &= ~prev_flags; /* Monitor active fields based on flow settings */ for (flow_index = 0; flow_index < numflowobj; flow_index++) { - Object *coll_ob = flowobjs[flow_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(coll_ob, + Object *flow_ob = flowobjs[flow_index]; + FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flow_ob, eModifierType_Fluid); /* Sanity check. */ @@ -2600,6 +2646,11 @@ static void update_flowsflags(FluidDomainSettings *mds, Object **flowobjs, int n if (!mfs) { break; } + if (mfs->flags & FLUID_FLOW_NEEDS_UPDATE) { + mfs->flags &= ~FLUID_FLOW_NEEDS_UPDATE; + BKE_fluid_cache_free_all(mds, domain); + mds->cache_flag |= FLUID_DOMAIN_OUTDATED_DATA; + } if (mfs->flags & FLUID_FLOW_INITVELOCITY) { active_fields |= FLUID_DOMAIN_ACTIVE_INVEL; } @@ -2648,29 +2699,6 @@ static void update_flowsflags(FluidDomainSettings *mds, Object **flowobjs, int n active_fields |= FLUID_DOMAIN_ACTIVE_COLORS; } } - /* Finally, initialize new data fields if any */ - if (active_fields & FLUID_DOMAIN_ACTIVE_INVEL) { - manta_ensure_invelocity(mds->fluid, mds->mmd); - } - if (active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW) { - manta_ensure_outflow(mds->fluid, mds->mmd); - } - if (active_fields & FLUID_DOMAIN_ACTIVE_HEAT) { - manta_smoke_ensure_heat(mds->fluid, mds->mmd); - } - if (active_fields & FLUID_DOMAIN_ACTIVE_FIRE) { - manta_smoke_ensure_fire(mds->fluid, mds->mmd); - } - if (active_fields & FLUID_DOMAIN_ACTIVE_COLORS) { - /* initialize all smoke with "active_color" */ - manta_smoke_ensure_colors(mds->fluid, mds->mmd); - } - if (mds->type == FLUID_DOMAIN_TYPE_LIQUID && - (mds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY || - mds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM || - mds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER)) { - manta_liquid_ensure_sndparts(mds->fluid, mds->mmd); - } mds->active_fields = active_fields; } @@ -2692,7 +2720,8 @@ static void update_flowsfluids(struct Depsgraph *depsgraph, depsgraph, ob, mds->fluid_group, &numflowobj, eModifierType_Fluid); /* Update all flow related flags and ensure that corresponding grids get initialized. */ - update_flowsflags(mds, flowobjs, numflowobj); + update_flowsflags(mds, ob, flowobjs, numflowobj); + ensure_flowsfields(mds); /* Initialize emission maps for each flow. */ bb_maps = MEM_callocN(sizeof(struct FluidObjectBB) * numflowobj, "fluid_flow_bb_maps"); @@ -3566,6 +3595,7 @@ static int manta_step( break; } + /* Only bake if the domain is bigger than one cell (important for adaptive domain). */ if (mds->total_cells > 1) { update_effectors(depsgraph, scene, ob, mds, dt); manta_bake_data(mds->fluid, mmd, frame); @@ -3585,7 +3615,7 @@ static int manta_step( } } - if (mds->type == FLUID_DOMAIN_TYPE_GAS) { + if (mds->type == FLUID_DOMAIN_TYPE_GAS && result) { manta_smoke_calc_transparency(mds, DEG_get_evaluated_view_layer(depsgraph)); } BLI_mutex_unlock(&object_update_lock); @@ -3684,8 +3714,35 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, return; } + bool bake_outdated = mds->cache_flag & + (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE | + FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES | + FLUID_DOMAIN_OUTDATED_GUIDE); + + /* Exit early if cache is outdated. */ + if (bake_outdated) { + return; + } + + /* Ensure cache directory is not relative. */ + const char *relbase = modifier_path_relbase_from_global(ob); + BLI_path_abs(mds->cache_directory, relbase); + + objs = BKE_collision_objects_create( + depsgraph, ob, mds->fluid_group, &numobj, eModifierType_Fluid); + update_flowsflags(mds, ob, objs, numobj); + if (objs) { + MEM_freeN(objs); + } + objs = BKE_collision_objects_create( + depsgraph, ob, mds->effector_group, &numobj, eModifierType_Fluid); + update_obstacleflags(mds, ob, objs, numobj); + if (objs) { + MEM_freeN(objs); + } + /* Reset fluid if no fluid present. */ - if (!mds->fluid) { + if (!mds->fluid || mds->cache_flag & FLUID_DOMAIN_OUTDATED_DATA) { BKE_fluid_modifier_reset_ex(mmd, false); /* Fluid domain init must not fail in order to continue modifier evaluation. */ @@ -3712,23 +3769,10 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, /* Get distance between cache start and current frame for total time. */ mds->time_total = abs(scene_framenr - mds->cache_frame_start) * mds->frame_length; - objs = BKE_collision_objects_create( - depsgraph, ob, mds->fluid_group, &numobj, eModifierType_Fluid); - update_flowsflags(mds, objs, numobj); - if (objs) { - MEM_freeN(objs); - } - - objs = BKE_collision_objects_create( - depsgraph, ob, mds->effector_group, &numobj, eModifierType_Fluid); - update_obstacleflags(mds, objs, numobj); - if (objs) { - MEM_freeN(objs); - } - - /* Ensure cache directory is not relative. */ - const char *relbase = modifier_path_relbase_from_global(ob); - BLI_path_abs(mds->cache_directory, relbase); + int next_frame = scene_framenr + 1; + int prev_frame = scene_framenr - 1; + /* Ensure positivity of previous frame. */ + CLAMP(prev_frame, mds->cache_frame_start, prev_frame); int data_frame = scene_framenr, noise_frame = scene_framenr; int mesh_frame = scene_framenr, particles_frame = scene_framenr, guide_frame = scene_framenr; @@ -3751,17 +3795,18 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, with_particles = drops || bubble || floater; bool has_data, has_noise, has_mesh, has_particles, has_guide; - has_data = has_noise = has_mesh = has_particles = has_guide = false; + has_data = manta_has_data(mds->fluid, mmd, scene_framenr); + has_noise = manta_has_noise(mds->fluid, mmd, scene_framenr); + has_mesh = manta_has_mesh(mds->fluid, mmd, scene_framenr); + has_particles = manta_has_particles(mds->fluid, mmd, scene_framenr); + has_guide = manta_has_guiding(mds->fluid, mmd, scene_framenr, guide_parent); - bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide, bake_outdated; + bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide; baking_data = mds->cache_flag & FLUID_DOMAIN_BAKING_DATA; baking_noise = mds->cache_flag & FLUID_DOMAIN_BAKING_NOISE; baking_mesh = mds->cache_flag & FLUID_DOMAIN_BAKING_MESH; baking_particles = mds->cache_flag & FLUID_DOMAIN_BAKING_PARTICLES; baking_guide = mds->cache_flag & FLUID_DOMAIN_BAKING_GUIDE; - bake_outdated = mds->cache_flag & (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE | - FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES | - FLUID_DOMAIN_OUTDATED_GUIDE); bool resume_data, resume_noise, resume_mesh, resume_particles, resume_guide; resume_data = (!is_startframe) && (mds->cache_frame_pause_data == scene_framenr); @@ -3775,35 +3820,27 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, bake_cache = baking_data || baking_noise || baking_mesh || baking_particles || baking_guide; bool next_data, next_noise, next_mesh, next_particles, next_guide; - next_data = manta_has_data(mds->fluid, mmd, scene_framenr + 1); - next_noise = manta_has_noise(mds->fluid, mmd, scene_framenr + 1); - next_mesh = manta_has_mesh(mds->fluid, mmd, scene_framenr + 1); - next_particles = manta_has_particles(mds->fluid, mmd, scene_framenr + 1); - next_guide = manta_has_guiding(mds->fluid, mmd, scene_framenr + 1, guide_parent); + next_data = manta_has_data(mds->fluid, mmd, next_frame); + next_noise = manta_has_noise(mds->fluid, mmd, next_frame); + next_mesh = manta_has_mesh(mds->fluid, mmd, next_frame); + next_particles = manta_has_particles(mds->fluid, mmd, next_frame); + next_guide = manta_has_guiding(mds->fluid, mmd, next_frame, guide_parent); bool prev_data, prev_noise, prev_mesh, prev_particles, prev_guide; - prev_data = manta_has_data(mds->fluid, mmd, scene_framenr - 1); - prev_noise = manta_has_noise(mds->fluid, mmd, scene_framenr - 1); - prev_mesh = manta_has_mesh(mds->fluid, mmd, scene_framenr - 1); - prev_particles = manta_has_particles(mds->fluid, mmd, scene_framenr - 1); - prev_guide = manta_has_guiding(mds->fluid, mmd, scene_framenr - 1, guide_parent); - - /* Unused for now, but needed for proper caching. */ - UNUSED_VARS(prev_guide); - UNUSED_VARS(next_noise); - UNUSED_VARS(next_mesh); - UNUSED_VARS(next_particles); - UNUSED_VARS(next_guide); + prev_data = manta_has_data(mds->fluid, mmd, prev_frame); + prev_noise = manta_has_noise(mds->fluid, mmd, prev_frame); + prev_mesh = manta_has_mesh(mds->fluid, mmd, prev_frame); + prev_particles = manta_has_particles(mds->fluid, mmd, prev_frame); + prev_guide = manta_has_guiding(mds->fluid, mmd, prev_frame, guide_parent); + + /* Unused for now. */ + UNUSED_VARS(prev_guide, next_mesh, next_guide); bool with_gdomain; with_gdomain = (mds->guide_source == FLUID_DOMAIN_GUIDE_SRC_DOMAIN); int o_res[3], o_min[3], o_max[3], o_shift[3]; int mode = mds->cache_type; - int prev_frame = scene_framenr - 1; - - /* Ensure positivity of previous frame. */ - CLAMP(prev_frame, 1, prev_frame); /* Cache mode specific settings. */ switch (mode) { @@ -3851,21 +3888,23 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, break; case FLUID_DOMAIN_CACHE_REPLAY: default: + baking_data = !has_data && (is_startframe || prev_data); + if (with_smoke && with_noise) { + baking_noise = !has_noise && (is_startframe || prev_noise); + } + if (with_liquid && with_mesh) { + baking_mesh = !has_mesh && (is_startframe || prev_mesh); + } + if (with_liquid && with_particles) { + baking_particles = !has_particles && (is_startframe || prev_particles); + } + /* Always trying to read the cache in replay mode. */ read_cache = true; bake_cache = false; break; } - /* Cache outdated? If so reset, don't read, and then just rebake. - * Note: Only do this in replay mode! */ - bool mode_replay = (mode == FLUID_DOMAIN_CACHE_REPLAY); - if (bake_outdated && mode_replay) { - read_cache = false; - bake_cache = true; - BKE_fluid_cache_free(mds, ob, mds->cache_flag); - } - /* Try to read from cache and keep track of read success. */ if (read_cache) { @@ -3877,7 +3916,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, /* Read particles cache. */ if (with_liquid && with_particles) { - if (!baking_data && !baking_particles && !mode_replay) { + if (!baking_data && !baking_particles && next_particles) { /* Update particle data from file is faster than via Python (manta_read_particles()). */ has_particles = manta_update_particle_structures(mds->fluid, mmd, particles_frame); } @@ -3901,8 +3940,8 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, manta_needs_realloc(mds->fluid, mmd)) { BKE_fluid_reallocate_fluid(mds, mds->res, 1); } - if (!baking_data && !baking_noise && !mode_replay) { - has_data = manta_update_noise_structures(mds->fluid, mmd, noise_frame); + if (!baking_data && !baking_noise && next_noise) { + has_noise = manta_update_noise_structures(mds->fluid, mmd, noise_frame); } else { has_noise = manta_read_noise(mds->fluid, mmd, noise_frame); @@ -3921,8 +3960,9 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, mds, o_res, mds->res, o_min, mds->res_min, o_max, o_shift, mds->shift); } } - if (!baking_data && !baking_noise && !mode_replay) { - /* TODO (sebbas): Confirm if this read call is really needed or not. */ + if (!baking_data && !baking_noise && next_data && next_noise) { + /* TODO (sebbas): Confirm if this read call is really needed or not. + * Currently only important to load the shadow grid. */ has_data = manta_update_smoke_structures(mds->fluid, mmd, data_frame); } else { @@ -3946,7 +3986,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, } } if (with_liquid) { - if (!baking_data && !baking_particles && !baking_mesh && !mode_replay) { + if (!baking_data && !baking_particles && !baking_mesh && next_data) { has_data = manta_update_liquid_structures(mds->fluid, mmd, data_frame); } else { @@ -3960,6 +4000,9 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, switch (mode) { case FLUID_DOMAIN_CACHE_FINAL: case FLUID_DOMAIN_CACHE_MODULAR: + if (!baking_data && !baking_noise && !baking_mesh && !baking_particles && !baking_guide) { + bake_cache = false; + } break; case FLUID_DOMAIN_CACHE_REPLAY: default: diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 80f29a55b28..9d7382010fe 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -663,7 +663,7 @@ static void id_swap(Main *bmain, ID *id_a, ID *id_b, const bool do_full_id) * Does a mere memory swap over the whole IDs data (including type-specific memory). * \note Most internal ID data itself is not swapped (only IDProperties are). * - * \param bmain May be NULL, in which case there will be no remapping of internal pointers to + * \param bmain: May be NULL, in which case there will be no remapping of internal pointers to * itself. */ void BKE_lib_id_swap(Main *bmain, ID *id_a, ID *id_b) @@ -675,7 +675,7 @@ void BKE_lib_id_swap(Main *bmain, ID *id_a, ID *id_b) * Does a mere memory swap over the whole IDs data (including type-specific memory). * \note All internal ID data itself is also swapped. * - * \param bmain May be NULL, in which case there will be no remapping of internal pointers to + * \param bmain: May be NULL, in which case there will be no remapping of internal pointers to * itself. */ void BKE_lib_id_swap_full(Main *bmain, ID *id_a, ID *id_b) @@ -1248,7 +1248,7 @@ ID *BKE_libblock_find_name(struct Main *bmain, const short type, const char *nam * * \note All other IDs beside given one are assumed already properly sorted in the list. * - * \param id_sorting_hint Ignored if NULL. Otherwise, used to check if we can insert \a id + * \param id_sorting_hint: Ignored if NULL. Otherwise, used to check if we can insert \a id * immediately before or after that pointer. It must always be into given \a lb list. */ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index f68b1a4d314..2f281a29211 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2677,7 +2677,7 @@ void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *o { /* Execute drivers and animation. */ const bool flush_to_original = DEG_is_active(depsgraph); - BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL, flush_to_original); + BKE_animsys_evaluate_animdata(&ob->id, ob->adt, ctime, ADT_RECALC_ALL, flush_to_original); object_where_is_calc_ex(depsgraph, scene, ob, ctime, NULL, NULL); } @@ -4567,8 +4567,7 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, /* TODO(sergey): What about animation? */ ob->id.recalc |= ID_RECALC_ALL; if (update_mesh) { - BKE_animsys_evaluate_animdata( - scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata(&ob->id, ob->adt, frame, ADT_RECALC_ANIM, flush_to_original); /* ignore cache clear during subframe updates * to not mess up cache validity */ object_cacheIgnoreClear(ob, 1); @@ -4582,14 +4581,12 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, /* for curve following objects, parented curve has to be updated too */ if (ob->type == OB_CURVE) { Curve *cu = ob->data; - BKE_animsys_evaluate_animdata( - scene, &cu->id, cu->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata(&cu->id, cu->adt, frame, ADT_RECALC_ANIM, flush_to_original); } /* and armatures... */ if (ob->type == OB_ARMATURE) { bArmature *arm = ob->data; - BKE_animsys_evaluate_animdata( - scene, &arm->id, arm->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata(&arm->id, arm->adt, frame, ADT_RECALC_ANIM, flush_to_original); BKE_pose_where_is(depsgraph, scene, ob); } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index cc49f500a5f..14b1ef7b87f 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3692,10 +3692,11 @@ typedef struct DynamicStepSolverTaskData { SpinLock spin; } DynamicStepSolverTaskData; -static void dynamics_step_finalize_sphdata(void *__restrict UNUSED(userdata), - void *__restrict tls_userdata_chunk) +static void dynamics_step_sphdata_reduce(const void *__restrict UNUSED(userdata), + void *__restrict UNUSED(join_v), + void *__restrict chunk_v) { - SPHData *sphdata = tls_userdata_chunk; + SPHData *sphdata = chunk_v; psys_sph_flush_springs(sphdata); } @@ -3986,7 +3987,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) settings.use_threading = (psys->totpart > 100); settings.userdata_chunk = &sphdata; settings.userdata_chunk_size = sizeof(sphdata); - settings.func_finalize = dynamics_step_finalize_sphdata; + settings.func_reduce = dynamics_step_sphdata_reduce; BLI_task_parallel_range( 0, psys->totpart, &task_data, dynamics_step_sph_ddr_task_cb_ex, &settings); @@ -4018,7 +4019,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) settings.use_threading = (psys->totpart > 100); settings.userdata_chunk = &sphdata; settings.userdata_chunk_size = sizeof(sphdata); - settings.func_finalize = dynamics_step_finalize_sphdata; + settings.func_reduce = dynamics_step_sphdata_reduce; BLI_task_parallel_range(0, psys->totpart, &task_data, @@ -4033,7 +4034,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) settings.use_threading = (psys->totpart > 100); settings.userdata_chunk = &sphdata; settings.userdata_chunk_size = sizeof(sphdata); - settings.func_finalize = dynamics_step_finalize_sphdata; + settings.func_reduce = dynamics_step_sphdata_reduce; BLI_task_parallel_range(0, psys->totpart, &task_data, @@ -4189,7 +4190,7 @@ static void particles_fluid_step(ParticleSimulationData *sim, ParticleSettings *part = psys->part; ParticleData *pa = NULL; - int p, totpart, tottypepart = 0; + int p, totpart = 0, tottypepart = 0; int flagActivePart, activeParts = 0; float posX, posY, posZ, velX, velY, velZ; float resX, resY, resZ; @@ -4847,7 +4848,7 @@ void particle_system_update(struct Depsgraph *depsgraph, hcfra = 100.0f * (float)i / (float)psys->part->hair_step; if ((part->flag & PART_HAIR_REGROW) == 0) { BKE_animsys_evaluate_animdata( - scene, &part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false); + &part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false); } system_step(&sim, hcfra, use_render_params); psys->cfra = hcfra; diff --git a/source/blender/blenkernel/intern/pointcloud.c b/source/blender/blenkernel/intern/pointcloud.c index 31b8de53291..717d84c1c1e 100644 --- a/source/blender/blenkernel/intern/pointcloud.c +++ b/source/blender/blenkernel/intern/pointcloud.c @@ -184,7 +184,7 @@ void BKE_pointcloud_update_customdata_pointers(PointCloud *pointcloud) PointCloud *BKE_pointcloud_new_for_eval(const PointCloud *pointcloud_src, int totpoint) { - PointCloud *pointcloud_dst = BKE_id_new_nomain(ID_HA, NULL); + PointCloud *pointcloud_dst = BKE_id_new_nomain(ID_PT, NULL); STRNCPY(pointcloud_dst->id.name, pointcloud_src->id.name); pointcloud_dst->mat = MEM_dupallocN(pointcloud_src->mat); diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c index 1bd02212908..4f57776f2ad 100644 --- a/source/blender/blenkernel/intern/seqprefetch.c +++ b/source/blender/blenkernel/intern/seqprefetch.c @@ -332,8 +332,7 @@ static void *seq_prefetch_frames(void *job) pfjob->scene_eval->ed->prefetch_job = NULL; AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id); - BKE_animsys_evaluate_animdata(pfjob->context_cpy.scene, - &pfjob->context_cpy.scene->id, + BKE_animsys_evaluate_animdata(&pfjob->context_cpy.scene->id, adt, pfjob->cfra + pfjob->num_frames_prefetched, ADT_RECALC_ALL, diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 93e5a3bbd74..c0ab5cf5816 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3330,8 +3330,7 @@ static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr /* anim-data */ adt = BKE_animdata_from_id(&mask->id); - BKE_animsys_evaluate_animdata( - context->scene, &mask_temp->id, adt, mask->sfra + nr, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata(&mask_temp->id, adt, mask->sfra + nr, ADT_RECALC_ANIM, false); maskbuf = MEM_mallocN(sizeof(float) * context->rectx * context->recty, __func__); @@ -3660,8 +3659,7 @@ static ImBuf *do_render_strip_seqbase(const SeqRenderData *context, if (seqbase && !BLI_listbase_is_empty(seqbase)) { if (seq->flag & SEQ_SCENE_STRIPS && seq->scene) { - BKE_animsys_evaluate_all_animation( - context->bmain, context->depsgraph, seq->scene, nr + offset); + BKE_animsys_evaluate_all_animation(context->bmain, context->depsgraph, nr + offset); } ibuf = seq_render_strip_stack(context, diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c index 521aeb60e66..d99c41eaa3e 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.c +++ b/source/blender/blenkernel/intern/subdiv_ccg.c @@ -770,8 +770,8 @@ static void subdiv_ccg_recalc_inner_normal_task(void *__restrict userdata_v, subdiv_ccg_average_inner_face_normals(data->subdiv_ccg, data->key, tls, grid_index); } -static void subdiv_ccg_recalc_inner_normal_finalize(void *__restrict UNUSED(userdata), - void *__restrict tls_v) +static void subdiv_ccg_recalc_inner_normal_free(const void *__restrict UNUSED(userdata), + void *__restrict tls_v) { RecalcInnerNormalsTLSData *tls = tls_v; MEM_SAFE_FREE(tls->face_normals); @@ -791,7 +791,7 @@ static void subdiv_ccg_recalc_inner_grid_normals(SubdivCCG *subdiv_ccg) BLI_parallel_range_settings_defaults(¶llel_range_settings); parallel_range_settings.userdata_chunk = &tls_data; parallel_range_settings.userdata_chunk_size = sizeof(tls_data); - parallel_range_settings.func_finalize = subdiv_ccg_recalc_inner_normal_finalize; + parallel_range_settings.func_free = subdiv_ccg_recalc_inner_normal_free; BLI_task_parallel_range(0, subdiv_ccg->num_grids, &data, @@ -834,8 +834,8 @@ static void subdiv_ccg_recalc_modified_inner_normal_task(void *__restrict userda subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, face); } -static void subdiv_ccg_recalc_modified_inner_normal_finalize(void *__restrict UNUSED(userdata), - void *__restrict tls_v) +static void subdiv_ccg_recalc_modified_inner_normal_free(const void *__restrict UNUSED(userdata), + void *__restrict tls_v) { RecalcInnerNormalsTLSData *tls = tls_v; MEM_SAFE_FREE(tls->face_normals); @@ -857,7 +857,7 @@ static void subdiv_ccg_recalc_modified_inner_grid_normals(SubdivCCG *subdiv_ccg, BLI_parallel_range_settings_defaults(¶llel_range_settings); parallel_range_settings.userdata_chunk = &tls_data; parallel_range_settings.userdata_chunk_size = sizeof(tls_data); - parallel_range_settings.func_finalize = subdiv_ccg_recalc_modified_inner_normal_finalize; + parallel_range_settings.func_free = subdiv_ccg_recalc_modified_inner_normal_free; BLI_task_parallel_range(0, num_effected_faces, &data, @@ -1077,8 +1077,8 @@ static void subdiv_ccg_average_grids_boundaries_task(void *__restrict userdata_v subdiv_ccg_average_grids_boundary(subdiv_ccg, key, adjacent_edge, tls); } -static void subdiv_ccg_average_grids_boundaries_finalize(void *__restrict UNUSED(userdata), - void *__restrict tls_v) +static void subdiv_ccg_average_grids_boundaries_free(const void *__restrict UNUSED(userdata), + void *__restrict tls_v) { AverageGridsBoundariesTLSData *tls = tls_v; MEM_SAFE_FREE(tls->accumulators); @@ -1136,7 +1136,7 @@ static void subdiv_ccg_average_all_boundaries(SubdivCCG *subdiv_ccg, CCGKey *key AverageGridsBoundariesTLSData tls_data = {NULL}; parallel_range_settings.userdata_chunk = &tls_data; parallel_range_settings.userdata_chunk_size = sizeof(tls_data); - parallel_range_settings.func_finalize = subdiv_ccg_average_grids_boundaries_finalize; + parallel_range_settings.func_free = subdiv_ccg_average_grids_boundaries_free; BLI_task_parallel_range(0, subdiv_ccg->num_adjacent_edges, &boundaries_data, diff --git a/source/blender/blenkernel/intern/subdiv_foreach.c b/source/blender/blenkernel/intern/subdiv_foreach.c index b31fb2c9312..0884f40952f 100644 --- a/source/blender/blenkernel/intern/subdiv_foreach.c +++ b/source/blender/blenkernel/intern/subdiv_foreach.c @@ -1838,9 +1838,9 @@ static void subdiv_foreach_boundary_edges_task(void *__restrict userdata, subdiv_foreach_boundary_edges(ctx, tls->userdata_chunk, edge_index); } -static void subdiv_foreach_finalize(void *__restrict userdata, void *__restrict userdata_chunk) +static void subdiv_foreach_free(const void *__restrict userdata, void *__restrict userdata_chunk) { - SubdivForeachTaskContext *ctx = userdata; + const SubdivForeachTaskContext *ctx = userdata; ctx->foreach_context->user_data_tls_free(userdata_chunk); } @@ -1873,7 +1873,7 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv, parallel_range_settings.userdata_chunk_size = context->user_data_tls_size; parallel_range_settings.min_iter_per_thread = 1; if (context->user_data_tls_free != NULL) { - parallel_range_settings.func_finalize = subdiv_foreach_finalize; + parallel_range_settings.func_free = subdiv_foreach_free; } /* TODO(sergey): Possible optimization is to have a single pool and push all diff --git a/source/blender/blenlib/BLI_hash.h b/source/blender/blenlib/BLI_hash.h index d09291b64be..3871ddf956a 100644 --- a/source/blender/blenlib/BLI_hash.h +++ b/source/blender/blenlib/BLI_hash.h @@ -81,7 +81,7 @@ BLI_INLINE void BLI_hash_pointer_to_color(const void *ptr, int *r, int *g, int * { size_t val = (size_t)ptr; const size_t hash_a = BLI_hash_int(val & 0x0000ffff); - const size_t hash_b = BLI_hash_int((uint)((val & 0xffff0000) >> 32)); + const size_t hash_b = BLI_hash_int((uint)((val & 0xffff0000) >> 16)); const size_t hash = hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2)); *r = (hash & 0xff0000) >> 16; *g = (hash & 0x00ff00) >> 8; diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h index 898e4be5f92..78370e98202 100644 --- a/source/blender/blenlib/BLI_task.h +++ b/source/blender/blenlib/BLI_task.h @@ -146,12 +146,14 @@ typedef struct TaskParallelTLS { void *userdata_chunk; } TaskParallelTLS; -typedef void (*TaskParallelFinalizeFunc)(void *__restrict userdata, - void *__restrict userdata_chunk); - typedef void (*TaskParallelRangeFunc)(void *__restrict userdata, const int iter, const TaskParallelTLS *__restrict tls); +typedef void (*TaskParallelReduceFunc)(const void *__restrict userdata, + void *__restrict chunk_join, + void *__restrict chunk); + +typedef void (*TaskParallelFreeFunc)(const void *__restrict userdata, void *__restrict chunk); typedef struct TaskParallelSettings { /* Whether caller allows to do threading of the particular range. @@ -171,7 +173,13 @@ typedef struct TaskParallelSettings { /* Function called from calling thread once whole range have been * processed. */ - TaskParallelFinalizeFunc func_finalize; + /* Function called to join user data chunk into another, to reduce + * the result to the original userdata_chunk memory. + * The reduce functions should have no side effects, so that they + * can be run on any thread. */ + TaskParallelReduceFunc func_reduce; + /* Function called to free data created by TaskParallelRangeFunc. */ + TaskParallelFreeFunc func_free; /* Minimum allowed number of range iterators to be handled by a single * thread. This allows to achieve following: * - Reduce amount of threading overhead. diff --git a/source/blender/blenlib/intern/task_iterator.c b/source/blender/blenlib/intern/task_iterator.c index 4ac012fa578..0d1c96612e3 100644 --- a/source/blender/blenlib/intern/task_iterator.c +++ b/source/blender/blenlib/intern/task_iterator.c @@ -78,8 +78,13 @@ typedef struct TaskParallelRangeState { /* Number of 'tls' copies in the array, i.e. number of worker threads. */ size_t num_elements_in_tls_storage; - /* Function called from calling thread once whole range have been processed. */ - TaskParallelFinalizeFunc func_finalize; + /* Function called to join user data chunk into another, to reduce + * the result to the original userdata_chunk memory. + * The reduce functions should have no side effects, so that they + * can be run on any thread. */ + TaskParallelReduceFunc func_reduce; + /* Function called to free data created by TaskParallelRangeFunc. */ + TaskParallelFreeFunc func_free; /* Current value of the iterator, shared between all threads (atomically updated). */ int iter_value; @@ -256,23 +261,18 @@ static void parallel_range_single_thread(TaskParallelRangePool *range_pool) void *initial_tls_memory = state->initial_tls_memory; const size_t tls_data_size = state->tls_data_size; - void *flatten_tls_storage = NULL; const bool use_tls_data = (tls_data_size != 0) && (initial_tls_memory != NULL); - if (use_tls_data) { - flatten_tls_storage = MALLOCA(tls_data_size); - memcpy(flatten_tls_storage, initial_tls_memory, tls_data_size); - } TaskParallelTLS tls = { .thread_id = 0, - .userdata_chunk = flatten_tls_storage, + .userdata_chunk = initial_tls_memory, }; for (int i = start; i < stop; i++) { func(userdata, i, &tls); } - if (state->func_finalize != NULL) { - state->func_finalize(userdata, flatten_tls_storage); + if (use_tls_data && state->func_free != NULL) { + /* `func_free` should only free data that was created during execution of `func`. */ + state->func_free(userdata, initial_tls_memory); } - MALLOCA_FREE(flatten_tls_storage, tls_data_size); } } @@ -303,7 +303,7 @@ void BLI_task_parallel_range(const int start, .iter_value = start, .initial_tls_memory = settings->userdata_chunk, .tls_data_size = settings->userdata_chunk_size, - .func_finalize = settings->func_finalize, + .func_free = settings->func_free, }; TaskParallelRangePool range_pool = { .pool = NULL, .parallel_range_states = &state, .current_state = NULL, .settings = settings}; @@ -367,11 +367,15 @@ void BLI_task_parallel_range(const int start, BLI_task_pool_work_and_wait(task_pool); BLI_task_pool_free(task_pool); - if (use_tls_data) { - if (settings->func_finalize != NULL) { - for (i = 0; i < num_tasks; i++) { - void *userdata_chunk_local = (char *)flatten_tls_storage + (tls_data_size * (size_t)i); - settings->func_finalize(userdata, userdata_chunk_local); + if (use_tls_data && (settings->func_free != NULL || settings->func_reduce != NULL)) { + for (i = 0; i < num_tasks; i++) { + void *userdata_chunk_local = (char *)flatten_tls_storage + (tls_data_size * (size_t)i); + if (settings->func_reduce) { + settings->func_reduce(userdata, tls_data, userdata_chunk_local); + } + if (settings->func_free) { + /* `func_free` should only free data that was created during execution of `func`. */ + settings->func_free(userdata, userdata_chunk_local); } } MALLOCA_FREE(flatten_tls_storage, tls_data_size * (size_t)num_tasks); @@ -382,16 +386,17 @@ void BLI_task_parallel_range(const int start, * Initialize a task pool to parallelize several for loops at the same time. * * See public API doc of ParallelRangeSettings for description of all settings. - * Note that loop-specific settings (like 'tls' data or finalize function) must be left NULL here. - * Only settings controlling how iteration is parallelized must be defined, as those will affect - * all loops added to that pool. + * Note that loop-specific settings (like 'tls' data or reduce/free functions) must be left NULL + * here. Only settings controlling how iteration is parallelized must be defined, as those will + * affect all loops added to that pool. */ TaskParallelRangePool *BLI_task_parallel_range_pool_init(const TaskParallelSettings *settings) { TaskParallelRangePool *range_pool = MEM_callocN(sizeof(*range_pool), __func__); BLI_assert(settings->userdata_chunk == NULL); - BLI_assert(settings->func_finalize == NULL); + BLI_assert(settings->func_reduce == NULL); + BLI_assert(settings->func_free == NULL); range_pool->settings = MEM_mallocN(sizeof(*range_pool->settings), __func__); *range_pool->settings = *settings; @@ -430,7 +435,8 @@ void BLI_task_parallel_range_pool_push(TaskParallelRangePool *range_pool, state->iter_value = start; state->initial_tls_memory = settings->userdata_chunk; state->tls_data_size = settings->userdata_chunk_size; - state->func_finalize = settings->func_finalize; + state->func_reduce = settings->func_reduce; + state->func_free = settings->func_free; state->next = range_pool->parallel_range_states; range_pool->parallel_range_states = state; @@ -445,7 +451,13 @@ static void parallel_range_func_finalize(TaskPool *__restrict pool, for (int i = 0; i < range_pool->num_tasks; i++) { void *tls_data = (char *)state->flatten_tls_storage + (state->tls_data_size * (size_t)i); - state->func_finalize(state->userdata_shared, tls_data); + if (state->func_reduce != NULL) { + state->func_reduce(state->userdata_shared, state->initial_tls_memory, tls_data); + } + if (state->func_free != NULL) { + /* `func_free` should only free data that was created during execution of `func`. */ + state->func_free(state->userdata_shared, tls_data); + } } } @@ -531,7 +543,7 @@ void BLI_task_parallel_range_pool_work_and_wait(TaskParallelRangePool *range_poo continue; } - if (state->func_finalize != NULL) { + if (state->func_reduce != NULL || state->func_free != NULL) { BLI_task_pool_push_from_thread( task_pool, parallel_range_func_finalize, state, false, NULL, thread_id); } @@ -677,11 +689,9 @@ static void task_parallel_iterator_no_threads(const TaskParallelSettings *settin parallel_iterator_func_do(state, userdata_chunk, 0); - if (use_userdata_chunk) { - if (settings->func_finalize != NULL) { - settings->func_finalize(state->userdata, userdata_chunk_local); - } - MALLOCA_FREE(userdata_chunk_local, userdata_chunk_size); + if (use_userdata_chunk && settings->func_free != NULL) { + /* `func_free` should only free data that was created during execution of `func`. */ + settings->func_free(state->userdata, userdata_chunk_local); } } @@ -740,11 +750,14 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings, BLI_task_pool_work_and_wait(task_pool); BLI_task_pool_free(task_pool); - if (use_userdata_chunk) { - if (settings->func_finalize != NULL) { - for (size_t i = 0; i < num_tasks; i++) { - userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); - settings->func_finalize(state->userdata, userdata_chunk_local); + if (use_userdata_chunk && (settings->func_reduce != NULL || settings->func_free != NULL)) { + for (size_t i = 0; i < num_tasks; i++) { + userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); + if (settings->func_reduce != NULL) { + settings->func_reduce(state->userdata, userdata_chunk, userdata_chunk_local); + } + if (settings->func_free != NULL) { + settings->func_free(state->userdata, userdata_chunk_local); } } MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * num_tasks); diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index 450d3fc2371..1555b9231ed 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -53,6 +53,7 @@ set(SRC intern/versioning_260.c intern/versioning_270.c intern/versioning_280.c + intern/versioning_290.c intern/versioning_cycles.c intern/versioning_defaults.c intern/versioning_dna.c diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 232cf3d73df..41f309f6e5e 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9916,6 +9916,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) blo_do_versions_260(fd, lib, main); blo_do_versions_270(fd, lib, main); blo_do_versions_280(fd, lib, main); + blo_do_versions_290(fd, lib, main); blo_do_versions_cycles(fd, lib, main); /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index 80f8bfc3f07..55abbe703de 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -199,6 +199,7 @@ void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main * void blo_do_versions_260(struct FileData *fd, struct Library *lib, struct Main *bmain); void blo_do_versions_270(struct FileData *fd, struct Library *lib, struct Main *bmain); void blo_do_versions_280(struct FileData *fd, struct Library *lib, struct Main *bmain); +void blo_do_versions_290(struct FileData *fd, struct Library *lib, struct Main *bmain); void blo_do_versions_cycles(struct FileData *fd, struct Library *lib, struct Main *bmain); void do_versions_after_linking_250(struct Main *bmain); diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c new file mode 100644 index 00000000000..0ce3cf405cd --- /dev/null +++ b/source/blender/blenloader/intern/versioning_290.c @@ -0,0 +1,66 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup blenloader + */ +/* allow readfile to use deprecated functionality */ +#define DNA_DEPRECATED_ALLOW + +#include "BLI_listbase.h" +#include "BLI_utildefines.h" + +#include "DNA_genfile.h" +#include "DNA_screen_types.h" + +#include "BKE_collection.h" +#include "BKE_main.h" + +#include "BLO_readfile.h" +#include "readfile.h" + +/* Make preferences read-only, use versioning_userdef.c. */ +#define U (*((const UserDef *)&U)) + +void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) +{ + UNUSED_VARS(fd); + /** + * Versioning code until next subversion bump goes here. + * + * \note Be sure to check when bumping the version: + * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend + * - "versioning_userdef.c", #do_versions_theme + * + * \note Keep this message at the bottom of the function. + */ + { + /* Keep this block, even when empty. */ + + if (!DNA_struct_elem_find(fd->filesdna, "SpaceImage", "float", "uv_opacity")) { + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + if (sl->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)sl; + sima->uv_opacity = 1.0f; + } + } + } + } + } + } +} diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 4fa7bf64834..45666a21a2c 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1046,6 +1046,7 @@ static BMOpDefine bmo_extrude_face_region_def = { {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */ {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ {"use_normal_from_adjacent", BMO_OP_SLOT_BOOL}, /* Use winding from surrounding faces instead of this region. */ + {"use_dissolve_ortho_edges", BMO_OP_SLOT_BOOL}, /* Dissolve edges whose faces form a flat surface. */ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ {{'\0'}}, }, diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 7a7f4a14db3..3c63f4a60d6 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -39,6 +39,7 @@ enum { EXT_INPUT = 1, EXT_KEEP = 2, EXT_DEL = 4, + EXT_TAG = 8, }; #define VERT_MARK 1 @@ -335,6 +336,8 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip"); const bool use_normal_from_adjacent = BMO_slot_bool_get(op->slots_in, "use_normal_from_adjacent"); + const bool use_dissolve_ortho_edges = BMO_slot_bool_get(op->slots_in, + "use_dissolve_ortho_edges"); /* initialize our sub-operators */ BMO_op_initf(bm, @@ -442,6 +445,24 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } } + BMVert **dissolve_verts = NULL; + int dissolve_verts_len = 0; + float average_normal[3]; + if (use_dissolve_ortho_edges) { + /* Calc average normal. */ + zero_v3(average_normal); + BMO_ITER (f, &siter, dupeop.slots_out, "geom.out", BM_FACE) { + add_v3_v3(average_normal, f->no); + } + if (normalize_v3(average_normal) == 0.0f) { + average_normal[2] = 1.0f; + } + + /* Allocate array to store possible vertices that will be dissolved. */ + int boundary_verts_len = BMO_slot_map_count(dupeop.slots_out, "boundary_map.out"); + dissolve_verts = MEM_mallocN((size_t)boundary_verts_len * sizeof(*dissolve_verts), __func__); + } + BMO_slot_copy(&dupeop, slots_out, "geom.out", op, slots_out, "geom.out"); slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude"); @@ -483,6 +504,16 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) continue; } + BMFace *join_face = NULL; + if (use_dissolve_ortho_edges) { + if (BM_edge_is_boundary(e)) { + join_face = e->l->f; + if (fabs(dot_v3v3(average_normal, join_face->no)) > 0.0001f) { + join_face = NULL; + } + } + } + bool edge_normal_flip; if (use_normal_from_adjacent == false) { /* Orient loop to give same normal as a loop of 'e_new' @@ -541,7 +572,22 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true); #endif - bm_extrude_copy_face_loop_attributes(bm, f); + if (join_face) { + BMVert *v1 = e->v1; + BMVert *v2 = e->v2; + if (!BMO_elem_flag_test(bm, v1, EXT_TAG)) { + BMO_elem_flag_enable(bm, v1, EXT_TAG); + dissolve_verts[dissolve_verts_len++] = v1; + } + if (!BMO_elem_flag_test(bm, v2, EXT_TAG)) { + BMO_elem_flag_enable(bm, v2, EXT_TAG); + dissolve_verts[dissolve_verts_len++] = v2; + } + bmesh_kernel_join_face_kill_edge(bm, join_face, f, e); + } + else { + bm_extrude_copy_face_loop_attributes(bm, f); + } } /* link isolated vert */ @@ -559,6 +605,23 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BM_edge_create(bm, v, v2, NULL, BM_CREATE_NO_DOUBLE); } + if (dissolve_verts) { + BMVert **v_iter = &dissolve_verts[0]; + for (int i = dissolve_verts_len; i--; v_iter++) { + v = *v_iter; + e = v->e; + BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v); + if ((e_other == e) || (BM_DISK_EDGE_NEXT(e_other, v) == e)) { + /* Lose edge or BMVert is edge pair. */ + BM_edge_collapse(bm, e, v, true, false); + } + else { + BLI_assert(!BM_vert_is_edge_pair(v)); + } + } + MEM_freeN(dissolve_verts); + } + /* cleanup */ if (delorig) { BMO_op_finish(bm, &delop); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index bc127243836..d1ddceb00b0 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -997,10 +997,10 @@ static bool point_between_edges(float co[3], BMVert *v, BMFace *f, EdgeHalf *e1, * record the change in offset_l (or offset_r); later we can tell that a change has happened * because the offset will differ from its original value in offset_l_spec (or offset_r_spec). * - * \param edges_between If this is true, there are edges between e1 and e2 in CCW order so they + * \param edges_between: If this is true, there are edges between e1 and e2 in CCW order so they * don't share a common face. We want the meeting point to be on an existing face so it * should be dropped onto one of the intermediate faces, if possible. - * \param e_in_plane If we need to drop from the calculated offset lines to one of the faces, + * \param e_in_plane: If we need to drop from the calculated offset lines to one of the faces, * we don't want to drop onto the 'in plane' face, so if this is not null skip this edge's faces. */ static void offset_meet(EdgeHalf *e1, @@ -2601,13 +2601,13 @@ static void adjust_miter_inner_coords(BevelParams *bp, BevVert *bv, EdgeHalf *em * to be a subsequent pass to make the widths as consistent as possible. * Doesn't make the actual BMVerts. * - * For a width consistency pass, we just recalculate the coordinates of the BoundVerts. If the + * For a width consistency pass, we just recalculate the coordinates of the #BoundVerts. If the * other ends have been (re)built already, then we copy the offsets from there to match, else we * use the ideal (user-specified) widths. * - * \param construct The first time through, construct will be true and we are making the BoundVerts - * and setting up the BoundVert and EdgeHalf pointers appropriately. Also, if construct, decide on - * the mesh pattern that will be used inside the boundary. + * \param construct: The first time through, construct will be true and we are making the + * #BoundVerts and setting up the #BoundVert and #EdgeHalf pointers appropriately. + * Also, if construct, decide on the mesh pattern that will be used inside the boundary. */ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 0adea027ecc..01cc95813ca 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -506,8 +506,7 @@ void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collecti } else if (from_layer_collection == nullptr && !id_node->is_collection_fully_expanded) { /* Initially collection was built from layer now, and was requested - * to not recurs into object. But nw it's asked to recurs into all - * objects. */ + * to not recurs into object. But now it's asked to recurs into all objects. */ } else { return; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc index d05385a7d7c..7fe7695f195 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc @@ -69,7 +69,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *object, RootPChanMap *root_map) { if ((con->flag & CONSTRAINT_DISABLE) != 0) { - /* Do not add disabled IK constraints to the relations. If these needs to be temporarly + /* Do not add disabled IK constraints to the relations. If these needs to be temporarily * enabled, they will be added as temporary constraints during transform. */ return; } diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index 13927cd5124..a6e6b30a6b1 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -73,8 +73,7 @@ static void eevee_motion_blur_camera_get_matrix_at_time(Scene *scene, /* Past matrix */ /* FIXME : This is a temporal solution that does not take care of parent animations */ /* Recalc Anim manually */ - BKE_animsys_evaluate_animdata( - scene, &camdata_cpy.id, camdata_cpy.adt, time, ADT_RECALC_ALL, false); + BKE_animsys_evaluate_animdata(&camdata_cpy.id, camdata_cpy.adt, time, ADT_RECALC_ALL, false); BKE_object_where_is_calc_time(draw_ctx->depsgraph, scene, &cam_cpy, time); /* Compute winmat */ diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 31c89ca9f43..1d2bf152777 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -1240,7 +1240,7 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op) workob.adt = ob->adt; workob.pose = dummyPose; - BKE_animsys_evaluate_animdata(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata(&workob.id, workob.adt, cframe, ADT_RECALC_ANIM, false); /* copy back values, but on selected bones only */ for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) { diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 7a1f64b61d4..dfdd809dbd1 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -37,6 +37,7 @@ struct Tex; struct View2D; struct bContext; struct bNode; +struct bNodeSocket; struct bNodeSocketType; struct bNodeTree; struct bNodeTree; @@ -79,6 +80,10 @@ void ED_node_draw_snap( struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned int pos); /* node_draw.c */ +void ED_node_socket_draw(struct bNodeSocket *sock, + const struct rcti *rect, + const float color[4], + float scale); void ED_node_tree_update(const struct bContext *C); void ED_node_tag_update_id(struct ID *id); void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node); diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 2a5803cbc4d..eb1533dc639 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -157,6 +157,8 @@ int BIF_countTransformOrientation(const struct bContext *C); #define P_GPENCIL_EDIT (1 << 13) #define P_CURSOR_EDIT (1 << 14) #define P_CLNOR_INVALIDATE (1 << 15) +/* For properties performed when confirming the transformation. */ +#define P_POST_TRANSFORM (1 << 16) void Transform_Properties(struct wmOperatorType *ot, int flags); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 774cf8c509f..cd2e2794192 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -250,6 +250,8 @@ enum { UI_BUT_TEXT_RIGHT = 1 << 3, /** Prevent the button to show any tooltip. */ UI_BUT_NO_TOOLTIP = 1 << 4, + /** Do not add the usual horizontal padding for text drawing. */ + UI_BUT_NO_TEXT_PADDING = 1 << 5, /* Button align flag, for drawing groups together. * Used in 'uiBlock.flag', take care! */ @@ -1585,6 +1587,8 @@ int UI_searchbox_size_x(void); /* check if a string is in an existing search box */ int UI_search_items_find_index(uiSearchItems *items, const char *name); +void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]); + void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg); void UI_block_func_butmenu_set(uiBlock *block, uiMenuHandleFunc func, void *arg); void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2); @@ -1772,6 +1776,8 @@ enum { UI_ITEM_O_DEPRESS = 1 << 10, UI_ITEM_R_COMPACT = 1 << 11, UI_ITEM_R_CHECKBOX_INVERT = 1 << 12, + /** Don't add a real decorator item, just blank space. */ + UI_ITEM_R_FORCE_BLANK_DECORATE = 1 << 13, }; #define UI_HEADER_OFFSET ((void)0, 0.4f * UI_UNIT_X) @@ -1782,6 +1788,9 @@ enum { UI_TEMPLATE_OP_PROPS_SHOW_EMPTY = 1 << 1, UI_TEMPLATE_OP_PROPS_COMPACT = 1 << 2, UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED = 1 << 3, + /* Disable property split for the default layout (custom ui callbacks still have full control + * over the layout and can enable it). */ + UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT = 1 << 4, }; /* used for transp checkers */ @@ -1869,7 +1878,9 @@ bool uiLayoutGetPropDecorate(uiLayout *layout); /* layout specifiers */ uiLayout *uiLayoutRow(uiLayout *layout, bool align); +uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading); uiLayout *uiLayoutColumn(uiLayout *layout, bool align); +uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading); uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align); uiLayout *uiLayoutGridFlow(uiLayout *layout, bool row_major, @@ -2044,11 +2055,11 @@ void uiTemplateOperatorSearch(uiLayout *layout); void UI_but_func_menu_search(uiBut *but); void uiTemplateMenuSearch(uiLayout *layout); -eAutoPropButsReturn uiTemplateOperatorPropertyButs(const struct bContext *C, - uiLayout *layout, - struct wmOperator *op, - const eButLabelAlign label_align, - const short flag); +void uiTemplateOperatorPropertyButs(const struct bContext *C, + uiLayout *layout, + struct wmOperator *op, + eButLabelAlign label_align, + short flag); void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C); void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C); void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C); @@ -2088,6 +2099,7 @@ void uiTemplateList(uiLayout *layout, bool sort_reverse, bool sort_lock); void uiTemplateNodeLink(uiLayout *layout, + struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input); @@ -2308,6 +2320,9 @@ void uiItemM_ptr(uiLayout *layout, struct MenuType *mt, const char *name, int ic void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon); /* menu contents */ void uiItemMContents(uiLayout *layout, const char *menuname); +/* Decorators */ +void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index); +void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index); /* value */ void uiItemV(uiLayout *layout, const char *name, int icon, int argval); /* separator */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 9ec660a9714..8ff3dc11dc7 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -641,6 +641,26 @@ static int ui_but_calc_float_precision(uiBut *but, double value) /* ************** BLOCK ENDING FUNCTION ************* */ +bool ui_but_rna_equals(const uiBut *a, const uiBut *b) +{ + return ui_but_rna_equals_ex(a, &b->rnapoin, b->rnaprop, b->rnaindex); +} + +bool ui_but_rna_equals_ex(const uiBut *but, + const PointerRNA *ptr, + const PropertyRNA *prop, + int index) +{ + if (but->rnapoin.data != ptr->data) { + return false; + } + if (but->rnaprop != prop || but->rnaindex != index) { + return false; + } + + return true; +} + /* NOTE: if but->poin is allocated memory for every defbut, things fail... */ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut) { @@ -649,10 +669,7 @@ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut) if (but->retval != oldbut->retval) { return false; } - if (but->rnapoin.data != oldbut->rnapoin.data) { - return false; - } - if (but->rnaprop != oldbut->rnaprop || but->rnaindex != oldbut->rnaindex) { + if (!ui_but_rna_equals(but, oldbut)) { return false; } if (but->func != oldbut->func) { @@ -979,7 +996,9 @@ static void ui_menu_block_set_keyaccels(uiBlock *block) UI_BTYPE_BUT_MENU, UI_BTYPE_MENU, UI_BTYPE_BLOCK, - UI_BTYPE_PULLDOWN) || + UI_BTYPE_PULLDOWN, + /* For PIE-menus. */ + UI_BTYPE_ROW) || (but->flag & UI_HIDDEN)) { /* pass */ } @@ -6486,6 +6505,13 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block, return but; } +void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4]) +{ + but->flag |= UI_BUT_NODE_LINK; + but->custom_data = socket; + rgba_float_to_uchar(but->col, draw_color); +} + /** * push a new event onto event queue to activate the given button * (usually a text-field) upon entering a popup diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 15fc23bc539..877216daacc 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -28,6 +28,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_string_utf8.h" #include "BLI_utildefines.h" @@ -114,10 +115,38 @@ void ui_but_anim_flag(uiBut *but, float cfra) } } +static uiBut *ui_but_anim_decorate_find_attached_button(uiBut *but_decorate) +{ + uiBut *but_iter = NULL; + + BLI_assert(UI_but_is_decorator(but_decorate)); + BLI_assert(but_decorate->rnasearchpoin.data && but_decorate->rnasearchprop); + + LISTBASE_CIRCULAR_BACKWARD_BEGIN (&but_decorate->block->buttons, but_iter, but_decorate->prev) { + if (but_iter != but_decorate && ui_but_rna_equals_ex(but_decorate, + &but_iter->rnasearchpoin, + but_iter->rnasearchprop, + POINTER_AS_INT(but_iter->custom_data))) { + return but_iter; + } + } + LISTBASE_CIRCULAR_BACKWARD_END(&but_decorate->block->buttons, but_iter, but_decorate->prev); + + return NULL; +} + void ui_but_anim_decorate_update_from_flag(uiBut *but) { - BLI_assert(UI_but_is_decorator(but) && but->prev); - int flag = but->prev->flag; + const uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but); + + if (!but_anim) { + printf("Could not find button with matching property to decorate (%s.%s)", + RNA_struct_identifier(but->rnapoin.type), + RNA_property_identifier(but->rnaprop)); + } + + int flag = but_anim->flag; + if (flag & UI_BUT_DRIVEN) { but->icon = ICON_DECORATE_DRIVER; } @@ -289,22 +318,26 @@ void ui_but_anim_paste_driver(bContext *C) void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy)) { wmWindowManager *wm = CTX_wm_manager(C); - uiBut *but = arg_but; - but = but->prev; + uiBut *but_decorate = arg_but; + uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but_decorate); + + if (!but_anim) { + return; + } /* FIXME(campbell), swapping active pointer is weak. */ - SWAP(struct uiHandleButtonData *, but->active, but->next->active); + SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active); wm->op_undo_depth++; - if (but->flag & UI_BUT_DRIVEN) { + if (but_anim->flag & UI_BUT_DRIVEN) { /* pass */ /* TODO: report? */ } - else if (but->flag & UI_BUT_ANIMATED_KEY) { + else if (but_anim->flag & UI_BUT_ANIMATED_KEY) { PointerRNA props_ptr; wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_delete_button", false); WM_operator_properties_create_ptr(&props_ptr, ot); - RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1); + RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1); WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); WM_operator_properties_free(&props_ptr); } @@ -312,11 +345,11 @@ void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy) PointerRNA props_ptr; wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_insert_button", false); WM_operator_properties_create_ptr(&props_ptr, ot); - RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1); + RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1); WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); WM_operator_properties_free(&props_ptr); } - SWAP(struct uiHandleButtonData *, but->active, but->next->active); + SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active); wm->op_undo_depth--; } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 51fe990bd02..c2417c86086 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -790,6 +790,11 @@ float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]); void ui_but_add_shortcut(uiBut *but, const char *key_str, const bool do_strip); void ui_but_clipboard_free(void); +bool ui_but_rna_equals(const uiBut *a, const uiBut *b); +bool ui_but_rna_equals_ex(const uiBut *but, + const PointerRNA *ptr, + const PropertyRNA *prop, + int index); uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new); uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new); @@ -853,7 +858,7 @@ void ui_draw_menu_item(const struct uiFontStyle *fstyle, int iconid, int state, bool use_sep, - int *r_name_width); + int *r_xmax); void ui_draw_preview_item( const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index cbea32f179a..80e248650e5 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -75,7 +75,7 @@ } \ (void)0 -#define UI_ITEM_PROP_SEP_DIVIDE 0.5f +#define UI_ITEM_PROP_SEP_DIVIDE 0.4f /* uiLayoutRoot */ @@ -135,10 +135,11 @@ enum { UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */ UI_ITEM_PROP_SEP = 1 << 3, + UI_ITEM_INSIDE_PROP_SEP = 1 << 4, /* Show an icon button next to each property (to set keyframes, show status). * Enabled by default, depends on 'UI_ITEM_PROP_SEP'. */ - UI_ITEM_PROP_DECORATE = 1 << 4, - UI_ITEM_PROP_DECORATE_NO_PAD = 1 << 5, + UI_ITEM_PROP_DECORATE = 1 << 5, + UI_ITEM_PROP_DECORATE_NO_PAD = 1 << 6, }; typedef struct uiButtonItem { @@ -151,8 +152,11 @@ struct uiLayout { uiLayoutRoot *root; bContextStore *context; + uiLayout *parent; ListBase items; + char heading[UI_MAX_NAME_STR]; + /** Sub layout to add child items, if not the layout itself. */ uiLayout *child_items_layout; @@ -1780,6 +1784,7 @@ static void ui_item_rna_size(uiLayout *layout, PropertyType type; PropertySubType subtype; int len, w = 0, h; + bool is_checkbox_only = false; /* arbitrary extended width by type */ type = RNA_property_type(prop); @@ -1791,6 +1796,10 @@ static void ui_item_rna_size(uiLayout *layout, name = "non-empty text"; } else if (type == PROP_BOOLEAN) { + if (icon == ICON_NONE) { + /* Exception for checkboxes, they need a little less space to align nicely. */ + is_checkbox_only = true; + } icon = ICON_DOT; } else if (type == PROP_ENUM) { @@ -1850,6 +1859,9 @@ static void ui_item_rna_size(uiLayout *layout, if (type == PROP_BOOLEAN && name[0]) { w += UI_UNIT_X / 5; } + else if (is_checkbox_only) { + w -= UI_UNIT_X / 4; + } else if (type == PROP_ENUM && !icon_only) { w += UI_UNIT_X / 4; } @@ -1863,13 +1875,62 @@ static void ui_item_rna_size(uiLayout *layout, } /** + * Find first layout ancestor (or self) with a heading set. + * + * \returns the layout to add the heading to as fallback (i.e. if it can't be placed in a split + * layout). Its #uiLayout.heading member can be cleared to mark the heading as added (so + * it's not added multiple times). Returns a pointer to the heading + */ +static uiLayout *ui_layout_heading_find(uiLayout *cur_layout) +{ + for (uiLayout *parent = cur_layout; parent; parent = parent->parent) { + if (parent->heading[0]) { + return parent; + } + } + + return NULL; +} + +static void ui_layout_heading_label_add(uiLayout *layout, + uiLayout *heading_layout, + bool right_align, + bool respect_prop_split) +{ + const int prev_alignment = layout->alignment; + + if (right_align) { + uiLayoutSetAlignment(layout, UI_LAYOUT_ALIGN_RIGHT); + } + + if (respect_prop_split) { + uiItemL_respect_property_split(layout, heading_layout->heading, ICON_NONE); + } + else { + uiItemL(layout, heading_layout->heading, ICON_NONE); + } + /* After adding the heading label, we have to mark it somehow as added, so it's not added again + * for other items in this layout. For now just clear it. */ + heading_layout->heading[0] = '\0'; + + layout->alignment = prev_alignment; +} + +/** * Hack to add further items in a row into the second part of the split layout, so the label part * keeps a fixed size. * \return The layout to place further items in for the split layout. */ static uiLayout *ui_item_prop_split_layout_hack(uiLayout *layout_parent, uiLayout *layout_split) { + /* Tag item as using property split layout, this is inherited to children so they can get special + * treatment if needed. */ + layout_parent->item.flag |= UI_ITEM_INSIDE_PROP_SEP; + if (layout_parent->item.type == ITEM_LAYOUT_ROW) { + /* Prevent further splits within the row. */ + uiLayoutSetPropSep(layout_parent, false); + layout_parent->child_items_layout = uiLayoutRow(layout_split, true); return layout_parent->child_items_layout; } @@ -1888,13 +1949,18 @@ void uiItemFullR(uiLayout *layout, uiBlock *block = layout->root->block; char namestr[UI_MAX_NAME_STR]; const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0); - - /* By default 'use_prop_sep' uses a separate column for labels. - * This is an exception for check-boxes otherwise only the small checkbox region is clickable. + const bool inside_prop_sep = ((layout->item.flag & UI_ITEM_INSIDE_PROP_SEP) != 0); + /* Columns can define a heading to insert. If the first item added to a split layout doesn't have + * a label to display in the first column, the heading is inserted there. Otherwise it's inserted + * as a new row before the first item. */ + uiLayout *heading_layout = ui_layout_heading_find(layout); + /* Although checkboxes use the split layout, they are an exception and should only place their + * label in the second column, to not make that almost empty. * * Keep using 'use_prop_sep' instead of disabling it entirely because * we need the ability to have decorators still. */ bool use_prop_sep_split_label = use_prop_sep; + bool forbid_single_col = false; #ifdef UI_PROP_DECORATE struct { @@ -2005,6 +2071,9 @@ void uiItemFullR(uiLayout *layout, if (use_prop_sep) { if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) { use_prop_sep_split_label = false; + /* For checkboxes we make an expection: We allow showing them in a split row even without + * label. It typically relates to its neighbor items, so no need for an extra label. */ + forbid_single_col = true; } } #endif @@ -2031,6 +2100,7 @@ void uiItemFullR(uiLayout *layout, /* Split the label / property. */ uiLayout *layout_parent = layout; + if (use_prop_sep) { uiLayout *layout_row = NULL; #ifdef UI_PROP_DECORATE @@ -2041,21 +2111,28 @@ void uiItemFullR(uiLayout *layout, } #endif /* UI_PROP_DECORATE */ - if ((name[0] == '\0') || (use_prop_sep_split_label == false)) { + if ((name[0] == '\0') && !forbid_single_col) { /* Ensure we get a column when text is not set. */ layout = uiLayoutColumn(layout_row ? layout_row : layout, true); layout->space = 0; + if (heading_layout) { + ui_layout_heading_label_add(layout, heading_layout, false, false); + } } else { const PropertySubType subtype = RNA_property_subtype(prop); uiLayout *layout_split = uiLayoutSplit( layout_row ? layout_row : layout, UI_ITEM_PROP_SEP_DIVIDE, true); + bool label_added = false; layout_split->space = 0; uiLayout *layout_sub = uiLayoutColumn(layout_split, true); layout_sub->space = 0; - if ((index == RNA_NO_INDEX && is_array) && - ((!expand && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA, PROP_DIRECTION)) == 0)) { + if (!use_prop_sep_split_label) { + /* Pass */ + } + else if ((index == RNA_NO_INDEX && is_array) && + ((!expand && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA, PROP_DIRECTION)) == 0)) { char name_with_suffix[UI_MAX_DRAW_STR + 2]; char str[2] = {'\0'}; for (int a = 0; a < len; a++) { @@ -2084,6 +2161,8 @@ void uiItemFullR(uiLayout *layout, ""); but->drawflag |= UI_BUT_TEXT_RIGHT; but->drawflag &= ~UI_BUT_TEXT_LEFT; + + label_added = true; } } else { @@ -2092,13 +2171,17 @@ void uiItemFullR(uiLayout *layout, block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); but->drawflag |= UI_BUT_TEXT_RIGHT; but->drawflag &= ~UI_BUT_TEXT_LEFT; + + label_added = true; } } - if (layout_parent) { - layout_split = ui_item_prop_split_layout_hack(layout_parent, layout_split); + if (!label_added && heading_layout) { + ui_layout_heading_label_add(layout_sub, heading_layout, true, false); } + layout_split = ui_item_prop_split_layout_hack(layout_parent, layout_split); + /* Watch out! We can only write into the new layout now. */ if ((type == PROP_ENUM) && (flag & UI_ITEM_R_EXPAND)) { /* Expanded enums each have their own name. */ @@ -2113,7 +2196,9 @@ void uiItemFullR(uiLayout *layout, } } else { - name = ""; + if (use_prop_sep_split_label) { + name = ""; + } layout = uiLayoutColumn(layout_split, true); } layout->space = 0; @@ -2132,9 +2217,20 @@ void uiItemFullR(uiLayout *layout, #endif /* UI_PROP_DECORATE */ } /* End split. */ + else if (heading_layout) { + /* Could not add heading to split layout, fallback to inserting it to the layout with the + * heading itself. */ + ui_layout_heading_label_add(heading_layout, heading_layout, false, false); + } /* array property */ if (index == RNA_NO_INDEX && is_array) { + if (inside_prop_sep) { + /* Within a split row, add array items to a column so they match the column layout of + * previous items (e.g. transform vector with lock icon for each item). */ + layout = uiLayoutColumn(layout, true); + } + ui_item_array(layout, block, name, @@ -2214,12 +2310,6 @@ void uiItemFullR(uiLayout *layout, if (layout->activate_init) { UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); } - - if (use_prop_sep && (use_prop_sep_split_label == false)) { - /* When the button uses it's own text right align it. */ - but->drawflag |= UI_BUT_TEXT_RIGHT; - but->drawflag &= ~UI_BUT_TEXT_LEFT; - } } /* The resulting button may have the icon set since boolean button drawing @@ -2242,50 +2332,21 @@ void uiItemFullR(uiLayout *layout, #ifdef UI_PROP_DECORATE if (ui_decorate.use_prop_decorate) { - const bool is_anim = RNA_property_animateable(ptr, prop); uiBut *but_decorate = ui_decorate.but ? ui_decorate.but->next : block->buttons.first; + const bool use_blank_decorator = (flag & UI_ITEM_R_FORCE_BLANK_DECORATE); uiLayout *layout_col = uiLayoutColumn(ui_decorate.layout, false); layout_col->space = 0; layout_col->emboss = UI_EMBOSS_NONE; + int i; for (i = 0; i < ui_decorate.len && but_decorate; i++) { + PointerRNA *ptr_dec = use_blank_decorator ? NULL : &but_decorate->rnapoin; + PropertyRNA *prop_dec = use_blank_decorator ? NULL : but_decorate->rnaprop; + /* The icons are set in 'ui_but_anim_flag' */ - if (is_anim) { - but = uiDefIconBut(block, - UI_BTYPE_BUT, - 0, - ICON_DOT, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0.0, - 0.0, - TIP_("Animate property")); - UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL); - but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK; - } - else { - /* We may show other information here in future, for now use empty space. */ - but = uiDefIconBut(block, - UI_BTYPE_BUT, - 0, - ICON_BLANK1, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0.0, - 0.0, - ""); - but->flag |= UI_BUT_DISABLED; - } + uiItemDecoratorR_prop(layout_col, ptr_dec, prop_dec, but_decorate->rnaindex); + but = block->buttons.last; + /* Order the decorator after the button we decorate, this is used so we can always * do a quick lookup. */ BLI_remlink(&block->buttons, but); @@ -2759,6 +2820,7 @@ static uiBut *ui_item_menu(uiLayout *layout, bool force_menu) { uiBlock *block = layout->root->block; + uiLayout *heading_layout = ui_layout_heading_find(layout); uiBut *but; int w, h; @@ -2788,6 +2850,10 @@ static uiBut *ui_item_menu(uiLayout *layout, } } + if (heading_layout) { + ui_layout_heading_label_add(layout, heading_layout, true, true); + } + if (name[0] && icon) { but = uiDefIconTextMenuBut(block, func, arg, icon, name, 0, 0, w, h, tip); } @@ -2861,6 +2927,79 @@ void uiItemMContents(uiLayout *layout, const char *menuname) UI_menutype_draw(C, mt, layout); } +/** + * Insert a decorator item for a button with the same property as \a prop. + * To force inserting a blank dummy element, NULL can be passed for \a ptr and \a prop. + */ +void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index) +{ + uiBlock *block = layout->root->block; + const bool is_anim = ptr && prop && RNA_property_animateable(ptr, prop); + uiBut *but = NULL; + uiLayout *row; + + UI_block_layout_set_current(block, layout); + row = uiLayoutRow(layout, false); + row->space = 0; + row->emboss = UI_EMBOSS_NONE; + + if (is_anim) { + but = uiDefIconBut(block, + UI_BTYPE_BUT, + 0, + ICON_DOT, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + TIP_("Animate property")); + UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL); + but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK; + /* Reusing RNA search members, setting actual RNA data has many side-effects. */ + but->rnasearchpoin = *ptr; + but->rnasearchprop = prop; + but->custom_data = POINTER_FROM_INT(index); + } + else { + /* We may show other information here in future, for now use empty space. */ + but = uiDefIconBut(block, + UI_BTYPE_BUT, + 0, + ICON_BLANK1, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + ""); + but->flag |= UI_BUT_DISABLED; + } +} + +void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index) +{ + PropertyRNA *prop; + + /* validate arguments */ + prop = RNA_struct_find_property(ptr, propname); + if (!prop) { + ui_item_disabled(layout, propname); + RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); + return; + } + + uiItemDecoratorR_prop(layout, ptr, prop, index); +} + /* popover */ void uiItemPopoverPanel_ptr( uiLayout *layout, bContext *C, PanelType *pt, const char *name, int icon) @@ -3017,6 +3156,7 @@ uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int { if (layout->item.flag & UI_ITEM_PROP_SEP) { uiBlock *block = uiLayoutGetBlock(layout); + uiLayout *layout_row = uiLayoutRow(layout, true); uiLayout *layout_split = uiLayoutSplit(layout_row, UI_ITEM_PROP_SEP_DIVIDE, true); uiLayout *layout_sub = uiLayoutColumn(layout_split, true); @@ -3029,8 +3169,9 @@ uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int layout_split = ui_item_prop_split_layout_hack(layout, layout_split); UI_block_layout_set_current(block, layout_split); - /* Give caller a new sub-row to place items in. */ - return layout_row; + /* The decorator layout uses the row the split layout was inserted to. */ + uiLayout *layout_decorator = layout_row; + return layout_decorator; } else { char namestr[UI_MAX_NAME_STR]; @@ -4471,13 +4612,24 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali litem->redalert = layout->redalert; litem->w = layout->w; litem->emboss = layout->emboss; - litem->item.flag = (layout->item.flag & (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE)); + litem->item.flag = (layout->item.flag & + (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE | UI_ITEM_INSIDE_PROP_SEP)); if (layout->child_items_layout) { BLI_addtail(&layout->child_items_layout->items, litem); + litem->parent = layout->child_items_layout; } else { BLI_addtail(&layout->items, litem); + litem->parent = layout; + } +} + +static void ui_layout_heading_set(uiLayout *layout, const char *heading) +{ + BLI_assert(layout->heading[0] == '\0'); + if (heading) { + STRNCPY(layout->heading, heading); } } @@ -4497,6 +4649,16 @@ uiLayout *uiLayoutRow(uiLayout *layout, bool align) return litem; } +/** + * See #uiLayoutColumnWithHeading(). + */ +uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading) +{ + uiLayout *litem = uiLayoutRow(layout, align); + ui_layout_heading_set(litem, heading); + return litem; +} + uiLayout *uiLayoutColumn(uiLayout *layout, bool align) { uiLayout *litem; @@ -4512,6 +4674,19 @@ uiLayout *uiLayoutColumn(uiLayout *layout, bool align) return litem; } +/** + * Variant of #uiLayoutColumn() that sets a heading label for the layout if the first item is + * added through #uiItemFullR(). If split layout is used and the item has no string to add to the + * first split-column, the heading is added there instead. Otherwise the heading inserted with a + * new row. + */ +uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading) +{ + uiLayout *litem = uiLayoutColumn(layout, align); + ui_layout_heading_set(litem, heading); + return litem; +} + uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align) { uiLayoutItemFlow *flow; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index d1c61925d40..b8f87a4300c 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -742,7 +742,7 @@ void ui_draw_aligned_panel(uiStyle *style, /* an open panel */ else { /* in some occasions, draw a border */ - if (panel->flag & PNL_SELECT) { + if (panel->flag & PNL_SELECT && !is_subpanel) { if (panel->control & UI_PNL_SOLID) { UI_draw_roundbox_corner_set(UI_CNR_ALL); } @@ -2457,6 +2457,24 @@ static void ui_handler_remove_panel(bContext *C, void *userdata) panel_activate_state(C, panel, PANEL_STATE_EXIT); } +/** + * Set selection state for a panel and its subpanels. The subpanels need to know they are selected + * too so they can be drawn above their parent when it is dragged. + */ +static void set_panel_selection(Panel *panel, bool value) +{ + if (value) { + panel->flag |= PNL_SELECT; + } + else { + panel->flag &= ~PNL_SELECT; + } + + LISTBASE_FOREACH (Panel *, child, &panel->children) { + set_panel_selection(child, value); + } +} + static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state) { uiHandlePanelData *data = panel->activedata; @@ -2479,10 +2497,10 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS check_panel_overlap(region, NULL); /* clears */ } - panel->flag &= ~PNL_SELECT; + set_panel_selection(panel, false); } else { - panel->flag |= PNL_SELECT; + set_panel_selection(panel, true); } if (data && data->animtimer) { diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index ca9f12a4219..27ce20ae374 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -2432,21 +2432,196 @@ uiLayout *uiTemplateShaderFx(uiLayout *layout, bContext *UNUSED(C), PointerRNA * /** \} */ /* -------------------------------------------------------------------- */ -/** \name Operator Redo Buttons Template +/** \name Operator Property Buttons Template * \{ */ -static void template_operator_redo_property_buts_draw( - const bContext *C, wmOperator *op, uiLayout *layout, int layout_flags, bool *r_has_advanced) +typedef struct uiTemplateOperatorPropertyPollParam { + const bContext *C; + wmOperator *op; + short flag; +} uiTemplateOperatorPropertyPollParam; + +#ifdef USE_OP_RESET_BUT +static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), + void *op_pt, + void *UNUSED(arg_dummy2)) +{ + WM_operator_properties_reset((wmOperator *)op_pt); +} +#endif + +static bool ui_layout_operator_buts_poll_property(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *prop, + void *user_data) +{ + uiTemplateOperatorPropertyPollParam *params = user_data; + + if ((params->flag & UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED) && + (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED)) { + return false; + } + return params->op->type->poll_property(params->C, params->op, prop); +} + +static eAutoPropButsReturn template_operator_property_buts_draw_single( + const bContext *C, + wmOperator *op, + uiLayout *layout, + const eButLabelAlign label_align, + int layout_flags) +{ + uiBlock *block = uiLayoutGetBlock(layout); + eAutoPropButsReturn return_info = 0; + + if (!op->properties) { + IDPropertyTemplate val = {0}; + op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); + } + + /* poll() on this operator may still fail, + * at the moment there is no nice feedback when this happens just fails silently. */ + if (!WM_operator_repeat_check(C, op)) { + UI_block_lock_set(block, true, "Operator can't' redo"); + return return_info; + } + else { + /* useful for macros where only one of the steps can't be re-done */ + UI_block_lock_clear(block); + } + + if (layout_flags & UI_TEMPLATE_OP_PROPS_SHOW_TITLE) { + uiItemL(layout, WM_operatortype_name(op->type, op->ptr), ICON_NONE); + } + + /* menu */ + if (op->type->flag & OPTYPE_PRESET) { + /* XXX, no simple way to get WM_MT_operator_presets.bl_label + * from python! Label remains the same always! */ + PointerRNA op_ptr; + uiLayout *row; + + block->ui_operator = op; + + row = uiLayoutRow(layout, true); + uiItemM(row, "WM_MT_operator_presets", NULL, ICON_NONE); + + wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false); + uiItemFullO_ptr(row, ot, "", ICON_ADD, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_string_set(&op_ptr, "operator", op->type->idname); + + uiItemFullO_ptr(row, ot, "", ICON_REMOVE, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_string_set(&op_ptr, "operator", op->type->idname); + RNA_boolean_set(&op_ptr, "remove_active", true); + } + + if (op->type->ui) { + op->layout = layout; + op->type->ui((bContext *)C, op); + op->layout = NULL; + + /* UI_LAYOUT_OP_SHOW_EMPTY ignored. retun_info is ignored too. We could + * allow ot.ui callback to return this, but not needed right now. */ + } + else { + wmWindowManager *wm = CTX_wm_manager(C); + PointerRNA ptr; + uiTemplateOperatorPropertyPollParam user_data = {.C = C, .op = op, .flag = layout_flags}; + const bool use_prop_split = (layout_flags & UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT) == 0; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + uiLayoutSetPropSep(layout, use_prop_split); + uiLayoutSetPropDecorate(layout, false); + + /* main draw call */ + return_info = uiDefAutoButsRNA( + layout, + &ptr, + op->type->poll_property ? ui_layout_operator_buts_poll_property : NULL, + op->type->poll_property ? &user_data : NULL, + op->type->prop, + label_align, + (layout_flags & UI_TEMPLATE_OP_PROPS_COMPACT)); + + if ((return_info & UI_PROP_BUTS_NONE_ADDED) && + (layout_flags & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) { + uiItemL(layout, IFACE_("No Properties"), ICON_NONE); + } + } + +#ifdef USE_OP_RESET_BUT + /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled + * but this is not so important if this button is drawn in those cases + * (which isn't all that likely anyway) - campbell */ + if (op->properties->len) { + uiBut *but; + uiLayout *col; /* needed to avoid alignment errors with previous buttons */ + + col = uiLayoutColumn(layout, false); + block = uiLayoutGetBlock(col); + but = uiDefIconTextBut(block, + UI_BTYPE_BUT, + 0, + ICON_FILE_REFRESH, + IFACE_("Reset"), + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + TIP_("Reset operator defaults")); + UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL); + } +#endif + + /* set various special settings for buttons */ + + /* Only do this if we're not refreshing an existing UI. */ + if (block->oldblock == NULL) { + const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0; + uiBut *but; + + for (but = block->buttons.first; but; but = but->next) { + /* no undo for buttons for operator redo panels */ + UI_but_flag_disable(but, UI_BUT_UNDO); + + /* only for popups, see [#36109] */ + + /* if button is operator's default property, and a text-field, enable focus for it + * - this is used for allowing operators with popups to rename stuff with fewer clicks + */ + if (is_popup) { + if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) { + UI_but_focus_on_enter_event(CTX_wm_window(C), but); + } + } + } + } + + return return_info; +} + +static void template_operator_property_buts_draw_recursive(const bContext *C, + wmOperator *op, + uiLayout *layout, + const eButLabelAlign label_align, + int layout_flags, + bool *r_has_advanced) { if (op->type->flag & OPTYPE_MACRO) { LISTBASE_FOREACH (wmOperator *, macro_op, &op->macro) { - template_operator_redo_property_buts_draw(C, macro_op, layout, layout_flags, r_has_advanced); + template_operator_property_buts_draw_recursive( + C, macro_op, layout, label_align, layout_flags, r_has_advanced); } } else { /* Might want to make label_align adjustable somehow. */ - eAutoPropButsReturn return_info = uiTemplateOperatorPropertyButs( - C, layout, op, UI_BUT_LABEL_ALIGN_NONE, layout_flags); + eAutoPropButsReturn return_info = template_operator_property_buts_draw_single( + C, op, layout, label_align, layout_flags); if (return_info & UI_PROP_BUTS_ANY_FAILED_CHECK) { if (r_has_advanced) { *r_has_advanced = true; @@ -2455,6 +2630,61 @@ static void template_operator_redo_property_buts_draw( } } +static bool ui_layout_operator_properties_only_booleans(const bContext *C, + wmWindowManager *wm, + wmOperator *op, + int layout_flags) +{ + if (op->type->flag & OPTYPE_MACRO) { + LISTBASE_FOREACH (wmOperator *, macro_op, &op->macro) { + if (!ui_layout_operator_properties_only_booleans(C, wm, macro_op, layout_flags)) { + return false; + } + } + } + else { + uiTemplateOperatorPropertyPollParam user_data = {.C = C, .op = op, .flag = layout_flags}; + PointerRNA ptr; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + RNA_STRUCT_BEGIN (&ptr, prop) { + if (RNA_property_flag(prop) & PROP_HIDDEN) { + continue; + } + if (op->type->poll_property && + !ui_layout_operator_buts_poll_property(&ptr, prop, &user_data)) { + continue; + } + if (RNA_property_type(prop) != PROP_BOOLEAN) { + return false; + } + } + RNA_STRUCT_END; + } + + return true; +} + +/** + * Draw Operator property buttons for redoing execution with different settings. + * This function does not initialize the layout, + * functions can be called on the layout before and after. + */ +void uiTemplateOperatorPropertyButs( + const bContext *C, uiLayout *layout, wmOperator *op, eButLabelAlign label_align, short flag) +{ + wmWindowManager *wm = CTX_wm_manager(C); + + /* If there are only checkbox items, don't use split layout by default. It looks weird if the + * checkboxes only use half the width. */ + if (ui_layout_operator_properties_only_booleans(C, wm, op, flag)) { + flag |= UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT; + } + + template_operator_property_buts_draw_recursive(C, op, layout, label_align, flag, NULL); +} + void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C) { wmOperator *op = WM_operator_last_redo(C); @@ -2487,8 +2717,8 @@ void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C) #endif UI_block_func_handle_set(block, ED_undo_operator_repeat_cb_evt, op); - template_operator_redo_property_buts_draw( - C, op, layout, layout_flags, NULL /* &has_advanced */); + template_operator_property_buts_draw_recursive( + C, op, layout, UI_BUT_LABEL_ALIGN_NONE, layout_flags, NULL /* &has_advanced */); /* Warning! this leaves the handle function for any other users of this block. */ #if 0 @@ -7348,187 +7578,6 @@ void uiTemplateMenuSearch(uiLayout *layout) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Operator Redo Properties Template - * \{ */ - -#ifdef USE_OP_RESET_BUT -static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), - void *op_pt, - void *UNUSED(arg_dummy2)) -{ - WM_operator_properties_reset((wmOperator *)op_pt); -} -#endif - -struct uiTemplateOperatorPropertyPollParam { - const bContext *C; - wmOperator *op; - short flag; -}; - -static bool ui_layout_operator_buts_poll_property(struct PointerRNA *UNUSED(ptr), - struct PropertyRNA *prop, - void *user_data) -{ - struct uiTemplateOperatorPropertyPollParam *params = user_data; - if ((params->flag & UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED) && - (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED)) { - return false; - } - return params->op->type->poll_property(params->C, params->op, prop); -} - -/** - * Draw Operator property buttons for redoing execution with different settings. - * This function does not initialize the layout, - * functions can be called on the layout before and after. - */ -eAutoPropButsReturn uiTemplateOperatorPropertyButs(const bContext *C, - uiLayout *layout, - wmOperator *op, - const eButLabelAlign label_align, - const short flag) -{ - uiBlock *block = uiLayoutGetBlock(layout); - eAutoPropButsReturn return_info = 0; - - if (!op->properties) { - IDPropertyTemplate val = {0}; - op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); - } - - /* poll() on this operator may still fail, - * at the moment there is no nice feedback when this happens just fails silently. */ - if (!WM_operator_repeat_check(C, op)) { - UI_block_lock_set(block, true, "Operator can't' redo"); - return return_info; - } - else { - /* useful for macros where only one of the steps can't be re-done */ - UI_block_lock_clear(block); - } - - if (flag & UI_TEMPLATE_OP_PROPS_SHOW_TITLE) { - uiItemL(layout, WM_operatortype_name(op->type, op->ptr), ICON_NONE); - } - - /* menu */ - if (op->type->flag & OPTYPE_PRESET) { - /* XXX, no simple way to get WM_MT_operator_presets.bl_label - * from python! Label remains the same always! */ - PointerRNA op_ptr; - uiLayout *row; - - block->ui_operator = op; - - row = uiLayoutRow(layout, true); - uiItemM(row, "WM_MT_operator_presets", NULL, ICON_NONE); - - wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false); - uiItemFullO_ptr(row, ot, "", ICON_ADD, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_string_set(&op_ptr, "operator", op->type->idname); - - uiItemFullO_ptr(row, ot, "", ICON_REMOVE, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_string_set(&op_ptr, "operator", op->type->idname); - RNA_boolean_set(&op_ptr, "remove_active", true); - } - - if (op->type->ui) { - op->layout = layout; - op->type->ui((bContext *)C, op); - op->layout = NULL; - - /* UI_LAYOUT_OP_SHOW_EMPTY ignored. return_info is ignored too. We could - * allow ot.ui callback to return this, but not needed right now. */ - } - else { - wmWindowManager *wm = CTX_wm_manager(C); - PointerRNA ptr; - struct uiTemplateOperatorPropertyPollParam user_data = { - .C = C, - .op = op, - .flag = flag, - }; - - RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); - - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - - /* main draw call */ - return_info = uiDefAutoButsRNA( - layout, - &ptr, - op->type->poll_property ? ui_layout_operator_buts_poll_property : NULL, - op->type->poll_property ? &user_data : NULL, - op->type->prop, - label_align, - (flag & UI_TEMPLATE_OP_PROPS_COMPACT)); - - if ((return_info & UI_PROP_BUTS_NONE_ADDED) && (flag & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) { - uiItemL(layout, IFACE_("No Properties"), ICON_NONE); - } - } - -#ifdef USE_OP_RESET_BUT - /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled - * but this is not so important if this button is drawn in those cases - * (which isn't all that likely anyway) - campbell */ - if (op->properties->len) { - uiBut *but; - uiLayout *col; /* needed to avoid alignment errors with previous buttons */ - - col = uiLayoutColumn(layout, false); - block = uiLayoutGetBlock(col); - but = uiDefIconTextBut(block, - UI_BTYPE_BUT, - 0, - ICON_FILE_REFRESH, - IFACE_("Reset"), - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0.0, - 0.0, - TIP_("Reset operator defaults")); - UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL); - } -#endif - - /* set various special settings for buttons */ - - /* Only do this if we're not refreshing an existing UI. */ - if (block->oldblock == NULL) { - const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0; - uiBut *but; - - for (but = block->buttons.first; but; but = but->next) { - /* no undo for buttons for operator redo panels */ - UI_but_flag_disable(but, UI_BUT_UNDO); - - /* only for popups, see [#36109] */ - - /* if button is operator's default property, and a text-field, enable focus for it - * - this is used for allowing operators with popups to rename stuff with fewer clicks - */ - if (is_popup) { - if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) { - UI_but_focus_on_enter_event(CTX_wm_window(C), but); - } - } - } - } - - return return_info; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Running Jobs Template * \{ */ diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 79a90d27373..d8c168a1423 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -294,7 +294,7 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, const bool compact) { eAutoPropButsReturn return_info = UI_PROP_BUTS_NONE_ADDED; - uiLayout *split, *col; + uiLayout *col; const char *name; RNA_STRUCT_BEGIN (ptr, prop) { @@ -325,19 +325,11 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, } else { BLI_assert(label_align == UI_BUT_LABEL_ALIGN_SPLIT_COLUMN); - split = uiLayoutSplit(layout, 0.5f, false); - - col = uiLayoutColumn(split, false); - uiItemL(col, (is_boolean) ? "" : name, ICON_NONE); - col = uiLayoutColumn(split, false); + col = uiLayoutColumn(layout, true); + /* Let uiItemFullR() create the split layout. */ + uiLayoutSetPropSep(col, true); } - /* May need to add more cases here. - * don't override enum flag names */ - - /* name is shown above, empty name for button below */ - name = (flag & PROP_ENUM_FLAG || is_boolean) ? NULL : ""; - break; } case UI_BUT_LABEL_ALIGN_NONE: diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index ae40b01c77d..064fa14a75e 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -42,6 +42,8 @@ #include "BLF_api.h" +#include "ED_node.h" + #include "UI_interface.h" #include "UI_interface_icons.h" @@ -2394,6 +2396,30 @@ static void widget_draw_extra_icons(const uiWidgetColors *wcol, } } +static void widget_draw_node_link_socket(const uiWidgetColors *wcol, + const rcti *rect, + uiBut *but, + float alpha) +{ + /* Node socket pointer can be passed as custom_data, see UI_but_node_link_set(). */ + if (but->custom_data) { + const float scale = 0.9f / but->block->aspect; + + float col[4]; + rgba_uchar_to_float(col, but->col); + col[3] *= alpha; + + GPU_blend(true); + UI_widgetbase_draw_cache_flush(); + GPU_blend(false); + + ED_node_socket_draw(but->custom_data, rect, col, scale); + } + else { + widget_draw_icon(but, ICON_LAYER_USED, alpha, rect, wcol->text); + } +} + /* draws text and icons for buttons */ static void widget_draw_text_icon(const uiFontStyle *fstyle, const uiWidgetColors *wcol, @@ -2403,15 +2429,27 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, const bool show_menu_icon = ui_but_draw_menu_icon(but); float alpha = (float)wcol->text[3] / 255.0f; char password_str[UI_MAX_DRAW_STR]; + bool no_text_padding = but->drawflag & UI_BUT_NO_TEXT_PADDING; ui_but_text_password_hide(password_str, but, false); /* check for button text label */ if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_POPOVER) && (but->flag & UI_BUT_NODE_LINK)) { rcti temp = *rect; - temp.xmin = rect->xmax - BLI_rcti_size_y(rect) - 1; - widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp, wcol->text); - rect->xmax = temp.xmin; + const int size = BLI_rcti_size_y(rect) + 1; /* Not the icon size! */ + + if (but->drawflag & UI_BUT_ICON_LEFT) { + temp.xmax = rect->xmin + size; + rect->xmin = temp.xmax; + /* Further padding looks off. */ + no_text_padding = true; + } + else { + temp.xmin = rect->xmax - size; + rect->xmax = temp.xmin; + } + + widget_draw_node_link_socket(wcol, &temp, but, alpha); } /* If there's an icon too (made with uiDefIconTextBut) then draw the icon @@ -2496,28 +2534,30 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, rect->xmin += icon_size + icon_padding; } - int text_padding = (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; - if (but->editstr) { - rect->xmin += text_padding; - } - else if (but->flag & UI_BUT_DRAG_MULTI) { - bool text_is_edited = ui_but_drag_multi_edit_get(but) != NULL; - if (text_is_edited) { + if (!no_text_padding) { + int text_padding = (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; + if (but->editstr) { rect->xmin += text_padding; } - } - else if (but->drawflag & UI_BUT_TEXT_LEFT) { - - /* Reduce the left padding for labels without an icon. */ - if ((but->type == UI_BTYPE_LABEL) && !(but->flag & UI_HAS_ICON) && - !ui_block_is_menu(but->block)) { - text_padding /= 2; + else if (but->flag & UI_BUT_DRAG_MULTI) { + bool text_is_edited = ui_but_drag_multi_edit_get(but) != NULL; + if (text_is_edited) { + rect->xmin += text_padding; + } } + else if (but->drawflag & UI_BUT_TEXT_LEFT) { - rect->xmin += text_padding; - } - else if (but->drawflag & UI_BUT_TEXT_RIGHT) { - rect->xmax -= text_padding; + /* Reduce the left padding for labels without an icon. */ + if ((but->type == UI_BTYPE_LABEL) && !(but->flag & UI_HAS_ICON) && + !ui_block_is_menu(but->block)) { + text_padding /= 2; + } + + rect->xmin += text_padding; + } + else if (but->drawflag & UI_BUT_TEXT_RIGHT) { + rect->xmax -= text_padding; + } } /* Menu contains sub-menu items with triangle icon on their right. Shortcut @@ -4121,10 +4161,10 @@ static void widget_optionbut(uiWidgetColors *wcol, /* smaller */ delta = 1 + BLI_rcti_size_y(&recttemp) / 8; - recttemp.xmin += delta; - recttemp.ymin += delta; - recttemp.xmax -= delta; - recttemp.ymax -= delta; + BLI_rcti_resize( + &recttemp, BLI_rcti_size_x(&recttemp) - delta * 2, BLI_rcti_size_y(&recttemp) - delta * 2); + /* Keep one edge in place. */ + BLI_rcti_translate(&recttemp, text_before_widget ? delta : -delta, 0); rad = wcol->roundness * BLI_rcti_size_y(&recttemp); round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad); @@ -4136,13 +4176,13 @@ static void widget_optionbut(uiWidgetColors *wcol, widgetbase_draw(&wtb, wcol); - /* text space */ - const float offset = BLI_rcti_size_y(rect) * 0.7 + delta; + /* Text space - factor is really just eyeballed. */ + const float offset = delta * 0.9; if (text_before_widget) { - rect->xmax -= offset; + rect->xmax = recttemp.xmin - offset; } else { - rect->xmin += offset; + rect->xmin = recttemp.xmax + offset; } } @@ -4699,9 +4739,14 @@ void ui_draw_but(const bContext *C, ARegion *region, uiStyle *style, uiBut *but, case UI_BTYPE_CHECKBOX_N: if (!(but->flag & UI_HAS_ICON)) { wt = widget_type(UI_WTYPE_CHECKBOX); + if ((but->drawflag & (UI_BUT_TEXT_LEFT | UI_BUT_TEXT_RIGHT)) == 0) { but->drawflag |= UI_BUT_TEXT_LEFT; } + /* widget_optionbut() carefully sets the text rectangle for fine tuned paddings. If the + * text drawing were to add its own padding, DPI and zoom factor would be applied twice + * in the final padding, so it's difficult to control it. */ + but->drawflag |= UI_BUT_NO_TEXT_PADDING; } else { wt = widget_type(UI_WTYPE_TOGGLE); @@ -5252,15 +5297,23 @@ void ui_draw_tooltip_background(const uiStyle *UNUSED(style), uiBlock *UNUSED(bl wt->draw(&wt->wcol, rect, 0, 0); } -/* helper call to draw a menu item without button */ -/* state: UI_ACTIVE or 0 */ +/** + * Helper call to draw a menu item without a button. + * + * \param state: The state of the button, + * typically #UI_ACTIVE, #UI_BUT_DISABLED, #UI_BUT_INACTIVE. + * \param use_sep: When true, characters after the last #UI_SEP_CHAR are right aligned, + * use for displaying key shortcuts. + * \param r_xmax: The right hand position of the text, this takes into the icon, + * padding and text clipping when there is not enough room to display the full text. + */ void ui_draw_menu_item(const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep, - int *r_name_width) + int *r_xmax) { uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM); rcti _rect = *rect; @@ -5323,8 +5376,8 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, &xofs, &yofs, &info); - if (r_name_width != NULL) { - *r_name_width = xofs + info.width; + if (r_xmax != NULL) { + *r_xmax = xofs + info.width; } } diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index c07166b9ad2..72f6535eadf 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -60,7 +60,7 @@ #include "interface_intern.h" -static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mask_scrollers); +static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize); /* -------------------------------------------------------------------- */ /** \name Internal Utilities @@ -134,7 +134,7 @@ void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask) * * \param mask_scroll: Optionally clamp scrollbars by this region. */ -static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scroll) +static void view2d_masks(View2D *v2d, const rcti *mask_scroll) { int scroll; @@ -144,26 +144,24 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr mask_scroll = &v2d->mask; } - if (check_scrollers) { - /* check size if hiding flag is set: */ - if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) { - if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) { - if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) { - v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR; - } - else { - v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR; - } + /* check size if hiding flag is set: */ + if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) { + if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) { + if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) { + v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR; + } + else { + v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR; } } - if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) { - if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) { - if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) { - v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR; - } - else { - v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR; - } + } + if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) { + if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) { + if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) { + v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR; + } + else { + v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR; } } } @@ -385,8 +383,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) v2d->winx = winx; v2d->winy = winy; - /* set masks (always do), but leave scroller scheck to totrect_set */ - view2d_masks(v2d, 0, NULL); + view2d_masks(v2d, NULL); if (do_init) { /* Visible by default. */ @@ -394,13 +391,12 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) } /* set 'tot' rect before setting cur? */ - /* XXX confusing stuff here still - - * I made this function not check scroller hide - that happens in totrect_set */ + /* XXX confusing stuff here still */ if (tot_changed) { UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init); } else { - ui_view2d_curRect_validate_resize(v2d, !do_init, 0); + ui_view2d_curRect_validate_resize(v2d, !do_init); } } @@ -409,7 +405,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) * 'cur' is not allowed to be: larger than max, smaller than min, or outside of 'tot' */ // XXX pre2.5 -> this used to be called test_view2d() -static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mask_scrollers) +static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize) { float totwidth, totheight, curwidth, curheight, width, height; float winx, winy; @@ -851,12 +847,12 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas } /* set masks */ - view2d_masks(v2d, mask_scrollers, NULL); + view2d_masks(v2d, NULL); } void UI_view2d_curRect_validate(View2D *v2d) { - ui_view2d_curRect_validate_resize(v2d, 0, 1); + ui_view2d_curRect_validate_resize(v2d, false); } /* ------------------ */ @@ -982,22 +978,10 @@ void UI_view2d_curRect_reset(View2D *v2d) /* Change the size of the maximum viewable area (i.e. 'tot' rect) */ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resize) { - // int scroll = view2d_scroll_mapped(v2d->scroll); - /* don't do anything if either value is 0 */ width = abs(width); height = abs(height); - /* hrumf! */ - /* XXX: there are work arounds for this in the panel and file browse code. */ - /* round to int, because this is called with width + V2D_SCROLL_WIDTH */ - // if (scroll & V2D_SCROLL_HORIZONTAL) { - // width -= (int)V2D_SCROLL_WIDTH; - // } - // if (scroll & V2D_SCROLL_VERTICAL) { - // height -= (int)V2D_SCROLL_HEIGHT; - // } - if (ELEM(0, width, height)) { if (G.debug & G_DEBUG) { printf("Error: View2D totRect set exiting: v2d=%p width=%d height=%d\n", @@ -1047,20 +1031,12 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resiz } /* make sure that 'cur' rect is in a valid state as a result of these changes */ - ui_view2d_curRect_validate_resize(v2d, resize, 1); + ui_view2d_curRect_validate_resize(v2d, resize); } void UI_view2d_totRect_set(View2D *v2d, int width, int height) { - int scroll = view2d_scroll_mapped(v2d->scroll); - - UI_view2d_totRect_set_resize(v2d, width, height, 0); - - /* solve bad recursion... if scroller state changed, - * mask is different, so you get different rects */ - if (scroll != view2d_scroll_mapped(v2d->scroll)) { - UI_view2d_totRect_set_resize(v2d, width, height, 0); - } + UI_view2d_totRect_set_resize(v2d, width, height, false); } bool UI_view2d_tab_set(View2D *v2d, int tab) @@ -1448,7 +1424,7 @@ View2DScrollers *UI_view2d_scrollers_calc(View2D *v2d, const rcti *mask_custom) scrollers = MEM_callocN(sizeof(View2DScrollers), "View2DScrollers"); /* Always update before drawing (for dynamically sized scrollers). */ - view2d_masks(v2d, false, mask_custom); + view2d_masks(v2d, mask_custom); vert = v2d->vert; hor = v2d->hor; diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 23f622ac359..bf6c5a2f829 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -226,6 +226,7 @@ static bool edbm_extrude_ex(Object *obedit, char htype, const char hflag, const bool use_normal_flip, + const bool use_dissolve_ortho_edges, const bool use_mirror, const bool use_select_history) { @@ -241,6 +242,7 @@ static bool edbm_extrude_ex(Object *obedit, BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region"); BMO_slot_bool_set(extop.slots_in, "use_normal_flip", use_normal_flip); + BMO_slot_bool_set(extop.slots_in, "use_dissolve_ortho_edges", use_dissolve_ortho_edges); BMO_slot_bool_set(extop.slots_in, "use_select_history", use_select_history); BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", htype, hflag); @@ -312,7 +314,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) mul_v3_m3v3(offset_local, tmat, offset); for (int a = 0; a < steps; a++) { - edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, true); + edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, false, true); BMO_op_callf( em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", offset_local, BM_ELEM_SELECT); } @@ -359,6 +361,7 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot) static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op) { const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip"); + const bool use_dissolve_ortho_edges = RNA_boolean_get(op->ptr, "use_dissolve_ortho_edges"); const char htype = edbm_extrude_htype_from_em_select(em); enum { NONE = 0, ELEM_FLAG, VERT_ONLY, EDGE_ONLY } nr; bool changed = false; @@ -401,7 +404,14 @@ static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op) case NONE: return false; case ELEM_FLAG: - changed = edbm_extrude_ex(obedit, em, htype, BM_ELEM_SELECT, use_normal_flip, true, true); + changed = edbm_extrude_ex(obedit, + em, + htype, + BM_ELEM_SELECT, + use_normal_flip, + use_dissolve_ortho_edges, + true, + true); break; case VERT_ONLY: changed = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT); @@ -465,6 +475,7 @@ void MESH_OT_extrude_region(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", ""); + RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", ""); Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY); } @@ -519,6 +530,7 @@ void MESH_OT_extrude_context(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", ""); + RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", ""); Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY); } @@ -840,7 +852,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w } } - edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, true, true); + edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, false, true, true); EDBM_op_callf( vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, local_center, mat); EDBM_op_callf(vc.em, op, "translate verts=%hv vec=%v", BM_ELEM_SELECT, ofs); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 66b2c66f2aa..c52a5956ac4 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -277,6 +277,18 @@ void ED_operatormacros_mesh(void) RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false); RNA_boolean_set(otmacro->ptr, "mirror", false); + ot = WM_operatortype_append_macro( + "MESH_OT_extrude_region_dissolve_move_intersect", + "Extrude, Dissolve, Move and Intersect", + "Extrude, dissolves edges whose faces form a flat surface and intersect new edges", + OPTYPE_UNDO | OPTYPE_REGISTER); + otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region"); + RNA_boolean_set(otmacro->ptr, "use_dissolve_ortho_edges", true); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false); + RNA_boolean_set(otmacro->ptr, "mirror", false); + RNA_boolean_set(otmacro->ptr, "use_automerge_and_split", true); + ot = WM_operatortype_append_macro("MESH_OT_extrude_context_move", "Extrude Region and Move", "Extrude region together along the average normal", diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index c2c25e47908..de9cc72dfa4 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -34,6 +34,7 @@ set(INC ../../shader_fx ../../render/extern/include ../../windowmanager + ../../../../intern/clog ../../../../intern/glew-mx ../../../../intern/guardedalloc ) diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 5506895613b..d944d4c4dd3 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -100,6 +100,8 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "CLG_log.h" + /* for menu/popup icons etc etc*/ #include "UI_interface.h" @@ -112,21 +114,17 @@ #include "object_intern.h" // own include +static CLG_LogRef LOG = {"ed.object.edit"}; + /* prototypes */ typedef struct MoveToCollectionData MoveToCollectionData; static void move_to_collection_menus_items(struct uiLayout *layout, struct MoveToCollectionData *menu); static ListBase selected_objects_get(bContext *C); -/* ************* XXX **************** */ -static void error(const char *UNUSED(arg)) -{ -} - -/* port over here */ -static void error_libdata(void) -{ -} +/* -------------------------------------------------------------------- */ +/** \name Internal Utilities + * \{ */ Object *ED_object_context(bContext *C) { @@ -147,7 +145,11 @@ Object *ED_object_active_context(bContext *C) return ob; } -/* ********************** object hiding *************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide Operator + * \{ */ static bool object_hide_poll(bContext *C) { @@ -401,7 +403,11 @@ void OBJECT_OT_hide_collection(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } -/* ******************* toggle editmode operator ***************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Edit-Mode Operator + * \{ */ static bool mesh_needs_keyindex(Main *bmain, const Mesh *me) { @@ -441,7 +447,11 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f } if (me->edit_mesh->bm->totvert > MESH_MAX_VERTS) { - error("Too many vertices"); + /* This used to be warned int the UI, we could warn again although it's quite rare. */ + CLOG_WARN(&LOG, + "Too many vertices for mesh '%s' (%d)", + me->id.name + 2, + me->edit_mesh->bm->totvert); return false; } @@ -600,7 +610,8 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag } if (BKE_object_obdata_is_libdata(ob)) { - error_libdata(); + /* Ideally the caller should check this. */ + CLOG_WARN(&LOG, "Unable to enter edit-mode on library data for object '%s'", ob->id.name + 2); return false; } @@ -777,7 +788,11 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* *************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Pose-Mode Operator + * \{ */ static int posemode_exec(bContext *C, wmOperator *op) { @@ -861,7 +876,11 @@ void OBJECT_OT_posemode_toggle(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************* force field toggle operator ***************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Force Field Toggle Operator + * \{ */ void ED_object_check_force_modifiers(Main *bmain, Scene *scene, Object *object) { @@ -924,8 +943,11 @@ void OBJECT_OT_forcefield_toggle(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************************************** */ -/* Motion Paths */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Calculate Motion Paths Operator + * \{ */ static eAnimvizCalcRange object_path_convert_range(eObjectPathCalcRange range) { @@ -1019,7 +1041,7 @@ static int object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEv } /* show popup dialog to allow editing of range... */ - /* FIXME: hardcoded dimensions here are just arbitrary */ + /* FIXME: hard-coded dimensions here are just arbitrary. */ return WM_operator_props_dialog_popup(C, op, 200); } @@ -1088,7 +1110,11 @@ void OBJECT_OT_paths_calculate(wmOperatorType *ot) MAXFRAME / 2.0); } -/* --------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Update Motion Paths Operator + * \{ */ static bool object_update_paths_poll(bContext *C) { @@ -1132,7 +1158,11 @@ void OBJECT_OT_paths_update(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* --------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Motion Paths Operator + * \{ */ /* Helper for ED_objects_clear_paths() */ static void object_clear_mpath(Object *ob) @@ -1151,14 +1181,14 @@ static void object_clear_mpath(Object *ob) void ED_objects_clear_paths(bContext *C, bool only_selected) { if (only_selected) { - /* loop over all selected + sedtiable objects in scene */ + /* Loop over all selected + editable objects in scene. */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { object_clear_mpath(ob); } CTX_DATA_END; } else { - /* loop over all edtiable objects in scene */ + /* Loop over all editable objects in scene. */ CTX_DATA_BEGIN (C, Object *, ob, editable_objects) { object_clear_mpath(ob); } @@ -1210,13 +1240,17 @@ void OBJECT_OT_paths_clear(wmOperatorType *ot) RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); } -/* --------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Update Motion Paths Range from Scene Operator + * \{ */ static int object_update_paths_range_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - /* loop over all edtiable objects in scene */ + /* Loop over all editable objects in scene. */ CTX_DATA_BEGIN (C, Object *, ob, editable_objects) { /* use Preview Range or Full Frame Range - whichever is in use */ ob->avs.path_sf = PSFRA; @@ -1246,63 +1280,99 @@ void OBJECT_OT_paths_range_update(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** Smooth/Flat *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Shade Smooth/Flat Operator + * \{ */ static int shade_smooth_exec(bContext *C, wmOperator *op) { - ID *data; - Curve *cu; - Nurb *nu; - int clear = (STREQ(op->idname, "OBJECT_OT_shade_flat")); - bool done = false, linked_data = false; + const bool use_smooth = STREQ(op->idname, "OBJECT_OT_shade_smooth"); + bool changed_multi = false; + bool has_linked_data = false; - CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { - data = ob->data; + ListBase ctx_objects = {NULL, NULL}; + CollectionPointerLink ctx_ob_single_active = {NULL}; + + /* For modes that only use an active object, don't handle the whole selection. */ + { + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obact = OBACT(view_layer); + if (obact && ((obact->mode & OB_MODE_ALL_PAINT))) { + ctx_ob_single_active.ptr.data = obact; + BLI_addtail(&ctx_objects, &ctx_ob_single_active); + } + } + + if (ctx_objects.first != &ctx_ob_single_active) { + CTX_data_selected_editable_objects(C, &ctx_objects); + } + + for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) { + Object *ob = ctx_ob->ptr.data; + ID *data = ob->data; + if (data != NULL) { + data->tag |= LIB_TAG_DOIT; + } + } + + for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) { + /* Always un-tag all object data-blocks irrespective of our ability to operate on them. */ + Object *ob = ctx_ob->ptr.data; + ID *data = ob->data; + if ((data == NULL) || ((data->tag & LIB_TAG_DOIT) == 0)) { + continue; + } + data->tag &= ~LIB_TAG_DOIT; + /* Finished un-tagging, continue with regular logic. */ if (data && ID_IS_LINKED(data)) { - linked_data = true; + has_linked_data = true; continue; } + bool changed = false; if (ob->type == OB_MESH) { - BKE_mesh_smooth_flag_set(ob->data, !clear); - + BKE_mesh_smooth_flag_set(ob->data, use_smooth); BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - - done = true; + changed = true; } else if (ELEM(ob->type, OB_SURF, OB_CURVE)) { - cu = ob->data; + BKE_curve_smooth_flag_set(ob->data, use_smooth); + changed = true; + } - for (nu = cu->nurb.first; nu; nu = nu->next) { - if (!clear) { - nu->flag |= ME_SMOOTH; - } - else { - nu->flag &= ~ME_SMOOTH; - } - } + if (changed) { + changed_multi = true; DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - - done = true; } } - CTX_DATA_END; - if (linked_data) { + if (ctx_objects.first != &ctx_ob_single_active) { + BLI_freelistN(&ctx_objects); + } + + if (has_linked_data) { BKE_report(op->reports, RPT_WARNING, "Can't edit linked mesh or curve data"); } - return (done) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } static bool shade_poll(bContext *C) { - return (CTX_data_edit_object(C) == NULL); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obact = OBACT(view_layer); + if (obact != NULL) { + /* Doesn't handle edit-data, sculpt dynamic-topology, or their undo systems. */ + if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT)) { + return false; + } + } + return true; } void OBJECT_OT_shade_flat(wmOperatorType *ot) @@ -1335,7 +1405,11 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Mode Set Operator + * \{ */ static const EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *UNUSED(ptr), @@ -1516,6 +1590,12 @@ void OBJECT_OT_mode_set_with_submode(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Link/Move to Collection Operator + * \{ */ + static ListBase selected_objects_get(bContext *C) { ListBase objects = {NULL}; @@ -1856,3 +1936,5 @@ void OBJECT_OT_link_to_collection(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); ot->prop = prop; } + +/** \} */ diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index a24f3ba2269..1b662ccc389 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -142,10 +142,11 @@ static void object_force_modifier_bind_simple_options(Depsgraph *depsgraph, md_eval->mode = mode; } -/** Add a modifier to given object, including relevant extra processing needed by some physics - * types (particles, simulations...). +/** + * Add a modifier to given object, including relevant extra processing needed by some physics types + * (particles, simulations...). * - * \param scene is only used to set current frame in some cases, and may be NULL. + * \param scene: is only used to set current frame in some cases, and may be NULL. */ ModifierData *ED_object_modifier_add( ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type) @@ -2455,7 +2456,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) * No drivers or other modifier parameters. */ /* TODO(sergey): This operates on an original data, so no flush is needed. However, baking * usually should happen on an evaluated objects, so this seems to be deeper issue here. */ - BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata((ID *)ob, ob->adt, f, ADT_RECALC_ANIM, false); och->time[i] = omd->time; i++; diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index b3d76382d26..1eede3e5197 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1608,6 +1608,7 @@ struct XFormAxisItem { float rot_mat[3][3]; void *obtfm; float xform_dist; + bool is_z_flip; #ifdef USE_RELATIVE_ROTATION /* use when translating multiple */ @@ -1730,11 +1731,16 @@ static void object_apply_location(Object *ob, const float loc[3]) static void object_orient_to_location(Object *ob, const float rot_orig[3][3], const float axis[3], - const float location[3]) + const float location[3], + const bool z_flip) { float delta[3]; sub_v3_v3v3(delta, ob->obmat[3], location); if (normalize_v3(delta) != 0.0f) { + if (z_flip) { + negate_v3(delta); + } + if (len_squared_v3v3(delta, axis) > FLT_EPSILON) { float delta_rot[3][3]; float final_rot[3][3]; @@ -1840,6 +1846,11 @@ static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, cons for (int i = 0; i < xfd->object_data_len; i++, item++) { item->obtfm = BKE_object_tfm_backup(item->ob); BKE_object_rot_to_mat3(item->ob, item->rot_mat, true); + + /* Detect negative scale matrix. */ + float full_mat3[3][3]; + BKE_object_to_mat3(item->ob, full_mat3); + item->is_z_flip = dot_v3v3(item->rot_mat[2], full_mat3[2]) < 0.0f; } } @@ -1974,7 +1985,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const } object_orient_to_location( - item->ob, item->rot_mat, item->rot_mat[2], location_world); + item->ob, item->rot_mat, item->rot_mat[2], location_world, item->is_z_flip); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob); } if (normal_found) { @@ -1986,7 +1997,8 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const else { struct XFormAxisItem *item = xfd->object_data; for (int i = 0; i < xfd->object_data_len; i++, item++) { - object_orient_to_location(item->ob, item->rot_mat, item->rot_mat[2], location_world); + object_orient_to_location( + item->ob, item->rot_mat, item->rot_mat[2], location_world, item->is_z_flip); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob); } xfd->prev.is_normal_valid = false; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 75ae0299318..3ce5aeedae8 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -4084,7 +4084,6 @@ typedef struct BrushAddCountIterData { short size; float imat[4][4]; ParticleData *add_pars; - int num_added; } BrushAddCountIterData; typedef struct BrushAddCountIterTLSData { @@ -4176,12 +4175,19 @@ static void brush_add_count_iter(void *__restrict iter_data_v, } } -static void brush_add_count_iter_finalize(void *__restrict userdata_v, - void *__restrict userdata_chunk_v) +static void brush_add_count_iter_reduce(const void *__restrict UNUSED(userdata), + void *__restrict join_v, + void *__restrict chunk_v) +{ + BrushAddCountIterTLSData *join = (BrushAddCountIterTLSData *)join_v; + BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)chunk_v; + join->num_added += tls->num_added; +} + +static void brush_add_count_iter_free(const void *__restrict UNUSED(userdata_v), + void *__restrict chunk_v) { - BrushAddCountIterData *iter_data = (BrushAddCountIterData *)userdata_v; - BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)userdata_chunk_v; - iter_data->num_added += tls->num_added; + BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)chunk_v; if (tls->rng != NULL) { BLI_rng_free(tls->rng); } @@ -4245,7 +4251,6 @@ static int brush_add(const bContext *C, PEData *data, short number) iter_data.number = number; iter_data.size = size; iter_data.add_pars = add_pars; - iter_data.num_added = 0; copy_m4_m4(iter_data.imat, imat); BrushAddCountIterTLSData tls = {NULL}; @@ -4255,13 +4260,14 @@ static int brush_add(const bContext *C, PEData *data, short number) settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; settings.userdata_chunk = &tls; settings.userdata_chunk_size = sizeof(BrushAddCountIterTLSData); - settings.func_finalize = brush_add_count_iter_finalize; + settings.func_reduce = brush_add_count_iter_reduce; + settings.func_free = brush_add_count_iter_free; BLI_task_parallel_range(0, number, &iter_data, brush_add_count_iter, &settings); /* Convert add_parse to a dense array, where all new particles are in the * beginning of the array. */ - n = iter_data.num_added; + n = tls.num_added; for (int current_iter = 0, new_index = 0; current_iter < number; current_iter++) { if (add_pars[current_iter].num == DMCACHE_NOTFOUND) { continue; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 49838b62b71..69cfe72308f 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2532,7 +2532,6 @@ void ED_region_panels_layout_ex(const bContext *C, v2d->scroll |= (V2D_SCROLL_BOTTOM); v2d->scroll &= ~(V2D_SCROLL_RIGHT); } - const int scroll = v2d->scroll; /* collect categories */ if (use_category_tabs) { @@ -2642,16 +2641,6 @@ void ED_region_panels_layout_ex(const bContext *C, /* this also changes the 'cur' */ UI_view2d_totRect_set(v2d, x, y); - if (scroll != v2d->scroll) { - /* Note: this code scales fine, but because of rounding differences, positions of elements - * flip +1 or -1 pixel compared to redoing the entire layout again. - * Leaving in commented code for future tests */ -#if 0 - UI_panels_scale(region, BLI_rctf_size_x(&v2d->cur)); - break; -#endif - } - if (use_category_tabs) { region->runtime.category = category; } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 452984f2333..b66964d0e7f 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -3870,7 +3870,6 @@ static int region_quadview_exec(bContext *C, wmOperator *op) rv3d->viewlock_quad = RV3D_VIEWLOCK_INIT; rv3d->viewlock = 0; - rv3d->rflag &= ~RV3D_CLIPPING; /* Accumulate locks, in case they're mixed. */ for (region_iter = area->regionbase.first; region_iter; region_iter = region_iter->next) { diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 1e1d4373fea..d7d85112497 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -127,6 +127,7 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce simage->zoom = 1.0f; simage->lock = true; simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS; + simage->uv_opacity = 1.0f; BKE_imageuser_default(&simage->iuser); simage->iuser.flag = IMA_SHOW_STEREO | IMA_ANIM_ALWAYS; diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index 4cf67dddb57..8fc343a9ed4 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -84,7 +84,7 @@ static void node_sockets_panel(const bContext *C, Panel *panel) split = uiLayoutSplit(layout, 0.35f, false); uiItemL(split, name, ICON_NONE); - uiTemplateNodeLink(split, ntree, node, sock); + uiTemplateNodeLink(split, (bContext *)C, ntree, node, sock); } } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 0552660b9bf..bd8950c5085 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -94,23 +94,11 @@ void ED_node_tree_update(const bContext *C) static bNodeTree *node_tree_from_ID(ID *id) { if (id) { - short idtype = GS(id->name); - - switch (idtype) { - case ID_NT: - return (bNodeTree *)id; - case ID_MA: - return ((Material *)id)->nodetree; - case ID_LA: - return ((Light *)id)->nodetree; - case ID_WO: - return ((World *)id)->nodetree; - case ID_SCE: - return ((Scene *)id)->nodetree; - case ID_TE: - return ((Tex *)id)->nodetree; - case ID_LS: - return ((FreestyleLineStyle *)id)->nodetree; + if (GS(id->name) == ID_NT) { + return (bNodeTree *)id; + } + else { + return ntreeFromID(id); } } @@ -719,39 +707,19 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) #define MARKER_SHAPE_CIRCLE 0x2 #define MARKER_SHAPE_INNER_DOT 0x10 -static void node_socket_draw(const bContext *C, - bNodeTree *ntree, - PointerRNA node_ptr, - bNodeSocket *sock, +static void node_socket_draw(const bNodeSocket *sock, + const float color[4], + const float color_outline[4], + float size, + int locx, + int locy, uint pos_id, uint col_id, uint shape_id, uint size_id, - uint outline_col_id, - float size, - bool selected) + uint outline_col_id) { - PointerRNA ptr; - float color[4]; - float outline_color[4]; - uint flags = 0; - - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); - sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color); - - bNode *node = node_ptr.data; - if (node->flag & NODE_MUTED) { - color[3] *= 0.25f; - } - - if (selected) { - UI_GetThemeColor4fv(TH_TEXT_HI, outline_color); - outline_color[3] = 0.9f; - } - else { - copy_v4_fl(outline_color, 0.0f); - outline_color[3] = 0.6f; - } + int flags; /* sets shape flags */ switch (sock->display_shape) { @@ -780,8 +748,120 @@ static void node_socket_draw(const bContext *C, immAttr4fv(col_id, color); immAttr1u(shape_id, flags); immAttr1f(size_id, size); - immAttr4fv(outline_col_id, outline_color); - immVertex2f(pos_id, sock->locx, sock->locy); + immAttr4fv(outline_col_id, color_outline); + immVertex2f(pos_id, locx, locy); +} + +static void node_socket_outline_color_get(bool selected, float r_outline_color[4]) +{ + if (selected) { + UI_GetThemeColor4fv(TH_TEXT_HI, r_outline_color); + r_outline_color[3] = 0.9f; + } + else { + copy_v4_fl(r_outline_color, 0.0f); + r_outline_color[3] = 0.6f; + } +} + +/* Usual convention here would be node_socket_get_color(), but that's already used (for setting a + * color property socket). */ +void node_socket_color_get( + bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, bNodeSocket *sock, float r_color[4]) +{ + PointerRNA ptr; + + BLI_assert(RNA_struct_is_a(node_ptr->type, &RNA_Node)); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + + sock->typeinfo->draw_color(C, &ptr, node_ptr, r_color); + + bNode *node = node_ptr->data; + if (node->flag & NODE_MUTED) { + r_color[3] *= 0.25f; + } +} + +static void node_socket_draw_nested(const bContext *C, + bNodeTree *ntree, + PointerRNA *node_ptr, + bNodeSocket *sock, + uint pos_id, + uint col_id, + uint shape_id, + uint size_id, + uint outline_col_id, + float size, + bool selected) +{ + float color[4]; + float outline_color[4]; + + node_socket_color_get((bContext *)C, ntree, node_ptr, sock, color); + node_socket_outline_color_get(selected, outline_color); + + node_socket_draw(sock, + color, + outline_color, + size, + sock->locx, + sock->locy, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id); +} + +/** + * Draw a single node socket at default size. + * \note this is only called from external code, internally #node_socket_draw_nested() is used for + * optimized drawing of multiple/all sockets of a node. + */ +void ED_node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], float scale) +{ + const float size = 2.25f * NODE_SOCKSIZE * scale; + rcti draw_rect = *rect; + float outline_color[4] = {0}; + + node_socket_outline_color_get(sock->flag & SELECT, outline_color); + + BLI_rcti_resize(&draw_rect, size, size); + + GPUVertFormat *format = immVertexFormat(); + uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + uint shape_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT); + uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + uint outline_col_id = GPU_vertformat_attr_add( + format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + + gpuPushAttr(GPU_BLEND_BIT); + GPU_blend(true); + GPU_program_point_size(true); + + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + immUniform1f("outline_scale", 0.7f); + immUniform2f("ViewportSize", -1.0f, -1.0f); + + /* Single point */ + immBegin(GPU_PRIM_POINTS, 1); + node_socket_draw(sock, + color, + outline_color, + BLI_rcti_size_y(&draw_rect), + BLI_rcti_cent_x(&draw_rect), + BLI_rcti_cent_y(&draw_rect), + pos_id, + col_id, + shape_id, + size_id, + outline_col_id); + immEnd(); + + immUnbindProgram(); + GPU_program_point_size(false); + gpuPopAttr(); } /* ************** Socket callbacks *********** */ @@ -974,17 +1054,17 @@ void node_draw_sockets(View2D *v2d, continue; } - node_socket_draw(C, - ntree, - node_ptr, - sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_socket_draw_nested(C, + ntree, + &node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); } /* socket outputs */ @@ -999,17 +1079,17 @@ void node_draw_sockets(View2D *v2d, continue; } - node_socket_draw(C, - ntree, - node_ptr, - sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_socket_draw_nested(C, + ntree, + &node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); } } @@ -1032,17 +1112,17 @@ void node_draw_sockets(View2D *v2d, continue; } if (select_all || (sock->flag & SELECT)) { - node_socket_draw(C, - ntree, - node_ptr, - sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_socket_draw_nested(C, + ntree, + &node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); if (--selected_input_len == 0) { break; /* stop as soon as last one is drawn */ } @@ -1057,17 +1137,17 @@ void node_draw_sockets(View2D *v2d, continue; } if (select_all || (sock->flag & SELECT)) { - node_socket_draw(C, - ntree, - node_ptr, - sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_socket_draw_nested(C, + ntree, + &node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); if (--selected_output_len == 0) { break; /* stop as soon as last one is drawn */ } diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 42439e88c96..04186c3a727 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -38,6 +38,7 @@ struct bContext; struct bNode; struct bNodeLink; struct bNodeSocket; +struct wmGizmoGroupType; struct wmKeyConfig; struct wmWindow; @@ -77,6 +78,11 @@ void node_draw_sockets(struct View2D *v2d, void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node); int node_select_area_default(struct bNode *node, int x, int y); int node_tweak_area_default(struct bNode *node, int x, int y); +void node_socket_color_get(struct bContext *C, + struct bNodeTree *ntree, + struct PointerRNA *node_ptr, + struct bNodeSocket *sock, + float r_color[4]); void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree); void node_draw_nodetree(const struct bContext *C, struct ARegion *region, @@ -122,7 +128,7 @@ void NODE_OT_find_node(struct wmOperatorType *ot); /* node_view.c */ int space_node_view_flag(struct bContext *C, - SpaceNode *snode, + struct SpaceNode *snode, ARegion *region, const int node_flag, const int smooth_viewtx); @@ -196,7 +202,7 @@ void NODE_OT_detach(struct wmOperatorType *ot); void NODE_OT_link_viewer(struct wmOperatorType *ot); -void NODE_OT_insert_offset(wmOperatorType *ot); +void NODE_OT_insert_offset(struct wmOperatorType *ot); /* node_edit.c */ void snode_notify(struct bContext *C, struct SpaceNode *snode); @@ -207,8 +213,8 @@ void snode_update(struct SpaceNode *snode, struct bNode *node); bool composite_node_active(struct bContext *C); bool composite_node_editable(struct bContext *C); -int node_has_hidden_sockets(bNode *node); -void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set); +int node_has_hidden_sockets(struct bNode *node); +void node_set_hidden_sockets(struct SpaceNode *snode, bNode *node, int set); int node_render_changed_exec(bContext *, struct wmOperator *); int node_find_indicated_socket(struct SpaceNode *snode, struct bNode **nodep, diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 7d4095326f8..91fe6a97432 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -45,6 +45,7 @@ #include "UI_interface.h" #include "ED_node.h" /* own include */ +#include "node_intern.h" #include "ED_undo.h" @@ -662,17 +663,23 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_ ui_node_menu_column(arg, NODE_CLASS_GROUP, N_("Group")); } -void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSocket *sock) +void uiTemplateNodeLink( + uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock) { uiBlock *block = uiLayoutGetBlock(layout); NodeLinkArg *arg; uiBut *but; + float socket_col[4]; arg = MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg"); arg->ntree = ntree; arg->node = node; arg->sock = sock; + PointerRNA node_ptr; + RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr); + node_socket_color_get(C, ntree, &node_ptr, sock, socket_col); + UI_block_layout_set_current(block, layout); if (sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) { @@ -687,8 +694,9 @@ void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSo } UI_but_type_set_menu_from_pulldown(but); + UI_but_node_link_set(but, sock, socket_col); + UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); - but->flag |= UI_BUT_NODE_LINK; but->poin = (char *)but; but->func_argN = arg; @@ -798,7 +806,7 @@ static void ui_node_draw_input( } else if (lnode) { /* input linked to a node */ - uiTemplateNodeLink(split, ntree, node, input); + uiTemplateNodeLink(split, C, ntree, node, input); if (depth == 0 || !(input->flag & SOCK_COLLAPSED)) { if (depth == 0) { @@ -809,6 +817,10 @@ static void ui_node_draw_input( } } else { + row = uiLayoutRow(split, true); + + uiTemplateNodeLink(row, C, ntree, node, input); + /* input not linked, show value */ if (!(input->flag & SOCK_HIDE_VALUE)) { switch (input->type) { @@ -817,25 +829,15 @@ static void ui_node_draw_input( case SOCK_BOOLEAN: case SOCK_RGBA: case SOCK_STRING: - row = uiLayoutRow(split, true); uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE); break; case SOCK_VECTOR: - row = uiLayoutRow(split, false); + uiItemS(row); col = uiLayoutColumn(row, false); uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE); break; - - default: - row = uiLayoutRow(split, false); - break; } } - else { - row = uiLayoutRow(split, false); - } - - uiTemplateNodeLink(row, ntree, node, input); } /* clear */ diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index b06bc7ad8b7..243a6e193eb 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -447,7 +447,6 @@ static void draw_histogram_bar(ImBuf *ibuf, int x, float val, int col) typedef struct MakeHistogramViewData { const ImBuf *ibuf; - uint32_t (*bins)[HIS_STEPS]; } MakeHistogramViewData; static void make_histogram_view_from_ibuf_byte_fn(void *__restrict userdata, @@ -469,17 +468,16 @@ static void make_histogram_view_from_ibuf_byte_fn(void *__restrict userdata, } } -static void make_histogram_view_from_ibuf_finalize(void *__restrict userdata, - void *__restrict userdata_chunk) +static void make_histogram_view_from_ibuf_reduce(const void *__restrict UNUSED(userdata), + void *__restrict chunk_join, + void *__restrict chunk) { - MakeHistogramViewData *data = userdata; - uint32_t(*bins)[HIS_STEPS] = data->bins; - - uint32_t(*cur_bins)[HIS_STEPS] = userdata_chunk; + uint32_t(*join_bins)[HIS_STEPS] = chunk_join; + uint32_t(*bins)[HIS_STEPS] = chunk; for (int j = 3; j--;) { for (int i = 0; i < HIS_STEPS; i++) { - bins[j][i] += cur_bins[j][i]; + join_bins[j][i] += bins[j][i]; } } } @@ -496,14 +494,13 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) MakeHistogramViewData data = { .ibuf = ibuf, - .bins = bins, }; TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (ibuf->y >= 256); settings.userdata_chunk = bins; settings.userdata_chunk_size = sizeof(bins); - settings.func_finalize = make_histogram_view_from_ibuf_finalize; + settings.func_reduce = make_histogram_view_from_ibuf_reduce; BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_byte_fn, &settings); nr = nb = ng = 0; @@ -582,14 +579,13 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf) MakeHistogramViewData data = { .ibuf = ibuf, - .bins = bins, }; TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (ibuf->y >= 256); settings.userdata_chunk = bins; settings.userdata_chunk_size = sizeof(bins); - settings.func_finalize = make_histogram_view_from_ibuf_finalize; + settings.func_reduce = make_histogram_view_from_ibuf_reduce; BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_float_fn, &settings); nr = nb = ng = 0; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 701e068d3fa..f4ea0beadb6 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -677,6 +677,10 @@ enum { T_MODAL_CURSOR_SET = 1 << 26, T_CLNOR_REBUILD = 1 << 27, + + /* Special Aftertrans. */ + T_AUTOMERGE = 1 << 28, + T_AUTOSPLIT = 1 << 29, }; /** #TransInfo.modifiers */ diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 0beacf1244a..f75c2c52756 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -1843,8 +1843,8 @@ static void special_aftertrans_update__node(bContext *C, TransInfo *t) static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) { - /* so automerge supports mirror */ - if ((t->scene->toolsettings->automerge) && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) { + bool use_automerge = (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0; + if (use_automerge && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); @@ -1870,14 +1870,12 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) hflag = BM_ELEM_SELECT; } - if (t->scene->toolsettings->automerge & AUTO_MERGE) { - if (t->scene->toolsettings->automerge & AUTO_MERGE_AND_SPLIT) { - EDBM_automerge_and_split( - tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit); - } - else { - EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit); - } + if (t->flag & T_AUTOSPLIT) { + EDBM_automerge_and_split( + tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit); + } + else { + EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit); } /* Special case, this is needed or faces won't re-select. diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 91b8b1ff657..17d210f57b9 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -609,9 +609,9 @@ void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, Object * /* TODO(germano): Realitve Mirror support */ } data->flag |= CONSTRAINT_IK_AUTO; - /* Add a temporary auto IK constraint here, as we will only temporarly active this targetless - * bone during transform. (Targetless IK constraints are treated as if they are disabled - * unless they are transformed) */ + /* Add a temporary auto IK constraint here, as we will only temporarily active this + * target-less bone during transform. (Target-less IK constraints are treated as if they are + * disabled unless they are transformed) */ add_temporary_ik_constraint(pchan, data); Main *bmain = CTX_data_main(t->context); update_deg_with_temporary_ik(bmain, ob); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 05318a5c1d3..485ceb2c209 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1763,6 +1763,24 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->options |= CTX_NO_PET; } + if (t->obedit_type == OB_MESH) { + if (op && (prop = RNA_struct_find_property(op->ptr, "use_automerge_and_split")) && + RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + t->flag |= T_AUTOMERGE | T_AUTOSPLIT; + } + } + else { + char automerge = t->scene->toolsettings->automerge; + if (automerge & AUTO_MERGE) { + t->flag |= T_AUTOMERGE; + if (automerge & AUTO_MERGE_AND_SPLIT) { + t->flag |= T_AUTOSPLIT; + } + } + } + } + // Mirror is not supported with PET, turn it off. #if 0 if (t->flag & T_PROP_EDIT) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 31b85cdf3a8..f8ac2a6ac09 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -705,6 +705,15 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation"); RNA_def_property_flag(prop, PROP_HIDDEN); } + + if (flags & P_POST_TRANSFORM) { + prop = RNA_def_boolean(ot->srna, + "use_automerge_and_split", + 0, + "Auto Merge & Split", + "Forces the use of Auto Merge & Split"); + RNA_def_property_flag(prop, PROP_HIDDEN); + } } static void TRANSFORM_OT_translate(struct wmOperatorType *ot) @@ -730,7 +739,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot) Transform_Properties(ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | - P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT); + P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT | P_POST_TRANSFORM); } static void TRANSFORM_OT_resize(struct wmOperatorType *ot) diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 6ea1bbbcc10..959ca1eeef1 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -306,6 +306,7 @@ static void draw_uvs(SpaceImage *sima, Object *ob_eval = batch->ob_eval; const ToolSettings *ts = scene->toolsettings; float col1[4], col2[4], col3[4], transparent[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + const float overlay_alpha = sima->uv_opacity; if (sima->flag & SI_DRAWSHADOW) { bool is_cage_like_final_meshes = false; @@ -346,7 +347,11 @@ static void draw_uvs(SpaceImage *sima, UI_GetThemeColor4fv(TH_FACE, col1); UI_GetThemeColor4fv(TH_FACE_SELECT, col2); UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, col3); - col3[3] *= 0.2; /* Simulate dithering */ + + col1[3] *= overlay_alpha; + col2[3] *= overlay_alpha; + col3[3] *= overlay_alpha; + GPU_batch_uniform_4fv(batch->faces, "faceColor", col1); GPU_batch_uniform_4fv(batch->faces, "selectColor", col2); GPU_batch_uniform_4fv(batch->faces, "activeColor", col3); @@ -372,9 +377,16 @@ static void draw_uvs(SpaceImage *sima, GPU_line_smooth(true); GPU_blend(true); } + else if (overlay_alpha < 1.0f) { + GPU_blend(true); + } + switch (sima->dt_uv) { case SI_UVDT_DASH: { - float dash_colors[2][4] = {{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}}; + float dash_colors[2][4] = { + {0.56f, 0.56f, 0.56f, overlay_alpha}, + {0.07f, 0.07f, 0.07f, overlay_alpha}, + }; float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -398,7 +410,8 @@ static void draw_uvs(SpaceImage *sima, * instead of modifying the provoking vert. */ glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - UI_GetThemeColor4fv(TH_EDGE_SELECT, col2); + UI_GetThemeColor3fv(TH_EDGE_SELECT, col2); + col2[3] = overlay_alpha; GPU_batch_program_set_builtin( batch->edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES); @@ -406,18 +419,19 @@ static void draw_uvs(SpaceImage *sima, if (sima->dt_uv == SI_UVDT_OUTLINE) { /* Black Outline. */ GPU_line_width(3.0f); - GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, 1.0f); - GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, 1.0f); + GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, overlay_alpha); + GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, overlay_alpha); GPU_batch_draw(batch->edges); - UI_GetThemeColor4fv(TH_WIRE_EDIT, col1); + UI_GetThemeColor3fv(TH_WIRE_EDIT, col1); } else if (sima->dt_uv == SI_UVDT_WHITE) { - copy_v4_fl4(col1, 1.0f, 1.0f, 1.0f, 1.0f); + copy_v3_fl3(col1, 1.0f, 1.0f, 1.0f); } else { - copy_v4_fl4(col1, 0.0f, 0.0f, 0.0f, 1.0f); + copy_v3_fl3(col1, 0.0f, 0.0f, 0.0f); } + col1[3] = overlay_alpha; /* Inner Line. Use depth test to insure selection is drawn on top. */ GPU_depth_test(true); @@ -435,6 +449,9 @@ static void draw_uvs(SpaceImage *sima, GPU_line_smooth(false); GPU_blend(false); } + else if (overlay_alpha < 1.0f) { + GPU_blend(false); + } } if (batch->verts || batch->facedots) { UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2); diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c index cb1cd9a6f6d..1caa88d18ae 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.c +++ b/source/blender/gpu/intern/gpu_shader_interface.c @@ -254,8 +254,12 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program) } /* TODO: reject DOUBLE gl_types */ - input->location = glGetAttribLocation(program, name); + /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */ + if (input->location == -1) { + MEM_freeN(input); + continue; + } shaderface->enabled_attr_mask |= (1 << input->location); diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index ed825db26ac..af98ac4411c 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -559,10 +559,10 @@ void GPU_viewport_colorspace_set(GPUViewport *viewport, { /** * HACK(fclem): We copy the settings here to avoid use after free if an update frees the scene - * and the viewport stays cached (see T75443). But this means the OCIO curvemapping caching - * (which is based on CurveMap pointer address) cannot operate correctly and it will create - * a different OCIO processor for each viewport. We try to only realloc the curvemap copy if - * needed to avoid uneeded cache invalidation. + * and the viewport stays cached (see T75443). But this means the OCIO curve-mapping caching + * (which is based on #CurveMap pointer address) cannot operate correctly and it will create + * a different OCIO processor for each viewport. We try to only reallocate the curve-map copy + * if needed to avoid unneeded cache invalidation. */ if (view_settings->curve_mapping) { if (viewport->view_settings.curve_mapping) { diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index d6d3628cc66..0565840b344 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -552,9 +552,9 @@ enum { /* RESET_NEVER tag data-block as needing an auto-override execution, if enabled. */ LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH = 1 << 17, - /* tag data-block has having an extra user. */ + /* tag data-block as having an extra user. */ LIB_TAG_EXTRAUSER = 1 << 2, - /* tag data-block has having actually increased usercount for the extra virtual user. */ + /* tag data-block as having actually increased usercount for the extra virtual user. */ LIB_TAG_EXTRAUSER_SET = 1 << 7, /* RESET_AFTER_USE tag newly duplicated/copied IDs. diff --git a/source/blender/makesdna/DNA_fluid_types.h b/source/blender/makesdna/DNA_fluid_types.h index bb85d8304ec..166b3c22932 100644 --- a/source/blender/makesdna/DNA_fluid_types.h +++ b/source/blender/makesdna/DNA_fluid_types.h @@ -541,6 +541,8 @@ enum { FLUID_FLOW_USE_INFLOW = (1 << 5), /* Control how to initialize flow objects. */ FLUID_FLOW_USE_PLANE_INIT = (1 << 6), + /* Notify domain objects about state change (invalidate cache). */ + FLUID_FLOW_NEEDS_UPDATE = (1 << 7), }; typedef struct FluidFlowSettings { @@ -614,6 +616,8 @@ enum { FLUID_EFFECTOR_USE_EFFEC = (1 << 1), /* Control how to initialize flow objects. */ FLUID_EFFECTOR_USE_PLANE_INIT = (1 << 2), + /* Notify domain objects about state change (invalidate cache). */ + FLUID_EFFECTOR_NEEDS_UPDATE = (1 << 3), }; /* Collision objects (filled with smoke). */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 648d35c9a2d..90af60447fe 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -1075,7 +1075,9 @@ typedef struct SpaceImage { int flag; char pixel_snap_mode; - char _pad2[3]; + char _pad2[7]; + + float uv_opacity; int tile_grid_shape[2]; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 7a09059e344..622222307c7 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -619,9 +619,8 @@ typedef struct UserDef_FileSpaceData { typedef struct UserDef_Experimental { char use_undo_legacy; - char use_menu_search; /** `makesdna` does not allow empty structs. */ - char _pad0[6]; + char _pad0[7]; } UserDef_Experimental; #define USER_EXPERIMENTAL_TEST(userdef, member) \ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 31d1ed54fa1..26773e59feb 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -930,10 +930,6 @@ void RNA_property_update_main(struct Main *bmain, PropertyRNA *prop); bool RNA_property_update_check(struct PropertyRNA *prop); -void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop); -void RNA_property_update_cache_flush(struct Main *bmain, struct Scene *scene); -void RNA_property_update_cache_free(void); - /* Property Data */ bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index b56a18c18a9..85892758a88 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -98,8 +98,6 @@ void RNA_exit(void) { StructRNA *srna; - RNA_property_update_cache_free(); - for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) { if (srna->cont.prophash) { BLI_ghash_free(srna->cont.prophash, NULL, NULL); @@ -2308,115 +2306,6 @@ void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, Proper rna_property_update(NULL, bmain, scene, ptr, prop); } -/* RNA Updates Cache ------------------------ */ -/* Overview of RNA Update cache system: - * - * RNA Update calls need to be cached in order to maintain reasonable performance - * of the animation system (i.e. maintaining a somewhat interactive framerate) - * while still allowing updates to be called (necessary in particular for modifier - * property updates to actually work). - * - * The cache is structured with a dual-layer structure - * - L1 = PointerRNA used as key; owner_id is used (it should always be defined, - * and most updates end up using just that anyways) - * - L2 = Update functions to be called on those PointerRNA's - */ - -/* cache element */ -typedef struct tRnaUpdateCacheElem { - struct tRnaUpdateCacheElem *next, *prev; - - PointerRNA ptr; /* L1 key - id as primary, data secondary/ignored? */ - ListBase L2Funcs; /* L2 functions (LinkData<RnaUpdateFuncRef>) */ -} tRnaUpdateCacheElem; - -/* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */ -static ListBase rna_updates_cache = {NULL, NULL}; - -/* ........................... */ - -void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop) -{ - const bool is_rna = (prop->magic == RNA_MAGIC); - tRnaUpdateCacheElem *uce = NULL; - UpdateFunc fn = NULL; - LinkData *ld; - - /* sanity check */ - if (NULL == ptr) { - return; - } - - prop = rna_ensure_property(prop); - - /* we can only handle update calls with no context args for now (makes animsys updates easier) */ - if ((is_rna == false) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE)) { - return; - } - fn = prop->update; - - /* find cache element for which key matches... */ - for (uce = rna_updates_cache.first; uce; uce = uce->next) { - /* Just match by id only for now, - * since most update calls that we'll encounter only really care about this. */ - /* TODO: later, the cache might need to have some nesting on L1 to cope better - * with these problems + some tagging to indicate we need this */ - if (uce->ptr.owner_id == ptr->owner_id) { - break; - } - } - if (uce == NULL) { - /* create new instance */ - uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem"); - BLI_addtail(&rna_updates_cache, uce); - - /* copy pointer */ - RNA_pointer_create(ptr->owner_id, ptr->type, ptr->data, &uce->ptr); - } - - /* check on the update func */ - for (ld = uce->L2Funcs.first; ld; ld = ld->next) { - /* stop on match - function already cached */ - if (fn == ld->data) { - return; - } - } - /* else... if still here, we need to add it */ - BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn)); -} - -void RNA_property_update_cache_flush(Main *bmain, Scene *scene) -{ - tRnaUpdateCacheElem *uce; - - /* TODO: should we check that bmain and scene are valid? The above stuff doesn't! */ - - /* execute the cached updates */ - for (uce = rna_updates_cache.first; uce; uce = uce->next) { - LinkData *ld; - - for (ld = uce->L2Funcs.first; ld; ld = ld->next) { - UpdateFunc fn = (UpdateFunc)ld->data; - fn(bmain, scene, &uce->ptr); - } - } -} - -void RNA_property_update_cache_free(void) -{ - tRnaUpdateCacheElem *uce, *ucn; - - for (uce = rna_updates_cache.first; uce; uce = ucn) { - ucn = uce->next; - - /* free L2 cache */ - BLI_freelistN(&uce->L2Funcs); - - /* remove self */ - BLI_freelinkN(&rna_updates_cache, uce); - } -} - /* ---------------------------------------------------------------------- */ /* Property Data */ @@ -5785,10 +5674,10 @@ static char *rna_idp_path(PointerRNA *ptr, } /** - * Find the path from the structure referenced by the pointer to the IDProperty object. + * Find the path from the structure referenced by the pointer to the #IDProperty object. * - * \param ptr Reference to the object owning the custom property storage. - * \param needle Custom property object to find. + * \param ptr: Reference to the object owning the custom property storage. + * \param needle: Custom property object to find. * \return Relative path or NULL. */ char *RNA_path_from_struct_to_idproperty(PointerRNA *ptr, IDProperty *needle) diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index e087056e850..d89bdcd074f 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -73,44 +73,112 @@ static void rna_Fluid_dependency_update(Main *bmain, Scene *scene, PointerRNA *p DEG_relations_tag_update(bmain); } -static void rna_Fluid_resetCache(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_Fluid_datacache_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { +# ifdef WITH_FLUID FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; if (settings->mmd && settings->mmd->domain) { - settings->mmd->domain->cache_flag |= (FLUID_DOMAIN_OUTDATED_DATA | - FLUID_DOMAIN_OUTDATED_NOISE | - FLUID_DOMAIN_OUTDATED_MESH | - FLUID_DOMAIN_OUTDATED_PARTICLES); + Object *ob = (Object *)ptr->owner_id; + int cache_map = (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE | + FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES); + BKE_fluid_cache_free(settings, ob, cache_map); } +# endif DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); } -static void rna_Fluid_reset(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_Fluid_noisecache_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ +# ifdef WITH_FLUID + FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; + if (settings->mmd && settings->mmd->domain) { + Object *ob = (Object *)ptr->owner_id; + int cache_map = FLUID_DOMAIN_OUTDATED_NOISE; + BKE_fluid_cache_free(settings, ob, cache_map); + } +# endif + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); +} +static void rna_Fluid_meshcache_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { - # ifdef WITH_FLUID - { - FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; - BKE_fluid_modifier_reset(settings->mmd); + FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; + if (settings->mmd && settings->mmd->domain) { + Object *ob = (Object *)ptr->owner_id; + int cache_map = FLUID_DOMAIN_OUTDATED_MESH; + BKE_fluid_cache_free(settings, ob, cache_map); } # endif + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); +} +static void rna_Fluid_particlescache_reset(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *ptr) +{ +# ifdef WITH_FLUID + FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; + if (settings->mmd && settings->mmd->domain) { + Object *ob = (Object *)ptr->owner_id; + int cache_map = FLUID_DOMAIN_OUTDATED_PARTICLES; + BKE_fluid_cache_free(settings, ob, cache_map); + } +# endif + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); +} +static void rna_Fluid_guidingcache_reset(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *ptr) +{ +# ifdef WITH_FLUID + FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; + if (settings->mmd && settings->mmd->domain) { + Object *ob = (Object *)ptr->owner_id; + int cache_map = (FLUID_DOMAIN_OUTDATED_DATA | FLUID_DOMAIN_OUTDATED_NOISE | + FLUID_DOMAIN_OUTDATED_MESH | FLUID_DOMAIN_OUTDATED_PARTICLES | + FLUID_DOMAIN_OUTDATED_GUIDE); + BKE_fluid_cache_free(settings, ob, cache_map); + } +# endif + DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY); +} + +static void rna_Fluid_effector_reset(Main *bmain, Scene *scene, PointerRNA *ptr) +{ +# ifdef WITH_FLUID + FluidEffectorSettings *settings = (FluidEffectorSettings *)ptr->data; + settings->flags |= FLUID_EFFECTOR_NEEDS_UPDATE; +# endif + + rna_Fluid_update(bmain, scene, ptr); +} - rna_Fluid_resetCache(bmain, scene, ptr); +static void rna_Fluid_flow_reset(Main *bmain, Scene *scene, PointerRNA *ptr) +{ +# ifdef WITH_FLUID + FluidFlowSettings *settings = (FluidFlowSettings *)ptr->data; + settings->flags |= FLUID_FLOW_NEEDS_UPDATE; +# endif rna_Fluid_update(bmain, scene, ptr); } -static void rna_Fluid_reset_dependency(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_Fluid_domain_reset(Main *bmain, Scene *scene, PointerRNA *ptr) { +# ifdef WITH_FLUID FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; + BKE_fluid_modifier_reset(settings->mmd); +# endif + rna_Fluid_datacache_reset(bmain, scene, ptr); + rna_Fluid_update(bmain, scene, ptr); +} + +static void rna_Fluid_reset_dependency(Main *bmain, Scene *scene, PointerRNA *ptr) +{ # ifdef WITH_FLUID + FluidDomainSettings *settings = (FluidDomainSettings *)ptr->data; BKE_fluid_modifier_reset(settings->mmd); # endif - if (settings->mmd && settings->mmd->domain) { - settings->mmd->domain->point_cache[0]->flag |= PTCACHE_OUTDATED; - } - rna_Fluid_dependency_update(bmain, scene, ptr); } @@ -161,7 +229,7 @@ static void rna_Fluid_flip_parts_update(Main *bmain, Scene *scene, PointerRNA *p /* Only create a particle system in liquid domain mode. */ if (mmd->domain->type != FLUID_DOMAIN_TYPE_LIQUID) { - rna_Fluid_reset(bmain, scene, ptr); + rna_Fluid_domain_reset(bmain, scene, ptr); return; } @@ -1260,14 +1328,14 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "adapt_res"); RNA_def_property_range(prop, 0, 512); RNA_def_property_ui_text(prop, "Additional", "Maximum number of additional cells"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "adapt_margin", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "adapt_margin"); RNA_def_property_range(prop, 2, 24); RNA_def_property_ui_text( prop, "Margin", "Margin added around fluid to minimize boundary interference"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "adapt_threshold", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 1.0); @@ -1276,14 +1344,14 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Threshold", "Minimum amount of fluid a cell can contain before it is considered empty"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "use_adaptive_domain", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN); RNA_def_property_ui_text( prop, "Adaptive Domain", "Adapt simulation resolution and size to fluid"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); /* fluid domain options */ @@ -1297,44 +1365,44 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Resolution used for the fluid domain. Value corresponds to the longest domain side " "(resolution for other domain sides is calculated automatically)"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); prop = RNA_def_property(srna, "use_collision_border_front", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_FRONT); RNA_def_property_ui_text(prop, "Front", "Enable collisions with front domain border"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "use_collision_border_back", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_BACK); RNA_def_property_ui_text(prop, "Back", "Enable collisions with back domain border"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "use_collision_border_right", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_RIGHT); RNA_def_property_ui_text(prop, "Right", "Enable collisions with right domain border"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "use_collision_border_left", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_LEFT); RNA_def_property_ui_text(prop, "Left", "Enable collisions with left domain border"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "use_collision_border_top", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_TOP); RNA_def_property_ui_text(prop, "Top", "Enable collisions with top domain border"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "use_collision_border_bottom", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "border_collisions", FLUID_DOMAIN_BORDER_BOTTOM); RNA_def_property_ui_text(prop, "Bottom", "Enable collisions with bottom domain border"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION); RNA_def_property_float_sdna(prop, NULL, "gravity"); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -1000.1, 1000.1); RNA_def_property_ui_text(prop, "Gravity", "Gravity in X, Y and Z direction"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "domain_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); @@ -1347,7 +1415,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "delete_in_obstacle", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_DELETE_IN_OBSTACLE); RNA_def_property_ui_text(prop, "Clear In Obstacle", "Delete fluid inside obstacles"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); /* smoke domain options */ @@ -1359,7 +1427,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Buoyancy Density", "Buoyant force based on smoke density (higher value results in faster rising smoke)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "beta", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "beta"); @@ -1369,7 +1437,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Buoyancy Heat", "Buoyant force based on smoke heat (higher value results in faster rising smoke)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "dissolve_speed", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "diss_speed"); @@ -1379,23 +1447,23 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Dissolve Speed", "Determine how quickly the smoke dissolves (lower value makes smoke disappear faster)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "vorticity", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vorticity"); RNA_def_property_range(prop, 0.0, 4.0); RNA_def_property_ui_text(prop, "Vorticity", "Amount of turbulence and rotation in smoke"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "highres_sampling", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, smoke_highres_sampling_items); RNA_def_property_ui_text(prop, "Emitter", "Method for sampling the high resolution flow"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "use_dissolve_smoke", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_DISSOLVE); RNA_def_property_ui_text(prop, "Dissolve Smoke", "Let smoke disappear over time"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "use_dissolve_smoke_log", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_DISSOLVE_LOG); @@ -1403,7 +1471,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Logarithmic Dissolve", "Dissolve smoke in a logarithmic fashion. Dissolves quickly at first, but lingers longer"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); /* flame options */ @@ -1412,19 +1480,19 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.01, 2.0, 1.0, 5); RNA_def_property_ui_text( prop, "Speed", "Speed of the burning reaction (higher value results in smaller flames)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "flame_smoke", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 8.0); RNA_def_property_ui_range(prop, 0.0, 4.0, 1.0, 5); RNA_def_property_ui_text(prop, "Smoke", "Amount of smoke created by burning fuel"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "flame_vorticity", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 2.0); RNA_def_property_ui_range(prop, 0.0, 1.0, 1.0, 5); RNA_def_property_ui_text(prop, "Vorticity", "Additional vorticity for the flames"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "flame_ignition", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.5, 5.0); @@ -1433,7 +1501,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Minimum", "Minimum temperature of the flames (higher value results in faster rising flames)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "flame_max_temp", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 1.0, 10.0); @@ -1442,12 +1510,12 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Maximum", "Maximum temperature of the flames (higher value results in faster rising flames)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "flame_smoke_color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Smoke Color", "Color of smoke emitted from burning fuel"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); /* noise options */ @@ -1456,19 +1524,20 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 10.0); RNA_def_property_ui_range(prop, 0.0, 10.0, 1, 2); RNA_def_property_ui_text(prop, "Strength", "Strength of noise"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_noisecache_reset"); prop = RNA_def_property(srna, "noise_pos_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "noise_pos_scale"); RNA_def_property_range(prop, 0.0001, 10.0); RNA_def_property_ui_text( prop, "Scale", "Scale of noise (higher value results in larger vortices)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_noisecache_reset"); prop = RNA_def_property(srna, "noise_time_anim", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "noise_time_anim"); RNA_def_property_range(prop, 0.0001, 10.0); RNA_def_property_ui_text(prop, "Time", "Animation time of noise"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_noisecache_reset"); prop = RNA_def_property(srna, "noise_scale", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "noise_scale"); @@ -1479,7 +1548,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "The noise simulation is scaled up by this factor (compared to the " "base resolution of the domain)"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); prop = RNA_def_property(srna, "noise_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "noise_type"); @@ -1487,7 +1556,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Noise Method", "Noise method which is used during the high-res simulation"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); prop = RNA_def_property(srna, "use_noise", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_NOISE); @@ -1501,7 +1570,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "simulation_method"); RNA_def_property_enum_items(prop, simulation_methods); RNA_def_property_ui_text(prop, "Simulation Method", "Change the underlying simulation method"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); prop = RNA_def_property(srna, "flip_ratio", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 1.0); @@ -1510,18 +1579,18 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "FLIP Ratio", "PIC/FLIP Ratio. A value of 1.0 will result in a completely FLIP based simulation. Use a " "lower value for simulations which should produce smaller splashes"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "particle_randomness", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 10.0); RNA_def_property_ui_text(prop, "Randomness", "Randomness factor for particle sampling"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "particle_number", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 1, 5); RNA_def_property_ui_text( prop, "Number", "Particle number factor (higher value results in more particles)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "particle_min", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "particle_minimum"); @@ -1530,7 +1599,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Minimum", "Minimum number of particles per cell (ensures that each cell has at " "least this amount of particles)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "particle_max", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "particle_maximum"); @@ -1539,7 +1608,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Maximum", "Maximum number of particles per cell (ensures that each cell has at " "most this amount of particles)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "particle_radius", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 10.0); @@ -1547,7 +1616,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Radius", "Particle radius factor. Increase this value if the simulation appears " "to leak volume, decrease it if the simulation seems to gain volume"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "particle_band_width", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 1000.0); @@ -1555,7 +1624,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Width", "Particle (narrow) band width (higher value results in thicker band and more particles)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "use_flip_particles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "particle_type", FLUID_DOMAIN_PARTICLE_FLIP); @@ -1569,7 +1638,8 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Fractional Obstacles", "Fractional obstacles improve and smoothen the fluid-obstacle boundary"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "fractions_threshold", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.001, 1.0); @@ -1579,7 +1649,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Determines how much fluid is allowed in an obstacle cell " "(higher values will tag a boundary cell as an obstacle easier " "and reduce the boundary smoothening effect)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); /* diffusion options */ @@ -1588,7 +1658,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Use Diffusion", "Enable fluid diffusion settings (e.g. viscosity, surface tension)"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); prop = RNA_def_property(srna, "surface_tension", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 100.0); @@ -1596,7 +1666,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Tension", "Surface tension of liquid (higher value results in greater hydrophobic behaviour)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "viscosity_base", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "viscosity_base"); @@ -1605,7 +1675,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Viscosity Base", "Viscosity setting: value that is multiplied by 10 to the power of (exponent*-1)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "viscosity_exponent", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "viscosity_exponent"); @@ -1615,12 +1685,12 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Viscosity Exponent", "Negative exponent for the viscosity value (to simplify entering small values " "e.g. 5*10^-6)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "domain_size", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.001, 10000.0); RNA_def_property_ui_text(prop, "Meters", "Domain size in meters (longest domain side)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); /* mesh options options */ @@ -1630,7 +1700,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Upper Concavity", "Upper mesh concavity bound (high values tend to smoothen and fill out concave regions)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset"); prop = RNA_def_property(srna, "mesh_concave_lower", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 10.0); @@ -1638,17 +1708,17 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Lower Concavity", "Lower mesh concavity bound (high values tend to smoothen and fill out concave regions)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset"); prop = RNA_def_property(srna, "mesh_smoothen_pos", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 0, 100); RNA_def_property_ui_text(prop, "Smoothen Pos", "Positive mesh smoothening"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset"); prop = RNA_def_property(srna, "mesh_smoothen_neg", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 0, 100); RNA_def_property_ui_text(prop, "Smoothen Neg", "Negative mesh smoothening"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset"); prop = RNA_def_property(srna, "mesh_scale", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "mesh_scale"); @@ -1660,7 +1730,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "resolution of the domain). For best meshing, it is recommended to " "adjust the mesh particle radius alongside this value"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); prop = RNA_def_property(srna, "mesh_generator", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mesh_generator"); @@ -1689,7 +1759,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Caches velocities of mesh vertices. These will be used " "(automatically) when rendering with motion blur enabled"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); prop = RNA_def_property(srna, "mesh_particle_radius", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 10.0); @@ -1697,7 +1767,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Radius", "Particle radius factor (higher value results in larger (meshed) " "particles). Needs to be adjusted after changing the mesh scale"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset"); /* secondary particles options */ @@ -1709,7 +1779,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Minimum Wave Crest Potential", "Lower clamping threshold for marking fluid cells as wave crests " "(lower value results in more marked cells)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_potential_max_wavecrest", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sndparticle_tau_max_wc"); @@ -1719,7 +1789,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Maximum Wave Crest Potential", "Upper clamping threshold for marking fluid cells as wave crests " "(higher value results in less marked cells)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_potential_min_trappedair", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sndparticle_tau_min_ta"); @@ -1729,7 +1799,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Minimum Trapped Air Potential", "Lower clamping threshold for marking fluid cells where air is trapped " "(lower value results in more marked cells)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_potential_max_trappedair", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sndparticle_tau_max_ta"); @@ -1739,7 +1809,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Maximum Trapped Air Potential", "Upper clamping threshold for marking fluid cells where air is trapped " "(higher value results in less marked cells)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_potential_min_energy", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sndparticle_tau_min_k"); @@ -1750,7 +1820,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Minimum Kinetic Energy Potential", "Lower clamping threshold that indicates the fluid speed where cells start to emit " "particles (lower values result in generally more particles)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_potential_max_energy", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sndparticle_tau_max_k"); @@ -1761,7 +1831,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Maximum Kinetic Energy Potential", "Upper clamping threshold that indicates the fluid speed where cells no longer emit more " "particles (higher value results in generally less particles)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_sampling_wavecrest", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "sndparticle_k_wc"); @@ -1770,7 +1840,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Wave Crest Sampling", "Maximum number of particles generated per wave crest cell per frame"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_sampling_trappedair", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "sndparticle_k_ta"); @@ -1779,7 +1849,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Trapped Air Sampling", "Maximum number of particles generated per trapped air cell per frame"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_bubble_buoyancy", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sndparticle_k_b"); @@ -1789,7 +1859,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Bubble Buoyancy", "Amount of buoyancy force that rises bubbles (high value results in " "bubble movement mainly upwards)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_bubble_drag", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sndparticle_k_d"); @@ -1799,28 +1869,28 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Bubble Drag", "Amount of drag force that moves bubbles along with the fluid (high " "value results in bubble movement mainly along with the fluid)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_life_min", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sndparticle_l_min"); RNA_def_property_range(prop, 0.0, 10000.0); RNA_def_property_ui_range(prop, 0.0, 10000.0, 100.0, 1); RNA_def_property_ui_text(prop, "Minimum Lifetime", "Lowest possible particle lifetime"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_life_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sndparticle_l_max"); RNA_def_property_range(prop, 0.0, 10000.0); RNA_def_property_ui_range(prop, 0.0, 10000.0, 100.0, 1); RNA_def_property_ui_text(prop, "Maximum Lifetime", "Highest possible particle lifetime"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_boundary", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "sndparticle_boundary"); RNA_def_property_enum_items(prop, sndparticle_boundary_items); RNA_def_property_ui_text( prop, "Particles in Boundary", "How particles that left the domain are treated"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_combined_export", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "sndparticle_combined_export"); @@ -1839,7 +1909,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Potential Radius", "Radius to compute potential for each cell (higher values are slower " "but create smoother potential grids)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "sndparticle_update_radius", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "sndparticle_update_radius"); @@ -1849,7 +1919,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "Update Radius", "Radius to compute position update for each particle (higher values " "are slower but particles move less chaotic)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "particle_scale", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "particle_scale"); @@ -1860,7 +1930,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "The particle simulation is scaled up by this factor (compared to the " "base resolution of the domain)"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); prop = RNA_def_property(srna, "use_spray_particles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "particle_type", FLUID_DOMAIN_PARTICLE_SPRAY); @@ -1892,13 +1962,13 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "guide_alpha"); RNA_def_property_range(prop, 1.0, 100.0); RNA_def_property_ui_text(prop, "Weight", "Guiding weight (higher value results in greater lag)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_guidingcache_reset"); prop = RNA_def_property(srna, "guide_beta", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "guide_beta"); RNA_def_property_range(prop, 1, 50); RNA_def_property_ui_text(prop, "Size", "Guiding size (higher value results in larger vortices)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_guidingcache_reset"); prop = RNA_def_property(srna, "guide_vel_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "guide_vel_factor"); @@ -1907,7 +1977,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, "Velocity Factor", "Guiding velocity factor (higher value results in greater guiding velocities)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_guidingcache_reset"); prop = RNA_def_property(srna, "guide_source", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "guide_source"); @@ -1924,13 +1994,13 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "", "Use velocities from this object for the guiding effect (object needs " "to have fluid modifier and be of type domain))"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_update"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_guidingcache_reset"); prop = RNA_def_property(srna, "use_guide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_GUIDE); RNA_def_property_ui_text(prop, "Use Guiding", "Enable fluid guiding"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_guidingcache_reset"); /* cache options */ @@ -1968,7 +2038,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, NULL, "rna_Fluid_cachetype_mesh_set", "rna_Fluid_cachetype_mesh_itemf"); RNA_def_property_ui_text( prop, "File Format", "Select the file format to be used for caching surface data"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_meshcache_reset"); prop = RNA_def_property(srna, "cache_data_format", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "cache_data_format"); @@ -1977,7 +2047,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, NULL, "rna_Fluid_cachetype_data_set", "rna_Fluid_cachetype_volume_itemf"); RNA_def_property_ui_text( prop, "File Format", "Select the file format to be used for caching volumetric data"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "cache_particle_format", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "cache_particle_format"); @@ -1986,7 +2056,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, NULL, "rna_Fluid_cachetype_particle_set", "rna_Fluid_cachetype_particle_itemf"); RNA_def_property_ui_text( prop, "File Format", "Select the file format to be used for caching particle data"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_particlescache_reset"); prop = RNA_def_property(srna, "cache_noise_format", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "cache_noise_format"); @@ -1995,21 +2065,21 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop, NULL, "rna_Fluid_cachetype_noise_set", "rna_Fluid_cachetype_volume_itemf"); RNA_def_property_ui_text( prop, "File Format", "Select the file format to be used for caching noise data"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_noisecache_reset"); prop = RNA_def_property(srna, "cache_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "cache_type"); RNA_def_property_enum_items(prop, cache_types); RNA_def_property_enum_funcs(prop, NULL, "rna_Fluid_cachetype_set", NULL); RNA_def_property_ui_text(prop, "Type", "Change the cache type of the simulation"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_domain_reset"); prop = RNA_def_property(srna, "cache_directory", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_maxlength(prop, FILE_MAX); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Fluid_cache_directory_set"); RNA_def_property_string_sdna(prop, NULL, "cache_directory"); RNA_def_property_ui_text(prop, "Cache directory", "Directory that contains fluid cache files"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_update"); prop = RNA_def_property(srna, "is_cache_baking_data", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", FLUID_DOMAIN_BAKING_DATA); @@ -2069,7 +2139,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) "only needed if you plan to analyze the cache (e.g. view grids, velocity vectors, " "particles) in Mantaflow directly (outside of Blender) after baking the simulation"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); /* time options */ @@ -2077,19 +2147,19 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "time_scale"); RNA_def_property_range(prop, 0.0001, 10.0); RNA_def_property_ui_text(prop, "Time Scale", "Adjust simulation speed"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "cfl_condition", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "cfl_condition"); RNA_def_property_range(prop, 0.0, 10.0); RNA_def_property_ui_text( prop, "CFL", "Maximal velocity per cell (higher value results in greater timesteps)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "use_adaptive_timesteps", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_ADAPTIVE_TIME); RNA_def_property_ui_text(prop, "Use Adaptive Time Steps", ""); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "timesteps_min", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "timesteps_minimum"); @@ -2097,7 +2167,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0, 100, 1, -1); RNA_def_property_ui_text( prop, "Minimum", "Minimum number of simulation steps to perform for one frame"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "timesteps_max", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "timesteps_maximum"); @@ -2105,7 +2175,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0, 100, 1, -1); RNA_def_property_ui_text( prop, "Maximum", "Maximum number of simulation steps to perform for one frame"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); /* display settings */ @@ -2316,26 +2386,26 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 10); RNA_def_property_ui_range(prop, 0.0, 1.0, 1.0, 4); RNA_def_property_ui_text(prop, "Density", ""); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "smoke_color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "color"); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Smoke Color", "Color of smoke"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "fuel_amount", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 10); RNA_def_property_ui_range(prop, 0.0, 5.0, 1.0, 4); RNA_def_property_ui_text(prop, "Flame Rate", ""); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "temperature", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "temperature"); RNA_def_property_range(prop, -10, 10); RNA_def_property_ui_range(prop, -10, 10, 1, 1); RNA_def_property_ui_text(prop, "Temp. Diff.", "Temperature difference to ambient temperature"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "psys"); @@ -2349,13 +2419,13 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna) RNA_def_property_enum_items(prop, flow_type_items); RNA_def_property_enum_funcs(prop, NULL, "rna_Fluid_flowtype_set", NULL); RNA_def_property_ui_text(prop, "Flow Type", "Change type of fluid in the simulation"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "flow_behavior", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "behavior"); RNA_def_property_enum_items(prop, flow_behavior_items); RNA_def_property_ui_text(prop, "Flow Behavior", "Change flow behavior in the simulation"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "flow_source", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "source"); @@ -2363,20 +2433,20 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna) RNA_def_property_enum_funcs( prop, NULL, "rna_Fluid_flowsource_set", "rna_Fluid_flowsource_itemf"); RNA_def_property_ui_text(prop, "Source", "Change how fluid is emitted"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "use_absolute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_ABSOLUTE); RNA_def_property_ui_text(prop, "Absolute Density", "Only allow given density value in emitter area and will not add up"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "use_initial_velocity", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_INITVELOCITY); RNA_def_property_ui_text( prop, "Initial Velocity", "Fluid has some initial velocity when it is emitted"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vel_multi"); @@ -2386,28 +2456,28 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna) "Source", "Multiplier of source velocity passed to fluid (source velocity is " "non-zero only if object is moving)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "velocity_normal", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vel_normal"); RNA_def_property_range(prop, -100.0, 100.0); RNA_def_property_ui_range(prop, -2.0, 2.0, 0.05, 5); RNA_def_property_ui_text(prop, "Normal", "Amount of normal directional velocity"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "velocity_random", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vel_random"); RNA_def_property_range(prop, 0.0, 10.0); RNA_def_property_ui_range(prop, 0.0, 2.0, 0.05, 5); RNA_def_property_ui_text(prop, "Random", "Amount of random velocity"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "velocity_coord", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "vel_coord"); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -1000.1, 1000.1); RNA_def_property_ui_text(prop, "Initial", "Initial velocity in X, Y and Z direction"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "volume_density", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 1.0); @@ -2416,7 +2486,7 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna) "Volume Emission", "Controls fluid emission from within the mesh (higher value results in " "greater emissions from inside the mesh)"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "surface_distance", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 10.0); @@ -2425,7 +2495,7 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna) "Surface Emission", "Controls fluid emission from the mesh surface (higher value results " "in emission further away from the mesh surface"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "use_plane_init", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_USE_PLANE_INIT); @@ -2434,24 +2504,24 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna) "Is Planar", "Treat this object as a planar and unclosed mesh. Fluid will only be emitted from the mesh " "surface and based on the surface emission value"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "particle_size", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.1, 20.0); RNA_def_property_ui_range(prop, 0.5, 5.0, 0.05, 5); RNA_def_property_ui_text(prop, "Size", "Particle size in simulation cells"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "use_particle_size", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_USE_PART_SIZE); RNA_def_property_ui_text( prop, "Set Size", "Set particle size in simulation cells or use nearest cell"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "use_inflow", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_USE_INFLOW); RNA_def_property_ui_text(prop, "Enabled", "Control when to apply inflow"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "subframes", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 0, 200); @@ -2460,7 +2530,7 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna) "Subframes", "Number of additional samples to take between frames to improve " "quality of fast moving flows"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "density_vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, @@ -2469,41 +2539,41 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna) "rna_FluidFlow_density_vgroup_set"); RNA_def_property_ui_text( prop, "Vertex Group", "Name of vertex group which determines surface emission rate"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "use_texture", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_FLOW_TEXTUREEMIT); RNA_def_property_ui_text(prop, "Use Texture", "Use a texture to control emission strength"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "texture_map_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "texture_type"); RNA_def_property_enum_items(prop, flow_texture_types); RNA_def_property_ui_text(prop, "Mapping", "Texture mapping type"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "uvlayer_name"); RNA_def_property_ui_text(prop, "UV Map", "UV map name"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_FluidFlow_uvlayer_set"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "noise_texture", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Texture", "Texture that controls emission strength"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "texture_size", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.01, 10.0); RNA_def_property_ui_range(prop, 0.1, 5.0, 0.05, 5); RNA_def_property_ui_text(prop, "Size", "Size of texture mapping"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); prop = RNA_def_property(srna, "texture_offset", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 200.0); RNA_def_property_ui_range(prop, 0.0, 100.0, 0.05, 5); RNA_def_property_ui_text(prop, "Offset", "Z-offset of texture mapping"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); } static void rna_def_fluid_effector_settings(BlenderRNA *brna) @@ -2553,36 +2623,36 @@ static void rna_def_fluid_effector_settings(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, effector_type_items); RNA_def_property_ui_text(prop, "Effector Type", "Change type of effector in the simulation"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_effector_reset"); prop = RNA_def_property(srna, "surface_distance", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 10.0); RNA_def_property_ui_range(prop, 0.0, 10.0, 0.05, 5); RNA_def_property_ui_text( prop, "Surface", "Additional distance around mesh surface to consider as effector"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_effector_reset"); prop = RNA_def_property(srna, "use_plane_init", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_EFFECTOR_USE_PLANE_INIT); RNA_def_property_ui_text(prop, "Is Planar", "Treat this object as a planar, unclosed mesh"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_reset"); prop = RNA_def_property(srna, "velocity_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "vel_multi"); RNA_def_property_range(prop, -100.0, 100.0); RNA_def_property_ui_text(prop, "Source", "Multiplier of obstacle velocity"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_effector_reset"); prop = RNA_def_property(srna, "guide_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "guide_mode"); RNA_def_property_enum_items(prop, fluid_guide_mode_items); RNA_def_property_ui_text(prop, "Guiding mode", "How to create guiding velocities"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_update"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_effector_reset"); prop = RNA_def_property(srna, "use_effector", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_EFFECTOR_USE_EFFEC); RNA_def_property_ui_text(prop, "Enabled", "Control when to apply the effector"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_effector_reset"); prop = RNA_def_property(srna, "subframes", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 0, 200); @@ -2591,7 +2661,7 @@ static void rna_def_fluid_effector_settings(BlenderRNA *brna) "Subframes", "Number of additional samples to take between frames to improve " "quality of fast moving effector objects"); - RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_reset"); + RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_effector_reset"); } void RNA_def_fluid(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index e13b9caa90c..ccc141c1bb2 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -920,7 +920,7 @@ static bool rna_HookModifier_object_override_apply(Main *UNUSED(bmain), { BLI_assert(len_dst == len_src && (!ptr_storage || len_dst == len_storage) && len_dst == 0); BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE && - "Unsupported RNA override operation on Hook modifier target objet pointer"); + "Unsupported RNA override operation on Hook modifier target object pointer"); UNUSED_VARS_NDEBUG(ptr_storage, len_dst, len_src, len_storage, opop); /* We need a special handling here because setting hook target resets invert parent matrix, diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 27ebbe79085..6548aa01091 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -5699,6 +5699,16 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem meta_input_items[] = { + {0, "SCENE", 0, "Scene", "Use metadata from the current scene"}, + {R_STAMP_STRIPMETA, + "STRIPS", + 0, + "Sequencer Strips", + "Use metadata from the strips in the sequencer"}, + {0, NULL, 0, NULL, NULL}, + }; + rna_def_scene_ffmpeg_settings(brna); srna = RNA_def_struct(brna, "RenderSettings", NULL); @@ -6216,10 +6226,10 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop, "Stamp Labels", "Display stamp labels (\"Camera\" in front of camera name, etc.)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - prop = RNA_def_property(srna, "use_stamp_strip_meta", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_STRIPMETA); - RNA_def_property_ui_text( - prop, "Strip Metadata", "Use metadata from the strips in the sequencer"); + prop = RNA_def_property(srna, "metadata_input", PROP_ENUM, PROP_NONE); /* as an enum */ + RNA_def_property_enum_bitflag_sdna(prop, NULL, "stamp"); + RNA_def_property_enum_items(prop, meta_input_items); + RNA_def_property_ui_text(prop, "Metadata Input", "Where to take the metadata from"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_stamp_memory", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 1f072d2eb26..c6a94aae450 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2935,6 +2935,12 @@ static void rna_def_space_image_uv(BlenderRNA *brna) prop, "Tile Grid Shape", "How many tiles will be shown in the background"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); + prop = RNA_def_property(srna, "uv_opacity", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "uv_opacity"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "UV Opacity", "Opacity of UV overlays"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); + /* todo: move edge and face drawing options here from G.f */ prop = RNA_def_property(srna, "pixel_snap_mode", PROP_ENUM, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index a169e81237d..2a64ffa73cd 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -693,7 +693,7 @@ void RNA_api_ui_layout(StructRNA *srna) static float node_socket_color_default[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* simple layout specifiers */ - func = RNA_def_function(srna, "row", "uiLayoutRow"); + func = RNA_def_function(srna, "row", "uiLayoutRowWithHeading"); parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); RNA_def_function_return(func, parm); RNA_def_function_ui_description( @@ -701,8 +701,14 @@ void RNA_api_ui_layout(StructRNA *srna) "Sub-layout. Items placed in this sublayout are placed next to each other " "in a row"); RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); + RNA_def_string(func, + "heading", + NULL, + UI_MAX_NAME_STR, + "Heading", + "Label to insert into the layout for this row"); - func = RNA_def_function(srna, "column", "uiLayoutColumn"); + func = RNA_def_function(srna, "column", "uiLayoutColumnWithHeading"); parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); RNA_def_function_return(func, parm); RNA_def_function_ui_description( @@ -710,6 +716,12 @@ void RNA_api_ui_layout(StructRNA *srna) "Sub-layout. Items placed in this sublayout are placed under each other " "in a column"); RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); + RNA_def_string(func, + "heading", + NULL, + UI_MAX_NAME_STR, + "Heading", + "Label to insert into the layout for this column"); func = RNA_def_function(srna, "column_flow", "uiLayoutColumnFlow"); RNA_def_int(func, "columns", 0, 0, INT_MAX, "", "Number of columns, 0 is automatic", 0, INT_MAX); @@ -887,6 +899,20 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); api_ui_item_common(func); + func = RNA_def_function(srna, "prop_decorator", "uiItemDecoratorR"); + api_ui_item_rna_common(func); + RNA_def_int(func, + "index", + /* RNA_NO_INDEX == -1 */ + -1, + -2, + INT_MAX, + "", + "The index of this button, when set a single member of an array can be accessed, " + "when set to -1 all array members are used", + -2, + INT_MAX); + for (int is_menu_hold = 0; is_menu_hold < 2; is_menu_hold++) { func = (is_menu_hold) ? RNA_def_function(srna, "operator_menu_hold", "rna_uiItemOMenuHold") : RNA_def_function(srna, "operator", "rna_uiItemO"); @@ -1492,6 +1518,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_CONTEXT); func = RNA_def_function(srna, "template_node_link", "uiTemplateNodeLink"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); parm = RNA_def_pointer(func, "ntree", "NodeTree", "", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_pointer(func, "node", "Node", "", ""); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index c08a95d7e16..d1af3ea7910 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -6063,10 +6063,6 @@ static void rna_def_userdef_experimental(BlenderRNA *brna) prop, "Undo Legacy", "Use legacy undo (slower than the new default one, but may be more stable in some cases)"); - - prop = RNA_def_property(srna, "use_menu_search", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "use_menu_search", 1); - RNA_def_property_ui_text(prop, "Menu Search", "Search actions by menus instead of operators"); } static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop) diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c index fa98f9efb74..420c5b75926 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c @@ -137,6 +137,9 @@ static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *nod nodeSetSocketAvailability(inGainSock, tex->musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL || tex->musgrave_type == SHD_MUSGRAVE_RIDGED_MULTIFRACTAL); + + bNodeSocket *outFacSock = nodeFindSocket(node, SOCK_OUT, "Fac"); + node_sock_label(outFacSock, "Height"); } void register_node_type_sh_tex_musgrave(void) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index f7901ebb7d0..77a482f8546 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2514,7 +2514,7 @@ void RE_RenderAnim(Render *re, { float ctime = BKE_scene_frame_get(scene); AnimData *adt = BKE_animdata_from_id(&scene->id); - BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, ADT_RECALC_ALL, false); + BKE_animsys_evaluate_animdata(&scene->id, adt, ctime, ADT_RECALC_ALL, false); } render_update_depsgraph(re); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index a7578291a21..96b2fcf92e7 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1349,17 +1349,8 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *region, void *arg_op) } uiLayout *col = uiLayoutColumn(layout, false); - - if (op->type->flag & OPTYPE_MACRO) { - for (op = op->macro.first; op; op = op->next) { - uiTemplateOperatorPropertyButs( - C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); - } - } - else { - uiTemplateOperatorPropertyButs( - C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); - } + uiTemplateOperatorPropertyButs( + C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); UI_block_bounds_set_popup(block, 6 * U.dpi_fac, NULL); @@ -1794,13 +1785,12 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *eve } } - PropertyRNA *prop = op->type->prop; int search_type; - if (RNA_property_is_set(op->ptr, prop)) { - search_type = RNA_property_enum_get(op->ptr, prop); + if (STREQ(op->type->idname, "WM_OT_search_menu")) { + search_type = SEARCH_TYPE_MENU; } else { - search_type = U.experimental.use_menu_search ? SEARCH_TYPE_MENU : SEARCH_TYPE_OPERATOR; + search_type = SEARCH_TYPE_OPERATOR; } static struct SearchPopupInit_Data data; @@ -1818,20 +1808,22 @@ static void WM_OT_search_menu(wmOperatorType *ot) { ot->name = "Search Menu"; ot->idname = "WM_OT_search_menu"; - ot->description = "Pop-up a search menu over all available operators in current context"; + ot->description = "Pop-up a search over all menus in the current context"; ot->invoke = wm_search_menu_invoke; ot->exec = wm_search_menu_exec; ot->poll = WM_operator_winactive; +} - static const EnumPropertyItem search_type_items[] = { - {SEARCH_TYPE_OPERATOR, "OPERATOR", 0, "Operator", "Search all operators"}, - {SEARCH_TYPE_MENU, "MENU", 0, "Menu", "Search active menu items"}, - {0, NULL, 0, NULL, NULL}, - }; +static void WM_OT_search_operator(wmOperatorType *ot) +{ + ot->name = "Search Operator"; + ot->idname = "WM_OT_search_operator"; + ot->description = "Pop-up a search over all available operators in current context"; - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", search_type_items, SEARCH_TYPE_OPERATOR, "Type", ""); + ot->invoke = wm_search_menu_invoke; + ot->exec = wm_search_menu_exec; + ot->poll = WM_operator_winactive; } static int wm_call_menu_exec(bContext *C, wmOperator *op) @@ -3806,6 +3798,7 @@ void wm_operatortypes_register(void) WM_operatortype_append(WM_OT_operator_defaults); WM_operatortype_append(WM_OT_splash); WM_operatortype_append(WM_OT_search_menu); + WM_operatortype_append(WM_OT_search_operator); WM_operatortype_append(WM_OT_call_menu); WM_operatortype_append(WM_OT_call_menu_pie); WM_operatortype_append(WM_OT_call_panel); |