diff options
Diffstat (limited to 'source/blender')
225 files changed, 3710 insertions, 1391 deletions
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index c647dd3cc0f..eb05e66cf06 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -129,9 +129,9 @@ bool BKE_camera_view_frame_fit_to_scene( struct Scene *scene, struct ViewLayer *view_layer, struct Object *camera_ob, float r_co[3], float *r_scale); bool BKE_camera_view_frame_fit_to_coords( - const struct Scene *scene, + const struct Depsgraph *depsgraph, const float (*cos)[3], int num_cos, - const struct Object *camera_ob, + struct Object *camera_ob, float r_co[3], float *r_scale); void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings); @@ -139,11 +139,11 @@ void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_set /* Camera multi-view API */ struct Object *BKE_camera_multiview_render(struct Scene *scene, struct Object *camera, const char *viewname); -void BKE_camera_multiview_view_matrix(struct RenderData *rd, struct Object *camera, const bool is_left, float r_viewmat[4][4]); -void BKE_camera_multiview_model_matrix(struct RenderData *rd, struct Object *camera, const char *viewname, float r_modelmat[4][4]); -float BKE_camera_multiview_shift_x(struct RenderData *rd, struct Object *camera, const char *viewname); -void BKE_camera_multiview_params(struct RenderData *rd, struct CameraParams *params, struct Object *camera, const char *viewname); -bool BKE_camera_multiview_spherical_stereo(struct RenderData *rd, struct Object *camera); +void BKE_camera_multiview_view_matrix(struct RenderData *rd, const struct Object *camera, const bool is_left, float r_viewmat[4][4]); +void BKE_camera_multiview_model_matrix(struct RenderData *rd, const struct Object *camera, const char *viewname, float r_modelmat[4][4]); +float BKE_camera_multiview_shift_x(struct RenderData *rd, const struct Object *camera, const char *viewname); +void BKE_camera_multiview_params(struct RenderData *rd, struct CameraParams *params, const struct Object *camera, const char *viewname); +bool BKE_camera_multiview_spherical_stereo(struct RenderData *rd, const struct Object *camera); /* Camera background image API */ struct CameraBGImage *BKE_camera_background_image_new(struct Camera *cam); diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index 18f6301953c..98ba0f6f2a4 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -49,6 +49,7 @@ extern "C" { /* special struct for use in constraint evaluation */ typedef struct bConstraintOb { + struct Depsgraph *depsgraph;/* to get evaluated armature. */ struct Scene *scene; /* for system time, part of deglobalization, code nicer later with local time (ton) */ struct Object *ob; /* if pchan, then armature that it comes from, otherwise constraint owner */ struct bPoseChannel *pchan; /* pose channel that owns the constraints being evaluated */ @@ -144,7 +145,7 @@ void BKE_constraints_proxylocal_extract(struct ListBase *dst, struct ListBase *s bool BKE_constraints_proxylocked_owner(struct Object *ob, struct bPoseChannel *pchan); /* Constraint Evaluation function prototypes */ -struct bConstraintOb *BKE_constraints_make_evalob(struct Scene *scene, struct Object *ob, void *subdata, short datatype); +struct bConstraintOb *BKE_constraints_make_evalob(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, void *subdata, short datatype); void BKE_constraints_clear_evalob(struct bConstraintOb *cob); void BKE_constraint_mat_convertspace( diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index e54531bdb0e..22897d2ea80 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -160,7 +160,7 @@ struct ImBuf *BKE_icon_geom_rasterize( const struct Icon_Geom *geom, const unsigned int size_x, const unsigned int size_y); -int BKE_icon_ensure_studio_light(struct StudioLight *sl); +int BKE_icon_ensure_studio_light(struct StudioLight *sl, int id_type); #define ICON_RENDER_DEFAULT_HEIGHT 32 diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index 626a1cd09e3..60204d177f2 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -80,7 +80,7 @@ void BKE_view_layer_copy_data( struct ViewLayer *view_layer_dst, const struct ViewLayer *view_layer_src, const int flag); -void BKE_view_layer_rename(struct Scene *scene, struct ViewLayer *view_layer, const char *name); +void BKE_view_layer_rename(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, const char *name); struct LayerCollection *BKE_layer_collection_get_active(struct ViewLayer *view_layer); bool BKE_layer_collection_activate(struct ViewLayer *view_layer, struct LayerCollection *lc); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index ab00b8174b5..c8d50793e76 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -557,7 +557,9 @@ struct DerivedMesh *modifier_applyModifierEM_DM_deprecated( struct ModifierData *md, const struct ModifierEvalContext *ctx, struct BMEditMesh *editData, struct DerivedMesh *dm); -struct Mesh *BKE_modifier_get_evaluated_mesh_from_object(struct Object *ob, const ModifierApplyFlag flag); +struct Mesh *BKE_modifier_get_evaluated_mesh_from_object( + const struct ModifierEvalContext *ctx, + struct Object *ob); #endif diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index f3cbcd7b99f..c654dd51e2a 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -796,6 +796,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, c #define SH_NODE_UVALONGSTROKE 191 #define SH_NODE_TEX_POINTDENSITY 192 #define SH_NODE_BSDF_PRINCIPLED 193 +#define SH_NODE_TEX_IES 194 #define SH_NODE_EEVEE_SPECULAR 195 #define SH_NODE_BEVEL 197 #define SH_NODE_DISPLACEMENT 198 diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 7dbdac1b835..db6c7aa9c4f 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -45,6 +45,7 @@ struct View3D; struct SoftBody; struct MovieClip; struct Main; +struct Mesh; struct RigidBodyWorld; struct HookModifierData; struct ModifierData; @@ -269,6 +270,8 @@ void BKE_object_sculpt_modifiers_changed(struct Object *ob); int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float **r_loc, float **r_size, float **r_rot); +struct Mesh *BKE_object_get_evaluated_mesh(const struct Depsgraph *depsgraph, struct Object *ob); + int BKE_object_insert_ptcache(struct Object *ob); void BKE_object_delete_ptcache(struct Object *ob, int index); struct KeyBlock *BKE_object_shapekey_insert(struct Object *ob, const char *name, const bool from_mix); diff --git a/source/blender/blenkernel/BKE_outliner_treehash.h b/source/blender/blenkernel/BKE_outliner_treehash.h index b82bc692402..8a14f8fb041 100644 --- a/source/blender/blenkernel/BKE_outliner_treehash.h +++ b/source/blender/blenkernel/BKE_outliner_treehash.h @@ -36,6 +36,9 @@ void *BKE_outliner_treehash_create_from_treestore(struct BLI_mempool *treestore) /* full rebuild for already allocated hashtable */ void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, struct BLI_mempool *treestore); +/* clear element usage flags */ +void BKE_outliner_treehash_clear_used(void *treehash); + /* Add/remove hashtable elements */ void BKE_outliner_treehash_add_element(void *treehash, struct TreeStoreElem *elem); void BKE_outliner_treehash_remove_element(void *treehash, struct TreeStoreElem *elem); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index b6a87ae333e..4820f0173bf 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -439,8 +439,8 @@ void psys_particle_on_dm(struct Mesh *mesh_final, int from, int index, int index /* particle_system.c */ void distribute_particles(struct ParticleSimulationData *sim, int from); void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa); -void psys_calc_dmcache(struct Object *ob, struct Mesh *mesh_final, struct Mesh *mesh_deformed, struct ParticleSystem *psys); -int psys_particle_dm_face_lookup(struct Mesh *mesh_final, struct Mesh *mesh_deformed, int findex, const float fw[4], struct LinkNode **poly_nodes); +void psys_calc_dmcache(struct Object *ob, struct Mesh *mesh_final, struct Mesh *mesh_original, struct ParticleSystem *psys); +int psys_particle_dm_face_lookup(struct Mesh *mesh_final, struct Mesh *mesh_original, int findex, const float fw[4], struct LinkNode **poly_nodes); void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra); diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h index 2fcf6ab2f19..213de712abd 100644 --- a/source/blender/blenkernel/BKE_studiolight.h +++ b/source/blender/blenkernel/BKE_studiolight.h @@ -51,6 +51,10 @@ #define STUDIOLIGHT_Y_NEG 3 #define STUDIOLIGHT_Z_POS 4 #define STUDIOLIGHT_Z_NEG 5 +#define STUDIOLIGHT_ICON_ID_TYPE_RADIANCE 0 +#define STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE 1 + +struct GPUTexture; enum StudioLightFlag { STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED = (1 << 0), @@ -58,7 +62,9 @@ enum StudioLightFlag { STUDIOLIGHT_EXTERNAL_FILE = (1 << 2), STUDIOLIGHT_ORIENTATION_CAMERA = (1 << 3), STUDIOLIGHT_ORIENTATION_WORLD = (1 << 4), - STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED = (1 << 5), + STUDIOLIGHT_EQUIRECTANGULAR_IMAGE_LOADED = (1 << 5), + STUDIOLIGHT_EQUIRECTANGULAR_GPUTEXTURE = (1 << 6), + STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED = (1 << 7), } StudioLightFlag; typedef struct StudioLight { @@ -66,18 +72,21 @@ typedef struct StudioLight { int flag; char name[FILE_MAXFILE]; char path[FILE_MAX]; - int icon_id; + int irradiance_icon_id; + int radiance_icon_id; int index; float diffuse_light[6][3]; float light_direction[3]; + ImBuf *equirectangular_buffer; ImBuf *radiance_buffers[6]; + struct GPUTexture *equirectangular_gputexture; } StudioLight; void BKE_studiolight_init(void); void BKE_studiolight_free(void); -struct StudioLight *BKE_studiolight_find(const char *name); +struct StudioLight *BKE_studiolight_find(const char *name, int flag); struct StudioLight *BKE_studiolight_findindex(int index); -unsigned int *BKE_studiolight_preview(StudioLight *sl, int icon_size); +unsigned int *BKE_studiolight_preview(StudioLight *sl, int icon_size, int icon_id_type); const struct ListBase *BKE_studiolight_listbase(void); void BKE_studiolight_ensure_flag(StudioLight *sl, int flag); diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h index 5ee15a08f9b..5442fd43ce5 100644 --- a/source/blender/blenkernel/BKE_workspace.h +++ b/source/blender/blenkernel/BKE_workspace.h @@ -53,12 +53,20 @@ void BKE_workspace_layout_remove( void BKE_workspace_relations_free( ListBase *relation_list); +void BKE_workspace_scene_relations_free_invalid( + struct WorkSpace *workspace); /* -------------------------------------------------------------------- */ /* General Utils */ -void BKE_workspace_view_layer_remove_references( +void BKE_workspace_view_layer_rename( + const struct Main *bmain, + const struct Scene *scene, + const char *old_name, + const char *new_name) ATTR_NONNULL(); + +void BKE_workspace_view_layer_remove( const struct Main *bmain, const struct ViewLayer *view_layer) ATTR_NONNULL(); @@ -92,6 +100,9 @@ struct Base *BKE_workspace_active_base_get(const struct WorkSpace *workspace, co struct ViewLayer *BKE_workspace_view_layer_get( const struct WorkSpace *workspace, const struct Scene *scene) GETTER_ATTRS; +struct ViewLayer *BKE_workspace_view_layer_exists( + const struct WorkSpace *workspace, + const struct Scene *scene) GETTER_ATTRS; void BKE_workspace_view_layer_set( struct WorkSpace *workspace, struct ViewLayer *layer, diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index f80096b39eb..8dbfc35c774 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2239,7 +2239,7 @@ void BKE_pose_where_is_bone( /* prepare PoseChannel for Constraint solving * - makes a copy of matrix, and creates temporary struct to use */ - cob = BKE_constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE); + cob = BKE_constraints_make_evalob(depsgraph, scene, ob, pchan, CONSTRAINT_OBTYPE_BONE); /* Solve PoseChannel's Constraints */ BKE_constraints_solve(depsgraph, &pchan->constraints, cob, ctime); /* ctime doesnt alter objects */ diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 259c5189896..dbaf3f2ee9e 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -560,6 +560,10 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int NodeShaderScript *nss = (NodeShaderScript *)node->storage; rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data); } + else if (node->type == SH_NODE_TEX_IES) { + NodeShaderTexIES *ies = (NodeShaderTexIES *)node->storage; + rewrite_path_fixed(ies->filepath, visit_cb, absbase, bpath_user_data); + } } } break; @@ -576,6 +580,10 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int NodeShaderScript *nss = (NodeShaderScript *)node->storage; rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data); } + else if (node->type == SH_NODE_TEX_IES) { + NodeShaderTexIES *ies = (NodeShaderTexIES *)node->storage; + rewrite_path_fixed(ies->filepath, visit_cb, absbase, bpath_user_data); + } } } break; diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index a18fd9ead87..b1b4f18a6d5 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -268,7 +268,7 @@ void BKE_camera_params_from_view3d(CameraParams *params, Depsgraph *depsgraph, c if (rv3d->persp == RV3D_CAMOB) { /* camera view */ - Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); + const Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); BKE_camera_params_from_object(params, ob_camera_eval); params->zoom = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); @@ -666,16 +666,18 @@ bool BKE_camera_view_frame_fit_to_scene( } bool BKE_camera_view_frame_fit_to_coords( - const Scene *scene, const float (*cos)[3], int num_cos, const Object *camera_ob, + const Depsgraph *depsgraph, const float (*cos)[3], int num_cos, Object *camera_ob, float r_co[3], float *r_scale) { + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob); CameraParams params; CameraViewFrameData data_cb; /* just in case */ *r_scale = 1.0f; - camera_frame_fit_data_init(scene, camera_ob, ¶ms, &data_cb); + camera_frame_fit_data_init(scene_eval, camera_ob_eval, ¶ms, &data_cb); /* run callback on all given coordinates */ while (num_cos--) { @@ -687,12 +689,12 @@ bool BKE_camera_view_frame_fit_to_coords( /******************* multiview matrix functions ***********************/ -static void camera_model_matrix(Object *camera, float r_modelmat[4][4]) +static void camera_model_matrix(const Object *camera, float r_modelmat[4][4]) { copy_m4_m4(r_modelmat, camera->obmat); } -static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, float r_modelmat[4][4]) +static void camera_stereo3d_model_matrix(const Object *camera, const bool is_left, float r_modelmat[4][4]) { Camera *data = (Camera *)camera->data; float interocular_distance, convergence_distance; @@ -790,7 +792,7 @@ static void camera_stereo3d_model_matrix(Object *camera, const bool is_left, flo } /* the view matrix is used by the viewport drawing, it is basically the inverted model matrix */ -void BKE_camera_multiview_view_matrix(RenderData *rd, Object *camera, const bool is_left, float r_viewmat[4][4]) +void BKE_camera_multiview_view_matrix(RenderData *rd, const Object *camera, const bool is_left, float r_viewmat[4][4]) { BKE_camera_multiview_model_matrix(rd, camera, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, r_viewmat); invert_m4(r_viewmat); @@ -805,7 +807,7 @@ static bool camera_is_left(const char *viewname) return true; } -void BKE_camera_multiview_model_matrix(RenderData *rd, Object *camera, const char *viewname, float r_modelmat[4][4]) +void BKE_camera_multiview_model_matrix(RenderData *rd, const Object *camera, const char *viewname, float r_modelmat[4][4]) { const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0; @@ -822,7 +824,7 @@ void BKE_camera_multiview_model_matrix(RenderData *rd, Object *camera, const cha normalize_m4(r_modelmat); } -bool BKE_camera_multiview_spherical_stereo(RenderData *rd, Object *camera) +bool BKE_camera_multiview_spherical_stereo(RenderData *rd, const Object *camera) { Camera *cam; const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0; @@ -895,7 +897,7 @@ Object *BKE_camera_multiview_render(Scene *scene, Object *camera, const char *vi } } -static float camera_stereo3d_shift_x(Object *camera, const char *viewname) +static float camera_stereo3d_shift_x(const Object *camera, const char *viewname) { Camera *data = camera->data; float shift = data->shiftx; @@ -933,7 +935,7 @@ static float camera_stereo3d_shift_x(Object *camera, const char *viewname) return shift; } -float BKE_camera_multiview_shift_x(RenderData *rd, Object *camera, const char *viewname) +float BKE_camera_multiview_shift_x(RenderData *rd, const Object *camera, const char *viewname) { const bool is_multiview = (rd && rd->scemode & R_MULTIVIEW) != 0; Camera *data = camera->data; @@ -951,7 +953,7 @@ float BKE_camera_multiview_shift_x(RenderData *rd, Object *camera, const char *v } } -void BKE_camera_multiview_params(RenderData *rd, CameraParams *params, Object *camera, const char *viewname) +void BKE_camera_multiview_params(RenderData *rd, CameraParams *params, const Object *camera, const char *viewname) { if (camera->type == OB_CAMERA) { params->shiftx = BKE_camera_multiview_shift_x(rd, camera, viewname); @@ -977,6 +979,7 @@ CameraBGImage *BKE_camera_background_image_new(Camera *cam) bgpic->alpha = 0.5f; bgpic->iuser.fie_ima = 2; bgpic->iuser.ok = 1; + bgpic->iuser.flag |= IMA_ANIM_ALWAYS; bgpic->flag |= CAM_BGIMG_FLAG_EXPANDED; BLI_addtail(&cam->bg_images, bgpic); diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 30ed796d73f..c4709a32f78 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -614,7 +614,7 @@ bool BKE_collection_object_remove(Main *bmain, Collection *collection, Object *o return false; } - if (collection_object_remove(bmain, collection, ob, free_us)) { + if (!collection_object_remove(bmain, collection, ob, free_us)) { return false; } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 6a477c9c06e..28c6fe852c2 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -84,6 +84,9 @@ #include "BIK_api.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + #ifdef WITH_PYTHON # include "BPY_extern.h" #endif @@ -116,7 +119,7 @@ void BKE_constraint_unique_name(bConstraint *con, ListBase *list) /* package an object/bone for use in constraint evaluation */ /* This function MEM_calloc's a bConstraintOb struct, that will need to be freed after evaluation */ -bConstraintOb *BKE_constraints_make_evalob(Scene *scene, Object *ob, void *subdata, short datatype) +bConstraintOb *BKE_constraints_make_evalob(Depsgraph *depsgraph, Scene *scene, Object *ob, void *subdata, short datatype) { bConstraintOb *cob; @@ -125,6 +128,7 @@ bConstraintOb *BKE_constraints_make_evalob(Scene *scene, Object *ob, void *subda /* for system time, part of deglobalization, code nicer later with local time (ton) */ cob->scene = scene; + cob->depsgraph = depsgraph; /* based on type of available data */ switch (datatype) { @@ -3903,20 +3907,25 @@ static void followtrack_id_looper(bConstraint *con, ConstraintIDFunc func, void static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) { + Depsgraph *depsgraph = cob->depsgraph; Scene *scene = cob->scene; bFollowTrackConstraint *data = con->data; MovieClip *clip = data->clip; MovieTracking *tracking; MovieTrackingTrack *track; MovieTrackingObject *tracking_object; - Object *camob = data->camera ? data->camera : scene->camera; - float ctime = BKE_scene_frame_get(scene); + + Object *camob_eval = DEG_get_evaluated_object( + depsgraph, + data->camera ? data->camera : scene->camera); + + float ctime = DEG_get_ctime(depsgraph);; float framenr; if (data->flag & FOLLOWTRACK_ACTIVECLIP) clip = scene->clip; - if (!clip || !data->track[0] || !camob) + if (!clip || !data->track[0] || !camob_eval) return; tracking = &clip->tracking; @@ -3945,7 +3954,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) { float imat[4][4]; - copy_m4_m4(mat, camob->obmat); + copy_m4_m4(mat, camob_eval->obmat); BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, imat); invert_m4(imat); @@ -3954,7 +3963,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); } else { - BKE_tracking_get_camera_object_matrix(cob->scene, camob, mat); + BKE_tracking_get_camera_object_matrix(cob->scene, camob_eval, mat); mul_m4_m4m4(cob->matrix, obmat, mat); translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); @@ -3966,7 +3975,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp); float len, d; - BKE_object_where_is_calc_mat4(scene, camob, mat); + BKE_object_where_is_calc_mat4(scene, camob_eval, mat); /* camera axis */ vec[0] = 0.0f; @@ -4034,7 +4043,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase } BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, camob); + BKE_camera_params_from_object(¶ms, camob_eval); if (params.is_ortho) { vec[0] = params.ortho_scale * (pos[0] - 0.5f + params.shiftx); @@ -4046,9 +4055,9 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase else vec[0] *= aspect; - mul_v3_m4v3(disp, camob->obmat, vec); + mul_v3_m4v3(disp, camob_eval->obmat, vec); - copy_m4_m4(rmat, camob->obmat); + copy_m4_m4(rmat, camob_eval->obmat); zero_v3(rmat[3]); mul_m4_m4m4(cob->matrix, cob->matrix, rmat); @@ -4066,10 +4075,10 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase else vec[0] *= aspect; - mul_v3_m4v3(disp, camob->obmat, vec); + mul_v3_m4v3(disp, camob_eval->obmat, vec); /* apply camera rotation so Z-axis would be co-linear */ - copy_m4_m4(rmat, camob->obmat); + copy_m4_m4(rmat, camob_eval->obmat); zero_v3(rmat[3]); mul_m4_m4m4(cob->matrix, cob->matrix, rmat); @@ -4088,7 +4097,7 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase invert_m4_m4(imat, depth_ob->obmat); - mul_v3_m4v3(ray_start, imat, camob->obmat[3]); + mul_v3_m4v3(ray_start, imat, camob_eval->obmat[3]); mul_v3_m4v3(ray_end, imat, cob->matrix[3]); sub_v3_v3v3(ray_nor, ray_end, ray_start); @@ -4147,6 +4156,7 @@ static void camerasolver_id_looper(bConstraint *con, ConstraintIDFunc func, void static void camerasolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) { + Depsgraph *depsgraph = cob->depsgraph; Scene *scene = cob->scene; bCameraSolverConstraint *data = con->data; MovieClip *clip = data->clip; @@ -4158,7 +4168,7 @@ static void camerasolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase float mat[4][4], obmat[4][4]; MovieTracking *tracking = &clip->tracking; MovieTrackingObject *object = BKE_tracking_object_get_camera(tracking); - float ctime = BKE_scene_frame_get(scene); + float ctime = DEG_get_ctime(depsgraph); float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime); BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, framenr, mat); @@ -4205,6 +4215,7 @@ static void objectsolver_id_looper(bConstraint *con, ConstraintIDFunc func, void static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) { + Depsgraph *depsgraph = cob->depsgraph; Scene *scene = cob->scene; bObjectSolverConstraint *data = con->data; MovieClip *clip = data->clip; @@ -4224,7 +4235,7 @@ static void objectsolver_evaluate(bConstraint *con, bConstraintOb *cob, ListBase if (object) { float mat[4][4], obmat[4][4], imat[4][4], cammat[4][4], camimat[4][4], parmat[4][4]; - float ctime = BKE_scene_frame_get(scene); + float ctime = DEG_get_ctime(depsgraph); float framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime); BKE_object_where_is_calc_mat4(scene, camob, cammat); @@ -4279,7 +4290,7 @@ static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBa return; } - const float frame = BKE_scene_frame_get(scene); + const float frame = DEG_get_ctime(cob->depsgraph); const float time = BKE_cachefile_time_offset(cache_file, frame, FPS); BKE_cachefile_ensure_handle(G.main, cache_file); @@ -4811,6 +4822,7 @@ void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph, Scene *scene, cob = MEM_callocN(sizeof(bConstraintOb), "tempConstraintOb"); cob->type = ownertype; cob->scene = scene; + cob->depsgraph = depsgraph; switch (ownertype) { case CONSTRAINT_OBTYPE_OBJECT: /* it is usually this case */ { diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index bfd4e07606f..e409f8c91f0 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -806,10 +806,11 @@ struct Icon_Geom *BKE_icon_geom_from_file(const char *filename) /** \name Studio Light Icon * \{ */ -int BKE_icon_ensure_studio_light(struct StudioLight *sl) +int BKE_icon_ensure_studio_light(struct StudioLight *sl, int id_type) { int icon_id = get_next_free_id(); - icon_create(icon_id, ICON_DATA_STUDIOLIGHT, sl); + Icon *icon = icon_create(icon_id, ICON_DATA_STUDIOLIGHT, sl); + icon->id_type = id_type; return icon_id; } /** \} */ diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index fd231971121..3a6d599ccd3 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -397,7 +397,7 @@ void BKE_view_layer_copy_data( // TODO: not always safe to free BKE_layer_collection_sync(scene_dst, view_layer_dst); } -void BKE_view_layer_rename(Scene *scene, ViewLayer *view_layer, const char *newname) +void BKE_view_layer_rename(Main *bmain, Scene *scene, ViewLayer *view_layer, const char *newname) { char oldname[sizeof(view_layer->name)]; @@ -418,8 +418,9 @@ void BKE_view_layer_rename(Scene *scene, ViewLayer *view_layer, const char *newn } } - /* fix all the animation data which may link to this */ + /* fix all the animation data and workspace which may link to this */ BKE_animdata_fix_paths_rename_all(NULL, "view_layers", oldname, view_layer->name); + BKE_workspace_view_layer_rename(bmain, scene, oldname, view_layer->name); /* Dependency graph uses view layer name based lookups. */ DEG_id_tag_update(&scene->id, 0); diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index dbfe619153d..37b5b62b06e 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -932,6 +932,9 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call BKE_workspace_layout_screen_set(layout, screen); } + for (WorkSpaceSceneRelation *relation = workspace->scene_layer_relations.first; relation; relation = relation->next) { + CALLBACK_INVOKE(relation->scene, IDWALK_CB_NOP); + } break; } case ID_GD: @@ -1080,6 +1083,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) case ID_LP: return ELEM(id_type_used, ID_IM); case ID_WS: + return ELEM(id_type_used, ID_SCR, ID_SCE); case ID_IM: case ID_VF: case ID_TXT: diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index c43a2e3b8ec..111968ba018 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -66,6 +66,7 @@ #include "BKE_library_query.h" #include "BKE_mesh.h" #include "BKE_multires.h" +#include "BKE_object.h" #include "BKE_DerivedMesh.h" /* may move these, only for modifier_path_relbase */ @@ -74,6 +75,7 @@ /* end */ #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "MOD_modifiertypes.h" @@ -1213,13 +1215,10 @@ struct DerivedMesh *modifier_applyModifierEM_DM_deprecated(struct ModifierData * /** Get evaluated mesh for other object, which is used as an operand for the modifier, * i.e. second operand for boolean modifier. */ -Mesh *BKE_modifier_get_evaluated_mesh_from_object(Object *ob, const ModifierApplyFlag flag) +Mesh *BKE_modifier_get_evaluated_mesh_from_object(const ModifierEvalContext *ctx, Object *ob) { - if (flag & MOD_APPLY_RENDER) { - /* TODO(sergey): Use proper derived render in the future. */ - return ob->mesh_evaluated; - } - else { - return ob->mesh_evaluated; - } + /* Note: we do not care about RENDER setting here, since we get data from despgraph + * (and render depsgraph shall be different from realtime one) + */ + return BKE_object_get_evaluated_mesh(ctx->depsgraph, ob); } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index d86b73ab1a9..a25b21a995a 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3545,6 +3545,7 @@ static void registerShaderNodes(void) register_node_type_sh_tex_checker(); register_node_type_sh_tex_brick(); register_node_type_sh_tex_pointdensity(); + register_node_type_sh_tex_ies(); } static void registerTextureNodes(void) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 9a1799ffb09..ab3300c4ff7 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -118,6 +118,7 @@ #include "BKE_image.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "DRW_engine.h" @@ -378,9 +379,9 @@ void BKE_object_free_caches(Object *object) if (psmd->mesh_final) { BKE_id_free(NULL, psmd->mesh_final); psmd->mesh_final = NULL; - if (psmd->mesh_deformed) { - BKE_id_free(NULL, psmd->mesh_deformed); - psmd->mesh_deformed = NULL; + if (psmd->mesh_original) { + BKE_id_free(NULL, psmd->mesh_original); + psmd->mesh_original = NULL; } psmd->flag |= eParticleSystemFlag_file_loaded; update_flag |= OB_RECALC_DATA; @@ -890,8 +891,7 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f BLI_listbase_clear(&psysn->pathcachebufs); BLI_listbase_clear(&psysn->childcachebufs); - /* XXX Never copy caches here? */ - psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag & ~LIB_ID_COPY_CACHES); + psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag); /* XXX - from reading existing code this seems correct but intended usage of * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */ @@ -2131,7 +2131,7 @@ void BKE_object_where_is_calc_time_ex( /* solve constraints */ if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) { bConstraintOb *cob; - cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); + cob = BKE_constraints_make_evalob(depsgraph, scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); BKE_constraints_solve(depsgraph, &ob->constraints, cob, ctime); BKE_constraints_clear_evalob(cob); } @@ -2457,6 +2457,7 @@ void BKE_object_empty_draw_type_set(Object *ob, const int value) if (!ob->iuser) { ob->iuser = MEM_callocN(sizeof(ImageUser), "image user"); ob->iuser->ok = 1; + ob->iuser->flag |= IMA_ANIM_ALWAYS; ob->iuser->frames = 100; ob->iuser->sfra = 1; ob->iuser->fie_ima = 2; @@ -2801,6 +2802,15 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc, return 1; } +/** Get evaluated mesh for given (main, original) object and depsgraph. */ +Mesh *BKE_object_get_evaluated_mesh(const Depsgraph *depsgraph, Object *ob) +{ + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + + return ob_eval->mesh_evaluated; +} + + static int pc_cmp(const void *a, const void *b) { const LinkData *ad = a, *bd = b; diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 91571e8bf62..d21a1326392 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -128,7 +128,7 @@ void BKE_object_eval_constraints(Depsgraph *depsgraph, * Not sure why, this is from Joshua - sergey * */ - cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); + cob = BKE_constraints_make_evalob(depsgraph, scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); BKE_constraints_solve(depsgraph, &ob->constraints, cob, ctime); BKE_constraints_clear_evalob(cob); } @@ -276,11 +276,12 @@ void BKE_object_handle_data_update( /* quick cache removed */ } -bool BKE_object_eval_proxy_copy(Depsgraph *UNUSED(depsgraph), +bool BKE_object_eval_proxy_copy(Depsgraph *depsgraph, Object *object) { /* Handle proxy copy for target, */ if (ID_IS_LINKED(object) && object->proxy_from) { + DEG_debug_print_eval(depsgraph, __func__, object->id.name, object); if (object->proxy_from->proxy_group) { /* Transform proxy into group space. */ Object *obg = object->proxy_from->proxy_group; diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c index 9bbde607b80..fb62645ef43 100644 --- a/source/blender/blenkernel/intern/outliner_treehash.c +++ b/source/blender/blenkernel/intern/outliner_treehash.c @@ -41,6 +41,7 @@ typedef struct TseGroup { TreeStoreElem **elems; + int lastused; int size; int allocated; } TseGroup; @@ -54,6 +55,7 @@ static TseGroup *tse_group_create(void) tse_group->elems = MEM_mallocN(sizeof(TreeStoreElem *), "TseGroupElems"); tse_group->size = 0; tse_group->allocated = 1; + tse_group->lastused = 0; return tse_group; } @@ -143,6 +145,16 @@ static void free_treehash_group(void *key) tse_group_free(key); } +void BKE_outliner_treehash_clear_used(void *treehash) +{ + GHashIterator gh_iter; + + GHASH_ITER(gh_iter, treehash) { + TseGroup *group = BLI_ghashIterator_getValue(&gh_iter); + group->lastused = 0; + } +} + void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *treestore) { BLI_assert(treehash); @@ -161,6 +173,7 @@ void BKE_outliner_treehash_add_element(void *treehash, TreeStoreElem *elem) *val_p = tse_group_create(); } group = *val_p; + group->lastused = 0; tse_group_add_element(group, elem); } @@ -198,10 +211,19 @@ TreeStoreElem *BKE_outliner_treehash_lookup_unused(void *treehash, short type, s group = BKE_outliner_treehash_lookup_group(treehash, type, nr, id); if (group) { - int i; - for (i = 0; i < group->size; i++) { - if (!group->elems[i]->used) { - return group->elems[i]; + /* Find unused element, with optimization to start from previously + * found element assuming we do repeated lookups. */ + int size = group->size; + int offset = group->lastused; + + for (int i = 0; i < size; i++, offset++) { + if (offset >= size) { + offset = 0; + } + + if (!group->elems[offset]->used) { + group->lastused = offset; + return group->elems[offset]; } } } diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 4056a15fe47..f961510984a 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -338,8 +338,8 @@ void BKE_paint_palette_set(Paint *p, Palette *palette) { if (p) { id_us_min((ID *)p->palette); - id_us_plus((ID *)palette); p->palette = palette; + id_us_plus((ID *)p->palette); } } @@ -347,8 +347,8 @@ void BKE_paint_curve_set(Brush *br, PaintCurve *pc) { if (br) { id_us_min((ID *)br->paint_curve); - id_us_plus((ID *)pc); br->paint_curve = pc; + id_us_plus((ID *)br->paint_curve); } } @@ -381,9 +381,7 @@ void BKE_palette_clear(Palette *palette) Palette *BKE_palette_add(Main *bmain, const char *name) { - Palette *palette; - - palette = BKE_libblock_alloc(bmain, ID_PAL, name, 0); + Palette *palette = BKE_id_new(bmain, ID_PAL, name); /* enable fake user by default */ id_fake_user_set(&palette->id); @@ -424,7 +422,7 @@ void BKE_palette_free(Palette *palette) PaletteColor *BKE_palette_color_add(Palette *palette) { - PaletteColor *color = MEM_callocN(sizeof(*color), "Pallete Color"); + PaletteColor *color = MEM_callocN(sizeof(*color), "Palette Color"); BLI_addtail(&palette->colors, color); return color; } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 26c822f5fef..a42826a1f89 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1295,7 +1295,7 @@ static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4 * \return the DM tessface index. */ int psys_particle_dm_face_lookup( - Mesh *mesh_final, Mesh *mesh_deformed, + Mesh *mesh_final, Mesh *mesh_original, int findex_orig, const float fw[4], struct LinkNode **poly_nodes) { MFace *mtessface_final; @@ -1308,7 +1308,7 @@ int psys_particle_dm_face_lookup( const int *index_mp_to_orig = NULL; const int totface_final = mesh_final->totface; - const int totface_deformed = mesh_deformed ? mesh_deformed->totface : totface_final; + const int totface_deformed = mesh_original ? mesh_original->totface : totface_final; if (ELEM(0, totface_final, totface_deformed)) { return DMCACHE_NOTFOUND; @@ -1318,8 +1318,8 @@ int psys_particle_dm_face_lookup( index_mp_to_orig = CustomData_get_layer(&mesh_final->pdata, CD_ORIGINDEX); BLI_assert(index_mf_to_mpoly); - if (mesh_deformed) { - index_mf_to_mpoly_deformed = CustomData_get_layer(&mesh_deformed->fdata, CD_ORIGINDEX); + if (mesh_original) { + index_mf_to_mpoly_deformed = CustomData_get_layer(&mesh_original->fdata, CD_ORIGINDEX); } else { BLI_assert(mesh_final->runtime.deformed_only); @@ -1329,8 +1329,8 @@ int psys_particle_dm_face_lookup( pindex_orig = index_mf_to_mpoly_deformed[findex_orig]; - if (mesh_deformed == NULL) { - mesh_deformed = mesh_final; + if (mesh_original == NULL) { + mesh_original = mesh_final; } index_mf_to_mpoly_deformed = NULL; @@ -1349,7 +1349,7 @@ int psys_particle_dm_face_lookup( return DMCACHE_NOTFOUND; } } - else if (findex_orig >= mesh_deformed->totface) { + else if (findex_orig >= mesh_original->totface) { return DMCACHE_NOTFOUND; /* index not in the original mesh */ } diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index e85a3f15022..846afd48064 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -847,7 +847,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti /* Simple children */ if (part->childtype != PART_CHILD_FACES) { BLI_srandom(31415926 + psys->seed + psys->child_seed); - distribute_simple_children(scene, ob, final_mesh, sim->psmd->mesh_deformed, psys, use_render_params); + distribute_simple_children(scene, ob, final_mesh, sim->psmd->mesh_original, psys, use_render_params); return 0; } } @@ -1233,7 +1233,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) BLI_task_pool_free(task_pool); - psys_calc_dmcache(sim->ob, final_mesh, sim->psmd->mesh_deformed, sim->psys); + psys_calc_dmcache(sim->ob, final_mesh, sim->psmd->mesh_original, sim->psys); if (ctx.mesh != final_mesh) BKE_id_free(NULL, ctx.mesh); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 6c454cfa0b1..cba0721ab3f 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -311,7 +311,7 @@ int psys_get_tot_child(Scene *scene, ParticleSystem *psys, const bool use_render /* Distribution */ /************************************************/ -void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_deformed, ParticleSystem *psys) +void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, ParticleSystem *psys) { /* use for building derived mesh mapping info: * @@ -350,7 +350,7 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_deformed, Partic origindex_poly= NULL; } else { - totelem = mesh_deformed->totface; + totelem = mesh_original->totface; origindex = CustomData_get_layer(&mesh_final->fdata, CD_ORIGINDEX); /* for face lookups we need the poly origindex too */ @@ -414,7 +414,7 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_deformed, Partic pa->num_dmcache = DMCACHE_NOTFOUND; } else { /* FROM_FACE/FROM_VOLUME */ - pa->num_dmcache = psys_particle_dm_face_lookup(mesh_final, mesh_deformed, pa->num, pa->fuv, nodearray); + pa->num_dmcache = psys_particle_dm_face_lookup(mesh_final, mesh_original, pa->num, pa->fuv, nodearray); } } } @@ -3242,7 +3242,7 @@ static void hair_step(ParticleSimulationData *sim, float cfra, const bool use_re if (psys->recalc & PSYS_RECALC_RESET) { /* need this for changing subsurf levels */ - psys_calc_dmcache(sim->ob, sim->psmd->mesh_final, sim->psmd->mesh_deformed, psys); + psys_calc_dmcache(sim->ob, sim->psmd->mesh_final, sim->psmd->mesh_original, psys); if (psys->clmd) cloth_free_modifier(psys->clmd); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 7fd7b791a3f..a99057ac0ad 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -50,6 +50,7 @@ #include "BLI_blenlib.h" #include "BLI_threads.h" #include "BLI_math.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "BLT_translation.h" @@ -4071,9 +4072,11 @@ void BKE_ptcache_update_info(PTCacheID *pid) } else { PTCacheMem *pm = cache->mem_cache.first; - float bytes = 0.0f; - int i, mb; - + char formatted_tot[16]; + char formatted_mem[15]; + long long int bytes = 0.0f; + int i; + for (; pm; pm=pm->next) { for (i=0; i<BPHYS_TOT_DATA; i++) bytes += MEM_allocN_len(pm->data[i]); @@ -4088,12 +4091,10 @@ void BKE_ptcache_update_info(PTCacheID *pid) totframes++; } - mb = (bytes > 1024.0f * 1024.0f); + BLI_str_format_int_grouped(formatted_tot, totframes); + BLI_str_format_byte_unit(formatted_mem, bytes, true); - BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames in memory (%.1f %s)"), - totframes, - bytes / (mb ? 1024.0f * 1024.0f : 1024.0f), - mb ? IFACE_("Mb") : IFACE_("kb")); + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%s frames in memory (%s)"), formatted_tot, formatted_mem); } if (cache->flag & PTCACHE_OUTDATED) { diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 28d5cad3da8..75018bbe5bd 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -1660,7 +1660,7 @@ void BKE_rigidbody_do_simulation(struct Depsgraph *depsgraph, Scene *scene, floa #else /* WITH_BULLET */ /* stubs */ -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-parameter" #endif @@ -1686,7 +1686,7 @@ void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {} void BKE_rigidbody_rebuild_world(struct Depsgraph *depsgraph, Scene *scene, float ctime) {} void BKE_rigidbody_do_simulation(struct Depsgraph *depsgraph, Scene *scene, float ctime) {} -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) # pragma GCC diagnostic pop #endif diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index d4ffc90c797..1a9a2d5b36d 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -571,6 +571,8 @@ void BKE_scene_init(Scene *sce) */ sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT; + sce->r.dither_intensity = 1.0f; + sce->r.bake_mode = 0; sce->r.bake_filter = 16; sce->r.bake_flag = R_BAKE_CLEAR; @@ -633,6 +635,7 @@ void BKE_scene_init(Scene *sce) sce->toolsettings->doublimit = 0.001; sce->toolsettings->vgroup_weight = 1.0f; sce->toolsettings->uvcalc_margin = 0.001f; + sce->toolsettings->uvcalc_flag = UVCALC_TRANSFORM_CORRECT; sce->toolsettings->unwrapper = 1; sce->toolsettings->select_thresh = 0.01f; diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 8e8bf395f38..3d3130486cb 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -414,7 +414,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, const Mo } if (calc->smd->auxTarget) { - auxMesh = BKE_modifier_get_evaluated_mesh_from_object(calc->smd->auxTarget, ctx->flag); + auxMesh = BKE_modifier_get_evaluated_mesh_from_object(ctx, calc->smd->auxTarget); if (!auxMesh) return; BLI_SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget); @@ -625,7 +625,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, Mesh *me if (smd->target) { - calc.target = BKE_modifier_get_evaluated_mesh_from_object(smd->target, ctx->flag); + calc.target = BKE_modifier_get_evaluated_mesh_from_object(ctx, smd->target); /* TODO there might be several "bugs" on non-uniform scales matrixs * because it will no longer be nearest surface, not sphere projection diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c index 8086156d3af..f139ea5fbe6 100644 --- a/source/blender/blenkernel/intern/studiolight.c +++ b/source/blender/blenkernel/intern/studiolight.c @@ -48,6 +48,8 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "GPU_texture.h" + #include "MEM_guardedalloc.h" @@ -67,6 +69,16 @@ static void studiolight_free(struct StudioLight *sl) IMB_freeImBuf(sl->radiance_buffers[index]); sl->radiance_buffers[index] = NULL; } + + if (sl->equirectangular_gputexture) { + GPU_texture_free(sl->equirectangular_gputexture); + sl->equirectangular_gputexture = NULL; + } + + if (sl->equirectangular_buffer) { + IMB_freeImBuf(sl->equirectangular_buffer); + sl->equirectangular_buffer = NULL; + } } MEM_freeN(sl); } @@ -78,7 +90,8 @@ static struct StudioLight *studiolight_create(void) sl->name[0] = 0x00; sl->flag = 0; sl->index = BLI_listbase_count(&studiolights); - sl->icon_id = BKE_icon_ensure_studio_light(sl); + sl->radiance_icon_id = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_RADIANCE); + sl->irradiance_icon_id = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE); for (int index = 0 ; index < 6 ; index ++) { sl->radiance_buffers[index] = NULL; @@ -109,7 +122,11 @@ static void studiolight_calculate_radiance(ImBuf *ibuf, float color[4], const fl nearest_interpolation_color_wrap(ibuf, NULL, color, uv[0] * ibuf->x, uv[1] * ibuf->y); } -static void studiolight_calculate_radiance_buffer(ImBuf *ibuf, float *colbuf, const float start_x, const float add_x, const float start_y, const float add_y, const float z, const int index_x, const int index_y, const int index_z) +static void studiolight_calculate_radiance_buffer( + ImBuf *ibuf, float *colbuf, + const float start_x, const float add_x, + const float start_y, const float add_y, const float z, + const int index_x, const int index_y, const int index_z) { float direction[3]; float yf = start_y; @@ -129,40 +146,71 @@ static void studiolight_calculate_radiance_buffer(ImBuf *ibuf, float *colbuf, co } } -static void studiolight_calculate_radiance_buffers(StudioLight *sl) +static void studiolight_load_equierectangular_image(StudioLight *sl) { if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { - ImBuf* ibuf = NULL; + ImBuf *ibuf = NULL; ibuf = IMB_loadiffname(sl->path, 0, NULL); if (ibuf) { IMB_float_from_rect(ibuf); - float *colbuf = MEM_mallocN(4*STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE*STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE*sizeof(float), __func__); + sl->equirectangular_buffer = ibuf; + } + } + sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_IMAGE_LOADED; +} + +static void studiolight_create_equierectangular_gputexture(StudioLight *sl) +{ + if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { + char error[256]; + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IMAGE_LOADED); + ImBuf *ibuf = sl->equirectangular_buffer; + sl->equirectangular_gputexture = GPU_texture_create_2D(ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error); + } + sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_GPUTEXTURE; +} + + + +static void studiolight_calculate_radiance_buffers(StudioLight *sl) +{ + if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) { + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IMAGE_LOADED); + ImBuf* ibuf = sl->equirectangular_buffer; + if (ibuf) { + float *colbuf = MEM_mallocN(SQUARE(STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) * sizeof(float[4]), __func__); const float add = 1.0f / (STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE + 1); const float start = ((1.0f / STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) * 0.5f) - 0.5f; /* front */ studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, start, add, 0.5f, 0, 2, 1); - sl->radiance_buffers[STUDIOLIGHT_Y_POS] = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + sl->radiance_buffers[STUDIOLIGHT_Y_POS] = IMB_allocFromBuffer( + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); /* back */ studiolight_calculate_radiance_buffer(ibuf, colbuf, -start, -add, start, add, -0.5f, 0, 2, 1); - sl->radiance_buffers[STUDIOLIGHT_Y_NEG] = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + sl->radiance_buffers[STUDIOLIGHT_Y_NEG] = IMB_allocFromBuffer( + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); /* left */ studiolight_calculate_radiance_buffer(ibuf, colbuf, -start, -add, start, add, 0.5f, 1, 2, 0); - sl->radiance_buffers[STUDIOLIGHT_X_POS] = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + sl->radiance_buffers[STUDIOLIGHT_X_POS] = IMB_allocFromBuffer( + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); /* right */ studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, start, add, -0.5f, 1, 2, 0); - sl->radiance_buffers[STUDIOLIGHT_X_NEG] = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + sl->radiance_buffers[STUDIOLIGHT_X_NEG] = IMB_allocFromBuffer( + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); /* top */ studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, start, add, -0.5f, 0, 1, 2); - sl->radiance_buffers[STUDIOLIGHT_Z_NEG] = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + sl->radiance_buffers[STUDIOLIGHT_Z_NEG] = IMB_allocFromBuffer( + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); /* bottom */ studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, -start, -add, 0.5f, 0, 1, 2); - sl->radiance_buffers[STUDIOLIGHT_Z_POS] = IMB_allocFromBuffer(NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); + sl->radiance_buffers[STUDIOLIGHT_Z_POS] = IMB_allocFromBuffer( + NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE); #if 0 IMB_saveiff(sl->radiance_buffers[STUDIOLIGHT_X_POS], "/tmp/studiolight_radiance_left.png", IB_rectfloat); @@ -173,7 +221,6 @@ static void studiolight_calculate_radiance_buffers(StudioLight *sl) IMB_saveiff(sl->radiance_buffers[STUDIOLIGHT_Z_NEG], "/tmp/studiolight_radiance_top.png", IB_rectfloat); #endif MEM_freeN(colbuf); - IMB_freeImBuf(ibuf); } } sl->flag |= STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED; @@ -441,6 +488,114 @@ static int studiolight_cmp(const void *a, const void *b) return BLI_strcasecmp(sl1->name, sl2->name); } } + +/* icons */ +static unsigned int* studiolight_radiance_preview(StudioLight *sl, int icon_size) +{ + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IMAGE_LOADED); + + uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__); + int icon_center = icon_size / 2; + float sphere_radius = icon_center * 0.9; + + int offset = 0; + for (int y = 0; y < icon_size; y++) { + float dy = y - icon_center; + for (int x = 0; x < icon_size; x++) { + float dx = x - icon_center; + /* calculate aliasing */ + float alias = 0; + const float alias_step = 0.333; + for (float ay = dy - 0.5; ay < dy + 0.5; ay += alias_step) { + for (float ax = dx - 0.5; ax < dx + 0.5; ax += alias_step) { + if (sqrt(ay * ay + ax * ax) < sphere_radius) { + alias += alias_step * alias_step; + } + } + } + uint pixelresult = 0x0; + uint alias_i = clamp_i(alias * 256, 0, 255); + if (alias_i != 0) { + /* calculate normal */ + uint alias_mask = alias_i << 24; + float incoming[3]; + copy_v3_fl3(incoming, 0.0, 1.0, 0.0); + + float normal[3]; + normal[0] = dx / sphere_radius; + normal[2] = dy / sphere_radius; + normal[1] = -sqrt(-(normal[0] * normal[0]) - (normal[2] * normal[2]) + 1); + normalize_v3(normal); + + float direction[3]; + reflect_v3_v3v3(direction, incoming, normal); + + float color[4]; + studiolight_calculate_radiance(sl->equirectangular_buffer, color, direction); + + pixelresult = rgb_to_cpack( + linearrgb_to_srgb(color[0]), + linearrgb_to_srgb(color[1]), + linearrgb_to_srgb(color[2])) | alias_mask; + } + rect[offset++] = pixelresult; + } + } + return rect; +} + +static unsigned int* studiolight_irradiance_preview(StudioLight *sl, int icon_size) +{ + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED); + + uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__); + int icon_center = icon_size / 2; + float sphere_radius = icon_center * 0.9; + + int offset = 0; + for (int y = 0; y < icon_size; y++) { + float dy = y - icon_center; + for (int x = 0; x < icon_size; x++) { + float dx = x - icon_center; + /* calculate aliasing */ + float alias = 0; + const float alias_step = 0.333; + for (float ay = dy - 0.5; ay < dy + 0.5; ay += alias_step) { + for (float ax = dx - 0.5; ax < dx + 0.5; ax += alias_step) { + if (sqrt(ay * ay + ax * ax) < sphere_radius) { + alias += alias_step * alias_step; + } + } + } + uint pixelresult = 0x0; + uint alias_i = clamp_i(alias * 256, 0, 255); + if (alias_i != 0) { + /* calculate normal */ + uint alias_mask = alias_i << 24; + float normal[3]; + normal[0] = dx / sphere_radius; + normal[1] = dy / sphere_radius; + normal[2] = sqrt(-(normal[0] * normal[0]) - (normal[1] * normal[1]) + 1); + normalize_v3(normal); + + float color[3]; + mul_v3_v3fl(color, sl->diffuse_light[STUDIOLIGHT_X_POS], clamp_f(normal[0], 0.0, 1.0)); + interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_X_NEG], clamp_f(-normal[0], 0.0, 1.0)); + interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_POS], clamp_f(normal[1], 0.0, 1.0)); + interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_NEG], clamp_f(-normal[1], 0.0, 1.0)); + interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Y_POS], clamp_f(normal[2], 0.0, 1.0)); + + pixelresult = rgb_to_cpack( + linearrgb_to_srgb(color[0]), + linearrgb_to_srgb(color[1]), + linearrgb_to_srgb(color[2])) | alias_mask; + } + rect[offset++] = pixelresult; + } + } + return rect; +} + /* API */ void BKE_studiolight_init(void) { @@ -477,11 +632,16 @@ void BKE_studiolight_free(void) } } -struct StudioLight *BKE_studiolight_find(const char *name) +struct StudioLight *BKE_studiolight_find(const char *name, int flag) { LISTBASE_FOREACH(StudioLight *, sl, &studiolights) { if (STREQLEN(sl->name, name, FILE_MAXFILE)) { - return sl; + if ((sl->flag & flag) == flag) { + return sl; + } else { + /* flags do not match, so use default */ + return studiolights.first; + } } } /* When not found, use the default studio light */ @@ -504,56 +664,13 @@ const struct ListBase *BKE_studiolight_listbase(void) return &studiolights; } -unsigned int *BKE_studiolight_preview(StudioLight *sl, int icon_size) +unsigned int *BKE_studiolight_preview(StudioLight *sl, int icon_size, int icon_id_type) { - BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED); - - uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__); - int icon_center = icon_size / 2; - float sphere_radius = icon_center * 0.9; - - int offset = 0; - for (int y = 0; y < icon_size; y++) { - float dy = y - icon_center; - for (int x = 0; x < icon_size; x++) { - float dx = x - icon_center; - /* calculate aliasing */ - float alias = 0; - const float alias_step = 0.333; - for (float ay = dy - 0.5; ay < dy + 0.5; ay += alias_step) { - for (float ax = dx - 0.5; ax < dx + 0.5; ax += alias_step) { - if (sqrt(ay * ay + ax * ax) < sphere_radius) { - alias += alias_step * alias_step; - } - } - } - uint pixelresult = 0x0; - uint alias_i = clamp_i(alias * 256, 0, 255); - if (alias_i != 0) { - /* calculate normal */ - uint alias_mask = alias_i << 24; - float normal[3]; - normal[0] = dx / sphere_radius; - normal[1] = dy / sphere_radius; - normal[2] = sqrt(-(normal[0] * normal[0]) - (normal[1] * normal[1]) + 1); - normalize_v3(normal); - - float color[3]; - mul_v3_v3fl(color, sl->diffuse_light[STUDIOLIGHT_X_POS], clamp_f(normal[0], 0.0, 1.0)); - interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_X_NEG], clamp_f(-normal[0], 0.0, 1.0)); - interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_POS], clamp_f(normal[1], 0.0, 1.0)); - interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_NEG], clamp_f(-normal[1], 0.0, 1.0)); - interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Y_POS], clamp_f(normal[2], 0.0, 1.0)); - - pixelresult = rgb_to_cpack( - linearrgb_to_srgb(color[0]), - linearrgb_to_srgb(color[1]), - linearrgb_to_srgb(color[2])) | alias_mask; - } - rect[offset++] = pixelresult; - } + if (icon_id_type == STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE) { + return studiolight_irradiance_preview(sl, icon_size); + } else { + return studiolight_radiance_preview(sl, icon_size); } - return rect; } void BKE_studiolight_ensure_flag(StudioLight *sl, int flag) @@ -562,12 +679,18 @@ void BKE_studiolight_ensure_flag(StudioLight *sl, int flag) return; } + if ((flag & STUDIOLIGHT_EQUIRECTANGULAR_IMAGE_LOADED)) { + studiolight_load_equierectangular_image(sl); + } if ((flag & STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED)) { studiolight_calculate_radiance_buffers(sl); } if ((flag & STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED)) { studiolight_calculate_diffuse_light(sl); } + if ((flag & STUDIOLIGHT_EQUIRECTANGULAR_GPUTEXTURE)) { + studiolight_create_equierectangular_gputexture(sl); + } if ((flag & STUDIOLIGHT_LIGHT_DIRECTION_CALCULATED)) { studiolight_calculate_light_direction(sl); } diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c index 7fc0d814089..fb768333bb6 100644 --- a/source/blender/blenkernel/intern/workspace.c +++ b/source/blender/blenkernel/intern/workspace.c @@ -26,6 +26,7 @@ #define DNA_PRIVATE_WORKSPACE_ALLOW #include <stdlib.h> +#include <string.h> #include "BLI_utildefines.h" #include "BLI_string.h" @@ -117,18 +118,6 @@ static void *workspace_relation_get_data_matching_parent( } } -static void workspace_relation_remove_from_value( - ListBase *relation_list, const void *value) -{ - for (WorkSpaceDataRelation *relation = relation_list->first, *relation_next; relation; relation = relation_next) { - relation_next = relation->next; - - if (relation->value == value) { - workspace_relation_remove(relation_list, relation); - } - } -} - /** * Checks if \a screen is already used within any workspace. A screen should never be assigned to multiple * WorkSpaceLayouts, but that should be ensured outside of the BKE_workspace module and without such checks. @@ -168,7 +157,7 @@ WorkSpace *BKE_workspace_add(Main *bmain, const char *name) void BKE_workspace_free(WorkSpace *workspace) { BKE_workspace_relations_free(&workspace->hook_layout_relations); - BKE_workspace_relations_free(&workspace->scene_viewlayer_relations); + BLI_freelistN(&workspace->scene_layer_relations); BLI_freelistN(&workspace->owner_ids); BLI_freelistN(&workspace->layouts); @@ -269,16 +258,45 @@ void BKE_workspace_relations_free( } } +void BKE_workspace_scene_relations_free_invalid( + WorkSpace *workspace) +{ + for (WorkSpaceSceneRelation *relation = workspace->scene_layer_relations.first, *relation_next; relation; relation = relation_next) { + relation_next = relation->next; + + if (relation->scene == NULL) { + BLI_freelinkN(&workspace->scene_layer_relations, relation); + } + else if (!BLI_findstring(&relation->scene->view_layers, relation->view_layer, offsetof(ViewLayer, name))) { + BLI_freelinkN(&workspace->scene_layer_relations, relation); + } + } +} /* -------------------------------------------------------------------- */ /* General Utils */ -void BKE_workspace_view_layer_remove_references( +void BKE_workspace_view_layer_rename( const Main *bmain, - const ViewLayer *view_layer) + const Scene *scene, + const char *old_name, + const char *new_name) { for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { - workspace_relation_remove_from_value(&workspace->scene_viewlayer_relations, view_layer); + for (WorkSpaceSceneRelation *relation = workspace->scene_layer_relations.first; relation; relation = relation->next) { + if (relation->scene == scene && STREQ(relation->view_layer, old_name)) { + STRNCPY(relation->view_layer, new_name); + } + } + } +} + +void BKE_workspace_view_layer_remove( + const Main *bmain, + const ViewLayer *UNUSED(view_layer)) +{ + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + BKE_workspace_scene_relations_free_invalid(workspace); } } @@ -408,13 +426,38 @@ Base *BKE_workspace_active_base_get(const WorkSpace *workspace, const Scene *sce return view_layer->basact; } +ViewLayer *BKE_workspace_view_layer_exists(const WorkSpace *workspace, const Scene *scene) +{ + WorkSpaceSceneRelation *relation = BLI_findptr(&workspace->scene_layer_relations, scene, offsetof(WorkSpaceSceneRelation, scene)); + return (relation) ? BLI_findstring(&scene->view_layers, relation->view_layer, offsetof(ViewLayer, name)) : NULL; +} + ViewLayer *BKE_workspace_view_layer_get(const WorkSpace *workspace, const Scene *scene) { - return workspace_relation_get_data_matching_parent(&workspace->scene_viewlayer_relations, scene); + ViewLayer *layer = BKE_workspace_view_layer_exists(workspace, scene); + + if (layer == NULL) { + BKE_workspace_view_layer_set((WorkSpace *)workspace, scene->view_layers.first, (Scene *)scene); + layer = scene->view_layers.first; + } + + return layer; } + void BKE_workspace_view_layer_set(WorkSpace *workspace, ViewLayer *layer, Scene *scene) { - workspace_relation_ensure_updated(&workspace->scene_viewlayer_relations, scene, layer); + WorkSpaceSceneRelation *relation = BLI_findptr(&workspace->scene_layer_relations, scene, offsetof(WorkSpaceSceneRelation, scene)); + if (relation == NULL) { + relation = MEM_callocN(sizeof(*relation), __func__); + } + else { + BLI_remlink(&workspace->scene_layer_relations, relation); + } + + /* (Re)insert at the head of the list, for faster lookups. */ + relation->scene = scene; + STRNCPY(relation->view_layer, layer->name); + BLI_addhead(&workspace->scene_layer_relations, relation); } ListBase *BKE_workspace_layouts_get(WorkSpace *workspace) @@ -422,7 +465,6 @@ ListBase *BKE_workspace_layouts_get(WorkSpace *workspace) return &workspace->layouts; } - const char *BKE_workspace_layout_name_get(const WorkSpaceLayout *layout) { return layout->name; diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 48be9d1842f..faa8dc03615 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -71,6 +71,7 @@ char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT A size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL(); size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL(); +void BLI_str_format_byte_unit(char dst[15], long long int size, const bool base_10) ATTR_NONNULL(); int BLI_strcaseeq(const char *a, const char *b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); char *BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index c0b76aa9cbf..75ddb5e739c 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -552,13 +552,13 @@ extern bool BLI_memory_is_zero(const void *arr, const size_t arr_size); /* UNUSED macro, for function argument */ -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) # define UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) #else # define UNUSED(x) UNUSED_ ## x #endif -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) # define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x #else # define UNUSED_FUNCTION(x) UNUSED_ ## x diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 1a6fd082e95..49630347032 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -799,6 +799,7 @@ int BLI_str_rstrip_float_zero(char *str, const char pad) while (end_p != p && *end_p == '0') { *end_p = pad; end_p--; + totstrip++; } } } @@ -995,6 +996,41 @@ size_t BLI_str_format_int_grouped(char dst[16], int num) } /** + * Format a size in bytes using binary units. + * 1000 -> 1 KB + * Number of decimal places grows with the used unit (e.g. 1.5 MB, 1.55 GB, 1.545 TB). + * + * \param dst The resulting string. Dimension of 14 to support largest possible value for \a bytes (LLONG_MAX). + * \param bytes Number to format + * \param base_10 Calculate using base 10 (GB, MB, ...) or 2 (GiB, MiB, ...) + */ +void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base_10) +{ + double bytes_converted = bytes; + int order = 0; + int decimals; + const int base = base_10 ? 1000 : 1024; + const char *units_base_10[] = {"B", "KB", "MB", "GB", "TB", "PB"}; + const char *units_base_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"}; + const int tot_units = ARRAY_SIZE(units_base_2); + + BLI_STATIC_ASSERT(ARRAY_SIZE(units_base_2) == ARRAY_SIZE(units_base_10), "array size mismatch"); + + while ((ABS(bytes_converted) >= base) && ((order + 1) < tot_units)) { + bytes_converted /= base; + order++; + } + decimals = MAX2(order - 1, 0); + + /* Format value first, stripping away floating zeroes. */ + const size_t dst_len = 15; + size_t len = BLI_snprintf_rlen(dst, dst_len, "%.*f", decimals, bytes_converted); + len -= (size_t)BLI_str_rstrip_float_zero(dst, '\0'); + dst[len++] = ' '; + BLI_strncpy(dst + len, base_10 ? units_base_10[order] : units_base_2[order], dst_len - len); +} + +/** * Find the ranges needed to split \a str into its individual words. * * \param str: The string to search for words. diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 761f3982e28..e6f5d9839ea 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -488,7 +488,8 @@ void BLI_spin_lock(SpinLock *spin) #elif defined(_MSC_VER) while (InterlockedExchangeAcquire(spin, 1)) { while (*spin) { - /* pass */ + /* Spinlock hint for processors with hyperthreading. */ + YieldProcessor(); } } #else diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 70c898a374e..bc4b8daf0d3 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2865,6 +2865,19 @@ static void direct_link_cachefile(FileData *fd, CacheFile *cache_file) /* ************ READ WORKSPACES *************** */ +static void lib_link_workspace_scene_data(FileData *fd, WorkSpace *workspace) +{ + for (WorkSpaceSceneRelation *relation = workspace->scene_layer_relations.first; + relation != NULL; + relation = relation->next) + { + relation->scene = newlibadr(fd, workspace->id.lib, relation->scene); + } + + /* Free any relations that got lost due to missing datablocks. */ + BKE_workspace_scene_relations_free_invalid(workspace); +} + static void lib_link_workspaces(FileData *fd, Main *bmain) { for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { @@ -2877,31 +2890,7 @@ static void lib_link_workspaces(FileData *fd, Main *bmain) IDP_LibLinkProperty(id->properties, fd); id_us_ensure_real(id); - for (WorkSpaceDataRelation *relation = workspace->scene_viewlayer_relations.first, - *relation_next = NULL; - relation != NULL; - relation = relation_next) - { - relation_next = relation->next; - - relation->parent = newlibadr(fd, id->lib, relation->parent); - /* relation->value is set in direct_link_workspace_link_scene_data, - * except when loading linked data. */ - Scene *scene = relation->parent; - - if (scene) { - if (scene->id.lib != NULL) { - relation->value = BLI_findstring(&scene->view_layers, relation->value_name, offsetof(ViewLayer, name)); - } - if (relation->value == NULL) { - relation->value = scene->view_layers.first; - } - } - else { - /* Remove empty relation if scene got lost. */ - BLI_freelinkN(&workspace->scene_viewlayer_relations, relation); - } - } + lib_link_workspace_scene_data(fd, workspace); for (WorkSpaceLayout *layout = layouts->first, *layout_next; layout; layout = layout_next) { bScreen *screen = newlibadr(fd, id->lib, BKE_workspace_layout_screen_get(layout)); @@ -2928,7 +2917,7 @@ static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main { link_list(fd, BKE_workspace_layouts_get(workspace)); link_list(fd, &workspace->hook_layout_relations); - link_list(fd, &workspace->scene_viewlayer_relations); + link_list(fd, &workspace->scene_layer_relations); link_list(fd, &workspace->owner_ids); link_list(fd, &workspace->tools); @@ -2940,12 +2929,6 @@ static void direct_link_workspace(FileData *fd, WorkSpace *workspace, const Main relation->value = newdataadr(fd, relation->value); } - if (ID_IS_LINKED(&workspace->id)) { - /* Appending workspace so render layer is likely from a different scene. Unset - * now, when activating workspace later we set a valid one from current scene. */ - BKE_workspace_relations_free(&workspace->scene_viewlayer_relations); - } - /* Same issue/fix as in direct_link_workspace_link_scene_data: Can't read workspace data * when reading windows, so have to update windows after/when reading workspaces. */ for (wmWindowManager *wm = main->wm.first; wm; wm = wm->id.next) { @@ -5247,7 +5230,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; psmd->mesh_final = NULL; - psmd->mesh_deformed = NULL; + psmd->mesh_original = NULL; psmd->psys= newdataadr(fd, psmd->psys); psmd->flag &= ~eParticleSystemFlag_psys_updated; psmd->flag |= eParticleSystemFlag_file_loaded; @@ -5717,7 +5700,6 @@ static void lib_link_collection_data(FileData *fd, Library *lib, Collection *col cob->ob = newlibadr_us(fd, lib, cob->ob); if (cob->ob == NULL) { - BLI_assert(!"Collection linked object got lost"); // TODO: remove, only for testing now BLI_freelinkN(&collection->gobject, cob); } } @@ -5729,7 +5711,6 @@ static void lib_link_collection_data(FileData *fd, Library *lib, Collection *col if (child->collection == NULL || BKE_collection_find_cycle(collection, child->collection)) { - BLI_assert(!"Collection child got lost"); // TODO: remove, only for testing now BLI_freelinkN(&collection->children, child); } else { @@ -6073,31 +6054,7 @@ static void direct_link_sequence_modifiers(FileData *fd, ListBase *lb) } } -/** - * Workspaces store a render layer pointer which can only be read after scene is read. - */ -static void direct_link_workspace_link_scene_data( - FileData *fd, Scene *scene, const ListBase *workspaces) -{ - for (WorkSpace *workspace = workspaces->first; workspace; workspace = workspace->id.next) { - for (WorkSpaceDataRelation *relation = workspace->scene_viewlayer_relations.first; - relation != NULL; - relation = relation->next) - { - ViewLayer *view_layer = newdataadr(fd, relation->value); - if (view_layer != NULL) { - BLI_assert(BLI_findindex(&scene->view_layers, view_layer) != -1); - /* relation->parent is set in lib_link_workspaces */ - } - if (UNLIKELY(view_layer == NULL)) { - view_layer = scene->view_layers.first; - } - relation->value = view_layer; - } - } -} - -static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain) +static void direct_link_scene(FileData *fd, Scene *sce) { Editing *ed; Sequence *seq; @@ -6363,8 +6320,6 @@ static void direct_link_scene(FileData *fd, Scene *sce, Main *bmain) sce->layer_properties = newdataadr(fd, sce->layer_properties); IDP_DirectLinkGroup_OrFree(&sce->layer_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - - direct_link_workspace_link_scene_data(fd, sce, &bmain->workspaces); } /* ****************** READ GREASE PENCIL ***************** */ @@ -7176,7 +7131,20 @@ static void lib_link_clipboard_restore(struct IDNameLib_Map *id_map) BKE_sequencer_base_recursive_apply(&seqbase_clipboard, lib_link_seq_clipboard_cb, id_map); } -static void lib_link_workspace_scene_data_restore(wmWindow *win, Scene *scene) +static void lib_link_workspace_scene_data_restore(struct IDNameLib_Map *id_map, WorkSpace *workspace) +{ + for (WorkSpaceSceneRelation *relation = workspace->scene_layer_relations.first; + relation != NULL; + relation = relation->next) + { + relation->scene = restore_pointer_by_name(id_map, &relation->scene->id, USER_IGNORE); + } + + /* Free any relations that got lost due to missing datablocks or view layers. */ + BKE_workspace_scene_relations_free_invalid(workspace); +} + +static void lib_link_window_scene_data_restore(wmWindow *win, Scene *scene) { bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); @@ -7437,12 +7405,14 @@ void blo_lib_link_restore(Main *newmain, wmWindowManager *curwm, Scene *curscene struct IDNameLib_Map *id_map = BKE_main_idmap_create(newmain); for (WorkSpace *workspace = newmain->workspaces.first; workspace; workspace = workspace->id.next) { + lib_link_workspace_scene_data_restore(id_map, workspace); + BKE_workspace_view_layer_set(workspace, cur_view_layer, curscene); + ListBase *layouts = BKE_workspace_layouts_get(workspace); for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) { lib_link_workspace_layout_restore(id_map, newmain, layout); } - BKE_workspace_view_layer_set(workspace, cur_view_layer, curscene); } for (wmWindow *win = curwm->windows.first; win; win = win->next) { @@ -7461,7 +7431,7 @@ void blo_lib_link_restore(Main *newmain, wmWindowManager *curwm, Scene *curscene /* keep cursor location through undo */ copy_v3_v3(win->scene->cursor.location, oldscene->cursor.location); copy_qt_qt(win->scene->cursor.rotation, oldscene->cursor.rotation); - lib_link_workspace_scene_data_restore(win, win->scene); + lib_link_window_scene_data_restore(win, win->scene); BLI_assert(win->screen == NULL); } @@ -8373,7 +8343,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short wrong_id = direct_link_screen(fd, (bScreen *)id); break; case ID_SCE: - direct_link_scene(fd, (Scene *)id, main); + direct_link_scene(fd, (Scene *)id); break; case ID_OB: direct_link_object(fd, (Object *)id); @@ -9096,6 +9066,14 @@ static void expand_constraint_channels(FileData *fd, Main *mainvar, ListBase *ch } } +static void expand_id(FileData *fd, Main *mainvar, ID *id) +{ + if (id->override_static) { + expand_doit(fd, mainvar, id->override_static->reference); + expand_doit(fd, mainvar, id->override_static->storage); + } +} + static void expand_idprops(FileData *fd, Main *mainvar, IDProperty *prop) { if (!prop) @@ -9870,6 +9848,7 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) id = lbarray[a]->first; while (id) { if (id->tag & LIB_TAG_NEED_EXPAND) { + expand_id(fd, mainvar, id); expand_idprops(fd, mainvar, id->properties); switch (GS(id->name)) { diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 7bb20c38308..a25c744afc4 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -262,6 +262,7 @@ static void do_version_layer_collection_post( static void do_version_scene_collection_convert( Main *bmain, + ID *id, SceneCollection *sc, Collection *collection, GHash *collection_map) @@ -273,7 +274,8 @@ static void do_version_scene_collection_convert( for (SceneCollection *nsc = sc->scene_collections.first; nsc;) { SceneCollection *nsc_next = nsc->next; Collection *ncollection = BKE_collection_add(bmain, collection, nsc->name); - do_version_scene_collection_convert(bmain, nsc, ncollection, collection_map); + ncollection->id.lib = id->lib; + do_version_scene_collection_convert(bmain, id, nsc, ncollection, collection_map); nsc = nsc_next; } @@ -293,7 +295,7 @@ static void do_version_group_collection_to_collection(Main *bmain, Collection *g { /* Convert old 2.8 group collections to new unified collections. */ if (group->collection) { - do_version_scene_collection_convert(bmain, group->collection, group, NULL); + do_version_scene_collection_convert(bmain, &group->id, group->collection, group, NULL); } group->collection = NULL; @@ -317,7 +319,7 @@ static void do_version_scene_collection_to_collection(Main *bmain, Scene *scene) /* Convert scene collections. */ GHash *collection_map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); if (scene->collection) { - do_version_scene_collection_convert(bmain, scene->collection, scene->master_collection, collection_map); + do_version_scene_collection_convert(bmain, &scene->id, scene->collection, scene->master_collection, collection_map); scene->collection = NULL; } @@ -434,6 +436,7 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene) collections[DO_VERSION_COLLECTION_VISIBLE].suffix); Collection *collection = BKE_collection_add(bmain, collection_master, name); + collection->id.lib = scene->id.lib; collection->flag |= collections[DO_VERSION_COLLECTION_VISIBLE].flag; collections[DO_VERSION_COLLECTION_VISIBLE].collections[layer] = collection; collections[DO_VERSION_COLLECTION_VISIBLE].created |= (1 << layer); @@ -453,6 +456,7 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene) collections[collection_index].suffix); Collection *collection = BKE_collection_add(bmain, collection_parent, name); + collection->id.lib = scene->id.lib; collection->flag |= collections[collection_index].flag; collections[collection_index].collections[layer] = collection; collections[collection_index].created |= (1 << layer); @@ -676,12 +680,14 @@ void do_versions_after_linking_280(Main *main) /* Convert group layer visibility flags to hidden nested collection. */ for (Collection *collection = main->collection.first; collection; collection = collection->id.next) { - Collection *collection_hidden = NULL; + /* Add fake user for all existing groups. */ + id_fake_user_set(&collection->id); if (collection->flag & (COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER)) { continue; } + Collection *collection_hidden = NULL; for (CollectionObject *cob = collection->gobject.first, *cob_next = NULL; cob; cob = cob_next) { cob_next = cob->next; Object *ob = cob->ob; @@ -689,6 +695,7 @@ void do_versions_after_linking_280(Main *main) if (!(ob->lay & collection->layer)) { if (collection_hidden == NULL) { collection_hidden = BKE_collection_add(main, collection, "Hidden"); + collection_hidden->id.lib = collection->id.lib; collection_hidden->flag |= COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER; } @@ -696,9 +703,6 @@ void do_versions_after_linking_280(Main *main) BKE_collection_object_remove(main, collection, ob, true); } } - - /* Add fake user for all existing groups. */ - id_fake_user_set(&collection->id); } /* Convert layers to collections. */ diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index f7a69931f9f..764eaecd1e9 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -141,6 +141,8 @@ void BLO_update_defaults_startup_blend(Main *bmain) if (scene->toolsettings) { ToolSettings *ts = scene->toolsettings; + ts->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT; + if (ts->sculpt) { Sculpt *sculpt = ts->sculpt; sculpt->paint.symmetry_flags |= PAINT_SYMM_X; @@ -354,6 +356,7 @@ void BLO_update_defaults_startup_blend(Main *bmain) for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) { scene->r.displaymode = R_OUTPUT_WINDOW; scene->r.size = 100; + scene->r.dither_intensity = 1.0f; scene->unit.system = USER_UNIT_METRIC; STRNCPY(scene->view_settings.view_transform, "Filmic"); } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index f3042dc84db..de1699e24b7 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -3599,18 +3599,10 @@ static void write_workspace(WriteData *wd, WorkSpace *workspace) { ListBase *layouts = BKE_workspace_layouts_get(workspace); - /* Update the names for file (only need to set on write). */ - for (WorkSpaceDataRelation *relation = workspace->scene_viewlayer_relations.first; - relation; - relation = relation->next) - { - STRNCPY(relation->value_name, ((ViewLayer *)relation->value)->name); - } - writestruct(wd, ID_WS, WorkSpace, 1, workspace); writelist(wd, DATA, WorkSpaceLayout, layouts); writelist(wd, DATA, WorkSpaceDataRelation, &workspace->hook_layout_relations); - writelist(wd, DATA, WorkSpaceDataRelation, &workspace->scene_viewlayer_relations); + writelist(wd, DATA, WorkSpaceSceneRelation, &workspace->scene_layer_relations); writelist(wd, DATA, wmOwnerID, &workspace->owner_ids); writelist(wd, DATA, bToolRef, &workspace->tools); for (bToolRef *tref = workspace->tools.first; tref; tref = tref->next) { diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index 5245d24a075..320bebc9958 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -169,7 +169,7 @@ set(SRC bmesh_tools.h ) -if(MSVC) +if(MSVC AND NOT MSVC_CLANG) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX /wd4101") endif() diff --git a/source/blender/compositor/nodes/COM_MathNode.cpp b/source/blender/compositor/nodes/COM_MathNode.cpp index eb6bb2caf56..0fb6933afe7 100644 --- a/source/blender/compositor/nodes/COM_MathNode.cpp +++ b/source/blender/compositor/nodes/COM_MathNode.cpp @@ -86,6 +86,9 @@ void MathNode::convertToOperations(NodeConverter &converter, const CompositorCon case NODE_MATH_ABS: operation = new MathAbsoluteOperation(); break; + case NODE_MATH_ATAN2: + operation = new MathArcTan2Operation(); + break; } if (operation) { diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cpp b/source/blender/compositor/operations/COM_MathBaseOperation.cpp index 32a1e77b9a7..dbc91980acd 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_MathBaseOperation.cpp @@ -343,3 +343,16 @@ void MathAbsoluteOperation::executePixelSampled(float output[4], float x, float clampIfNeeded(output); } + +void MathArcTan2Operation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +{ + float inputValue1[4]; + float inputValue2[4]; + + this->m_inputValue1Operation->readSampled(inputValue1, x, y, sampler); + this->m_inputValue2Operation->readSampled(inputValue2, x, y, sampler); + + output[0] = atan2(inputValue1[0], inputValue2[0]); + + clampIfNeeded(output); +}
\ No newline at end of file diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.h b/source/blender/compositor/operations/COM_MathBaseOperation.h index 32cd19f1fb9..04019372711 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.h +++ b/source/blender/compositor/operations/COM_MathBaseOperation.h @@ -169,4 +169,10 @@ public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; +class MathArcTan2Operation : public MathBaseOperation { +public: + MathArcTan2Operation() : MathBaseOperation() {} + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); +}; + #endif diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 9a1bd87f93d..64bdbe49dac 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -549,7 +549,11 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object) */ ComponentKey ob_pose_key(&object->id, DEG_NODE_TYPE_EVAL_POSE); ComponentKey proxy_pose_key(&object->proxy->id, DEG_NODE_TYPE_EVAL_POSE); - add_relation(ob_pose_key, proxy_pose_key, "Proxy"); + add_relation(ob_pose_key, proxy_pose_key, "Proxy Pose"); + + ComponentKey ob_transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey proxy_transform_key(&object->proxy->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform"); } /* Object dupligroup. */ if (object->dup_group != NULL) { diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index c8b9702621e..0e8d4669108 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -49,6 +49,7 @@ #include "BLI_threads.h" #include "BLI_string.h" +#include "BKE_curve.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_layer.h" @@ -76,6 +77,7 @@ extern "C" { # include "DNA_lattice_types.h" # include "DNA_linestyle_types.h" # include "DNA_material_types.h" +# include "DNA_meta_types.h" # include "DNA_node_types.h" # include "DNA_texture_types.h" # include "DNA_world_types.h" @@ -276,10 +278,11 @@ bool id_copy_inplace_no_main(const ID *id, ID *newid) bool result = BKE_id_copy_ex(NULL, (ID *)id_for_copy, &newid, - LIB_ID_CREATE_NO_MAIN | - LIB_ID_CREATE_NO_USER_REFCOUNT | - LIB_ID_CREATE_NO_ALLOCATE | - LIB_ID_CREATE_NO_DEG_TAG, + (LIB_ID_CREATE_NO_MAIN | + LIB_ID_CREATE_NO_USER_REFCOUNT | + LIB_ID_CREATE_NO_ALLOCATE | + LIB_ID_CREATE_NO_DEG_TAG | + LIB_ID_COPY_CACHES), false); #ifdef NESTED_ID_NASTY_WORKAROUND @@ -410,7 +413,7 @@ int foreach_libblock_remap_callback(void *user_data_v, return IDWALK_RET_NOP; } -void updata_armature_edit_mode_pointers(const Depsgraph * /*depsgraph*/, +void update_armature_edit_mode_pointers(const Depsgraph * /*depsgraph*/, const ID *id_orig, ID *id_cow) { const bArmature *armature_orig = (const bArmature *)id_orig; @@ -418,7 +421,32 @@ void updata_armature_edit_mode_pointers(const Depsgraph * /*depsgraph*/, armature_cow->edbo = armature_orig->edbo; } -void updata_mesh_edit_mode_pointers(const Depsgraph *depsgraph, +void update_curve_edit_mode_pointers(const Depsgraph * /*depsgraph*/, + const ID *id_orig, ID *id_cow) +{ + const Curve *curve_orig = (const Curve *)id_orig; + Curve *curve_cow = (Curve *)id_cow; + curve_cow->editnurb = curve_orig->editnurb; + curve_cow->editfont = curve_orig->editfont; +} + +void update_mball_edit_mode_pointers(const Depsgraph * /*depsgraph*/, + const ID *id_orig, ID *id_cow) +{ + const MetaBall *mball_orig = (const MetaBall *)id_orig; + MetaBall *mball_cow = (MetaBall *)id_cow; + mball_cow->editelems = mball_orig->editelems; +} + +void update_lattice_edit_mode_pointers(const Depsgraph * /*depsgraph*/, + const ID *id_orig, ID *id_cow) +{ + const Lattice *lt_orig = (const Lattice *)id_orig; + Lattice *lt_cow = (Lattice *)id_cow; + lt_cow->editlatt = lt_orig->editlatt; +} + +void update_mesh_edit_mode_pointers(const Depsgraph *depsgraph, const ID *id_orig, ID *id_cow) { /* For meshes we need to update edit_btmesh to make it to point @@ -443,16 +471,25 @@ void updata_mesh_edit_mode_pointers(const Depsgraph *depsgraph, /* Edit data is stored and owned by original datablocks, copied ones * are simply referencing to them. */ -void updata_edit_mode_pointers(const Depsgraph *depsgraph, +void update_edit_mode_pointers(const Depsgraph *depsgraph, const ID *id_orig, ID *id_cow) { const ID_Type type = GS(id_orig->name); switch (type) { case ID_AR: - updata_armature_edit_mode_pointers(depsgraph, id_orig, id_cow); + update_armature_edit_mode_pointers(depsgraph, id_orig, id_cow); break; case ID_ME: - updata_mesh_edit_mode_pointers(depsgraph, id_orig, id_cow); + update_mesh_edit_mode_pointers(depsgraph, id_orig, id_cow); + break; + case ID_CU: + update_curve_edit_mode_pointers(depsgraph, id_orig, id_cow); + break; + case ID_MB: + update_mball_edit_mode_pointers(depsgraph, id_orig, id_cow); + break; + case ID_LT: + update_lattice_edit_mode_pointers(depsgraph, id_orig, id_cow); break; default: break; @@ -504,7 +541,7 @@ void update_special_pointers(const Depsgraph *depsgraph, default: break; } - updata_edit_mode_pointers(depsgraph, id_orig, id_cow); + update_edit_mode_pointers(depsgraph, id_orig, id_cow); } /* This callback is used to validate that all nested ID datablocks are @@ -680,6 +717,7 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, ListBase gpumaterial_backup; ListBase *gpumaterial_ptr = NULL; Mesh *mesh_evaluated = NULL; + CurveCache *curve_cache = NULL; short base_flag = 0; if (check_datablock_expanded(id_cow)) { switch (id_type) { @@ -729,6 +767,10 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, object->data = mesh_evaluated->id.orig_id; } } + /* Store curve cache and make sure we don't free it. */ + curve_cache = object->curve_cache; + object->curve_cache = NULL; + /* Make a backup of base flags. */ base_flag = object->base_flag; break; @@ -764,6 +806,9 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, ((Mesh *)mesh_evaluated->id.orig_id)->edit_btmesh; } } + if (curve_cache != NULL) { + object->curve_cache = curve_cache; + } object->base_flag = base_flag; } return id_cow; @@ -786,6 +831,25 @@ void discard_armature_edit_mode_pointers(ID *id_cow) armature_cow->edbo = NULL; } +void discard_curve_edit_mode_pointers(ID *id_cow) +{ + Curve *curve_cow = (Curve *)id_cow; + curve_cow->editnurb = NULL; + curve_cow->editfont = NULL; +} + +void discard_mball_edit_mode_pointers(ID *id_cow) +{ + MetaBall *mball_cow = (MetaBall *)id_cow; + mball_cow->editelems = NULL; +} + +void discard_lattice_edit_mode_pointers(ID *id_cow) +{ + Lattice *lt_cow = (Lattice *)id_cow; + lt_cow->editlatt = NULL; +} + void discard_mesh_edit_mode_pointers(ID *id_cow) { Mesh *mesh_cow = (Mesh *)id_cow; @@ -810,6 +874,15 @@ void discard_edit_mode_pointers(ID *id_cow) case ID_ME: discard_mesh_edit_mode_pointers(id_cow); break; + case ID_CU: + discard_curve_edit_mode_pointers(id_cow); + break; + case ID_MB: + discard_mball_edit_mode_pointers(id_cow); + break; + case ID_LT: + discard_lattice_edit_mode_pointers(id_cow); + break; default: break; } diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 96dcac5b2d2..965faa7ba53 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -62,6 +62,7 @@ set(SRC intern/draw_cache_impl_metaball.c intern/draw_cache_impl_particles.c intern/draw_common.c + intern/draw_debug.c intern/draw_instance_data.c intern/draw_manager.c intern/draw_manager_data.c @@ -96,6 +97,7 @@ set(SRC engines/eevee/eevee_engine.c engines/eevee/eevee_lightprobes.c engines/eevee/eevee_lights.c + engines/eevee/eevee_lookdev.c engines/eevee/eevee_materials.c engines/eevee/eevee_mist.c engines/eevee/eevee_motion_blur.c @@ -120,6 +122,7 @@ set(SRC intern/draw_cache.h intern/draw_cache_impl.h intern/draw_common.h + intern/draw_debug.h intern/draw_instance_data.h intern/draw_manager.h intern/draw_manager_text.h @@ -220,6 +223,7 @@ data_to_c_simple(engines/workbench/shaders/workbench_deferred_composite_frag.gls data_to_c_simple(engines/workbench/shaders/workbench_forward_composite_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_forward_depth_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_object_outline_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_prepass_vert.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_prepass_frag.glsl SRC) diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c index 204990de5b0..c86574f7557 100644 --- a/source/blender/draw/engines/basic/basic_engine.c +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -119,7 +119,8 @@ static void basic_cache_init(void *vedata) #ifdef USE_DEPTH /* Depth Pass */ { - psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); + psl->depth_pass = DRW_pass_create( + "Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass); psl->depth_pass_cull = DRW_pass_create( diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c index bcbc37ac7af..d08fee6039f 100644 --- a/source/blender/draw/engines/clay/clay_engine.c +++ b/source/blender/draw/engines/clay/clay_engine.c @@ -224,7 +224,8 @@ static void clay_view_layer_data_free(void *storage) static CLAY_ViewLayerData *CLAY_view_layer_data_get(void) { - CLAY_ViewLayerData **sldata = (CLAY_ViewLayerData **)DRW_view_layer_engine_data_ensure(&draw_engine_clay_type, &clay_view_layer_data_free); + CLAY_ViewLayerData **sldata = (CLAY_ViewLayerData **)DRW_view_layer_engine_data_ensure( + &draw_engine_clay_type, &clay_view_layer_data_free); if (*sldata == NULL) { *sldata = MEM_callocN(sizeof(**sldata), "CLAY_ViewLayerData"); @@ -751,7 +752,8 @@ static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, boo return shgrps[id]; } -static DRWShadingGroup *CLAY_hair_shgrp_get(CLAY_Data *UNUSED(vedata), Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl) +static DRWShadingGroup *CLAY_hair_shgrp_get( + CLAY_Data *UNUSED(vedata), Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl) { DRWShadingGroup **hair_shgrps = stl->storage->hair_shgrps; @@ -803,8 +805,8 @@ static void clay_cache_init(void *vedata) /* Hair Pass */ { psl->hair_pass = DRW_pass_create( - "Hair Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); + "Hair Pass", + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); } { diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c index f644b59c0b7..8be9c637fbc 100644 --- a/source/blender/draw/engines/eevee/eevee_bloom.c +++ b/source/blender/draw/engines/eevee/eevee_bloom.c @@ -92,7 +92,7 @@ int EEVEE_bloom_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - if (scene_eval->flag & SCE_EEVEE_BLOOM_ENABLED) { + if (scene_eval->eevee.flag & SCE_EEVEE_BLOOM_ENABLED) { const float *viewport_size = DRW_viewport_size_get(); /* Shaders */ diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c index c275a5005ff..60c6175f4fa 100644 --- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c +++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c @@ -84,7 +84,7 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - if (scene_eval->flag & SCE_EEVEE_DOF_ENABLED) { + if (scene_eval->eevee.flag & SCE_EEVEE_DOF_ENABLED) { RegionView3D *rv3d = draw_ctx->rv3d; if (!e_data.dof_downsample_sh) { diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 646c7a03afd..211a8abd42c 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -305,7 +305,8 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); { - psl->color_downsample_ps = DRW_pass_create("Downsample", DRW_STATE_WRITE_COLOR); + psl->color_downsample_ps = DRW_pass_create( + "Downsample", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_sh, psl->color_downsample_ps); DRW_shgroup_uniform_texture_ref(grp, "source", &e_data.color_src); DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1); @@ -315,7 +316,8 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { static int zero = 0; static uint six = 6; - psl->color_downsample_cube_ps = DRW_pass_create("Downsample Cube", DRW_STATE_WRITE_COLOR); + psl->color_downsample_cube_ps = DRW_pass_create( + "Downsample Cube", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_cube_sh, psl->color_downsample_cube_ps); DRW_shgroup_uniform_texture_ref(grp, "source", &e_data.color_src); DRW_shgroup_uniform_float(grp, "texelSize", &e_data.cube_texel_size, 1); @@ -327,25 +329,29 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* Perform min/max downsample */ DRWShadingGroup *grp; - psl->maxz_downlevel_ps = DRW_pass_create("HiZ Max Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS); + psl->maxz_downlevel_ps = DRW_pass_create( + "HiZ Max Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_downlevel_sh, psl->maxz_downlevel_ps); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &txl->maxzbuffer); DRW_shgroup_call_add(grp, quad, NULL); /* Copy depth buffer to halfres top level of HiZ */ - psl->maxz_downdepth_ps = DRW_pass_create("HiZ Max Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); + psl->maxz_downdepth_ps = DRW_pass_create( + "HiZ Max Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_downdepth_sh, psl->maxz_downdepth_ps); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_call_add(grp, quad, NULL); - psl->maxz_downdepth_layer_ps = DRW_pass_create("HiZ Max Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); + psl->maxz_downdepth_layer_ps = DRW_pass_create( + "HiZ Max Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_downdepth_layer_sh, psl->maxz_downdepth_layer_ps); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1); DRW_shgroup_call_add(grp, quad, NULL); - psl->maxz_copydepth_ps = DRW_pass_create("HiZ Max Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS); + psl->maxz_copydepth_ps = DRW_pass_create( + "HiZ Max Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_copydepth_sh, psl->maxz_copydepth_ps); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_call_add(grp, quad, NULL); @@ -353,7 +359,8 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) { /* This pass compute camera motions to the non moving objects. */ - psl->velocity_resolve = DRW_pass_create("Velocity Resolve", DRW_STATE_WRITE_COLOR); + psl->velocity_resolve = DRW_pass_create( + "Velocity Resolve", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.velocity_resolve_sh, psl->velocity_resolve); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); @@ -504,6 +511,13 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) /* Save the final texture and framebuffer for final transformation or read. */ effects->final_tx = effects->source_buffer; effects->final_fb = (effects->target_buffer != fbl->main_color_fb) ? fbl->main_fb : fbl->effect_fb; + if ((effects->enabled_effects & EFFECT_TAA) && (effects->enabled_effects & (EFFECT_BLOOM | EFFECT_DOF | EFFECT_MOTION_BLUR)) == 0) { + if (!effects->swap_double_buffer) { + effects->final_fb = fbl->double_buffer_fb; + } else { + effects->final_fb = fbl->main_fb; + } + } /* If no post processes is enabled, buffers are still not swapped, do it now. */ SWAP_DOUBLE_BUFFERS(); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 8448393aa97..f6776d43665 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -187,7 +187,6 @@ static void eevee_draw_background(void *vedata) /* Default framebuffer and texture */ DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - /* Sort transparents before the loop. */ DRW_pass_sort_shgroup_z(psl->transparent_pass); @@ -310,6 +309,11 @@ static void eevee_draw_background(void *vedata) } } + /* LookDev */ + EEVEE_lookdev_draw_background(vedata); + /* END */ + + /* Tonemapping and transfer result to default framebuffer. */ GPU_framebuffer_bind(dfbl->default_fb); DRW_transform_to_display(stl->effects->final_tx); diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index d2faeb6ed39..c7a2951a670 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -71,6 +71,7 @@ static struct { struct GPUShader *probe_default_sh; + struct GPUShader *probe_default_studiolight_sh; struct GPUShader *probe_filter_glossy_sh; struct GPUShader *probe_filter_diffuse_sh; struct GPUShader *probe_filter_visibility_sh; @@ -214,6 +215,9 @@ static void lightprobe_shaders_init(void) e_data.probe_default_sh = DRW_shader_create( datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, NULL); + e_data.probe_default_studiolight_sh = DRW_shader_create( + datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, "#define LOOKDEV\n"); + MEM_freeN(shader_str); shader_str = BLI_string_joinN( @@ -411,7 +415,11 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat World *wo = scene->world; float *col = ts.colorBackground; - if (wo) { + + /* LookDev */ + EEVEE_lookdev_cache_init(vedata, &grp, e_data.probe_default_studiolight_sh, psl->probe_background, pinfo); + /* END */ + if (!grp && wo) { col = &wo->horr; bool wo_sh_compiled = true; @@ -445,6 +453,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat if (wo->update_flag != 0 || pinfo->prev_world != wo || pinfo->prev_wo_sh_compiled != wo_sh_compiled) { pinfo->update_world |= PROBE_UPDATE_ALL; + pinfo->studiolight_index = 0; pinfo->prev_wo_sh_compiled = wo_sh_compiled; pinfo->prev_world = wo; } @@ -452,6 +461,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat } else if (pinfo->prev_world) { pinfo->update_world |= PROBE_UPDATE_ALL; + pinfo->studiolight_index = 0; pinfo->prev_wo_sh_compiled = false; pinfo->prev_world = NULL; } @@ -1830,6 +1840,7 @@ void EEVEE_lightprobes_free(void) MEM_SAFE_FREE(e_data.format_probe_display_cube); MEM_SAFE_FREE(e_data.format_probe_display_planar); DRW_SHADER_FREE_SAFE(e_data.probe_default_sh); + DRW_SHADER_FREE_SAFE(e_data.probe_default_studiolight_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_visibility_sh); diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 123dabbe226..dd69e19e7c1 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -82,7 +82,8 @@ static bool lightbits_get(const EEVEE_LightBits *r, uint idx) return r->fields[idx / 8] & (1 << (idx % 8)); } -static void lightbits_convert(EEVEE_LightBits *r, const EEVEE_LightBits *bitf, const int *light_bit_conv_table, uint table_length) +static void lightbits_convert( + EEVEE_LightBits *r, const EEVEE_LightBits *bitf, const int *light_bit_conv_table, uint table_length) { for (int i = 0; i < table_length; ++i) { if (lightbits_get(bitf, i) != 0) { @@ -591,7 +592,7 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) } else if (la->type == LA_AREA) { evli->sizex = max_ff(0.0001f, la->area_size * scale[0] * 0.5f); - if (la->area_shape == LA_AREA_RECT) { + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { evli->sizey = max_ff(0.0001f, la->area_sizey * scale[1] * 0.5f); } else { @@ -602,10 +603,18 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) evli->radius = max_ff(0.001f, la->area_size); } + /* Lamp Type */ + evli->lamptype = (float)la->type; + /* Make illumination power constant */ if (la->type == LA_AREA) { power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) * /* 1/(w*h*Pi) */ 80.0f; /* XXX : Empirical, Fit cycles power */ + if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { + evli->lamptype = LAMPTYPE_AREA_ELLIPSE; + /* Scale power to account for the lower area of the ellipse compared to the surrouding rectangle. */ + power *= 4.0f / M_PI; + } } else if (la->type == LA_SPOT || la->type == LA_LOCAL) { power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) * /* 1/(4*r²*Pi²) */ @@ -620,9 +629,6 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) } mul_v3_fl(evli->color, power * la->energy); - /* Lamp Type */ - evli->lamptype = (float)la->type; - /* No shadow by default */ evli->shadowid = -1.0f; } diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c new file mode 100644 index 00000000000..4ae13669a01 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -0,0 +1,130 @@ +/* + * Copyright 2016, Blender Foundation. + * + * 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file eevee_lookdev.c + * \ingroup draw_engine + */ +#include "DRW_render.h" + +#include "BKE_camera.h" +#include "BKE_studiolight.h" + +#include "DNA_screen_types.h" + +#include "eevee_private.h" + +void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, DRWShadingGroup **grp, GPUShader *shader, DRWPass *pass, EEVEE_LightProbesInfo *pinfo) +{ + EEVEE_StorageList *stl = vedata->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + if (v3d && v3d->drawtype == OB_MATERIAL) + { + StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light, STUDIOLIGHT_ORIENTATION_WORLD); + if ((sl->flag & STUDIOLIGHT_ORIENTATION_WORLD)) { + struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); + + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_GPUTEXTURE); + *grp = DRW_shgroup_create(shader, pass); + GPUTexture *tex = sl->equirectangular_gputexture; + DRW_shgroup_uniform_texture(*grp, "image", tex); + + axis_angle_to_mat3_single(stl->g_data->studiolight_matrix, 'Z', v3d->shading.studiolight_rot_z); + DRW_shgroup_uniform_mat3(*grp, "StudioLightMatrix", stl->g_data->studiolight_matrix); + + DRW_shgroup_uniform_float(*grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); + DRW_shgroup_call_add(*grp, geom, NULL); + + /* Do we need to recalc the lightprobes? */ + if (pinfo && (pinfo->studiolight_index != sl->index || pinfo->studiolight_rot_z != v3d->shading.studiolight_rot_z)) { + pinfo->update_world |= PROBE_UPDATE_ALL; + pinfo->studiolight_index = sl->index; + pinfo->studiolight_rot_z = v3d->shading.studiolight_rot_z; + pinfo->prev_wo_sh_compiled = false; + pinfo->prev_world = NULL; + } + } + } +} + +void EEVEE_lookdev_draw_background(EEVEE_Data *vedata) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (psl->lookdev_pass && draw_ctx->v3d) { + DRW_stats_group_start("Look Dev"); + CameraParams params; + BKE_camera_params_init(¶ms); + View3D *v3d = draw_ctx->v3d; + RegionView3D *rv3d = draw_ctx->rv3d; + ARegion *ar = draw_ctx->ar; + + BKE_camera_params_from_view3d(¶ms, draw_ctx->depsgraph, v3d, rv3d); + params.is_ortho = true; + params.ortho_scale = 4.0; + params.zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; + BKE_camera_params_compute_viewplane(¶ms, ar->winx, ar->winy, 1.0f, 1.0f); + BKE_camera_params_compute_matrix(¶ms); + + const float *viewport_size = DRW_viewport_size_get(); + int viewport_inset_x = viewport_size[0]/4; + int viewport_inset_y = viewport_size[1]/4; + + EEVEE_CommonUniformBuffer *common = &sldata->common_data; + common->la_num_light = 0; + common->prb_num_planar = 0; + common->prb_num_render_cube = 1; + common->prb_num_render_grid = 1; + common->ao_dist = 0.0f; + common->ao_factor = 0.0f; + common->ao_settings = 0.0f; + DRW_uniformbuffer_update(sldata->common_ubo, common); + + /* override matrices */ + float winmat[4][4]; + float winmat_inv[4][4]; + copy_m4_m4(winmat, params.winmat); + invert_m4_m4(winmat_inv, winmat); + DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(winmat_inv, DRW_MAT_WININV); + float viewmat[4][4]; + DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); + float persmat[4][4]; + float persmat_inv[4][4]; + mul_m4_m4m4(persmat, winmat, viewmat); + invert_m4_m4(persmat_inv, persmat); + DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(persmat_inv, DRW_MAT_PERSINV); + + GPUFrameBuffer *fb = effects->final_fb; + GPU_framebuffer_bind(fb); + GPU_framebuffer_viewport_set(fb, viewport_size[0]-viewport_inset_x, 0, viewport_inset_x, viewport_inset_y); + DRW_draw_pass(psl->lookdev_pass); + + DRW_viewport_matrix_override_unset_all(); + DRW_stats_group_end(); + } +}
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index b585b1a4f85..1134c82954c 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -34,6 +34,7 @@ #include "BKE_particle.h" #include "BKE_paint.h" #include "BKE_pbvh.h" +#include "BKE_studiolight.h" #include "DNA_world_types.h" #include "DNA_modifier_types.h" @@ -54,6 +55,7 @@ static struct { struct GPUShader *default_prepass_clip_sh; struct GPUShader *default_lit[VAR_MAT_MAX]; struct GPUShader *default_background; + struct GPUShader *default_studiolight_background; struct GPUShader *update_noise_sh; /* 64*64 array texture containing all LUTs and other utilitarian arrays. @@ -320,6 +322,9 @@ static char *eevee_get_defines(int options) if (((options & VAR_MAT_VOLUME) != 0) && ((options & VAR_MAT_BLEND) != 0)) { BLI_dynstr_appendf(ds, "#define USE_ALPHA_BLEND_VOLUMETRICS\n"); } + if ((options & VAR_MAT_LOOKDEV) != 0) { + BLI_dynstr_appendf(ds, "#define LOOKDEV\n"); + } str = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); @@ -578,6 +583,10 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, E datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, NULL); + e_data.default_studiolight_background = DRW_shader_create( + datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, + "#define LOOKDEV\n"); + e_data.default_prepass_sh = DRW_shader_create( datatoc_prepass_vert_glsl, NULL, datatoc_prepass_frag_glsl, NULL); @@ -861,6 +870,35 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get( return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]); } +/** + * Create a default shading group inside the lookdev pass without standard uniforms. + **/ +static struct DRWShadingGroup *EEVEE_lookdev_shading_group_get( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, + bool use_ssr, int shadow_method) +{ + static int ssr_id; + ssr_id = (use_ssr) ? 1 : -1; + int options = VAR_MAT_MESH | VAR_MAT_LOOKDEV; + + options |= eevee_material_shadow_option(shadow_method); + + if (e_data.default_lit[options] == NULL) { + create_default_shader(options); + } + + if (vedata->psl->lookdev_pass == NULL) { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_CULL_BACK; + vedata->psl->lookdev_pass = DRW_pass_create("LookDev Pass", state); + + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->lookdev_pass); + /* XXX / WATCH: This creates non persistent binds for the ubos and textures. + * But it's currently OK because the following shgroups does not add any bind. */ + add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false); + } + + return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->lookdev_pass); +} void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; @@ -884,7 +922,11 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) float *col = ts.colorBackground; - if (wo) { + /* LookDev */ + EEVEE_lookdev_cache_init(vedata, &grp, e_data.default_studiolight_background, psl->background_pass, NULL); + /* END */ + + if (!grp && wo) { col = &wo->horr; if (wo->use_nodes && wo->nodetree) { @@ -936,7 +978,8 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_CULL_BACK; psl->depth_pass_clip_cull = DRW_pass_create("Depth Pass Cull Clip", state); - stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->depth_pass_clip_cull); + stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create( + e_data.default_prepass_clip_sh, psl->depth_pass_clip_cull); DRW_shgroup_uniform_block(stl->g_data->depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo); } @@ -952,26 +995,33 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; psl->refract_depth_pass_cull = DRW_pass_create("Refract Depth Pass Cull", state); - stl->g_data->refract_depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh, psl->refract_depth_pass_cull); + stl->g_data->refract_depth_shgrp_cull = DRW_shgroup_create( + e_data.default_prepass_sh, psl->refract_depth_pass_cull); state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE; psl->refract_depth_pass_clip = DRW_pass_create("Refract Depth Pass Clip", state); - stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip); + stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create( + e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip); DRW_shgroup_uniform_block(stl->g_data->refract_depth_shgrp_clip, "clip_block", sldata->clip_ubo); state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_CULL_BACK; psl->refract_depth_pass_clip_cull = DRW_pass_create("Refract Depth Pass Cull Clip", state); - stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull); + stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create( + e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull); DRW_shgroup_uniform_block(stl->g_data->refract_depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo); } { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE; + DRWState state = ( + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | + DRW_STATE_WIRE); psl->refract_pass = DRW_pass_create("Opaque Refraction Pass", state); } { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL; + DRWState state = ( + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | + DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL); psl->sss_pass = DRW_pass_create("Subsurface Pass", state); e_data.sss_count = 0; } @@ -1062,16 +1112,16 @@ static void material_opaque( static float half = 0.5f; /* Shading */ - *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, false, false, use_refract, - use_sss, use_translucency, linfo->shadow_method); + *gpumat = EEVEE_material_mesh_get( + scene, ma, vedata, false, false, use_refract, + use_sss, use_translucency, linfo->shadow_method); GPUMaterialStatus status_mat_surface = GPU_material_status(*gpumat); /* Alpha CLipped : Discard pixel from depth pass, then * fail the depth test for shading. */ if (ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED)) { - *gpumat_depth = EEVEE_material_mesh_depth_get(scene, ma, - (ma->blend_method == MA_BM_HASHED), false); + *gpumat_depth = EEVEE_material_mesh_depth_get(scene, ma, (ma->blend_method == MA_BM_HASHED), false); GPUMaterialStatus status_mat_depth = GPU_material_status(*gpumat_depth); if (status_mat_depth != GPU_MAT_SUCCESS) { @@ -1080,12 +1130,16 @@ static void material_opaque( status_mat_surface = status_mat_depth; } else if (use_refract) { - *shgrp_depth = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass); - *shgrp_depth_clip = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip); + *shgrp_depth = DRW_shgroup_material_create( + *gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass); + *shgrp_depth_clip = DRW_shgroup_material_create( + *gpumat_depth, (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip); } else { - *shgrp_depth = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass); - *shgrp_depth_clip = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip); + *shgrp_depth = DRW_shgroup_material_create( + *gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass); + *shgrp_depth_clip = DRW_shgroup_material_create( + *gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip); } if (*shgrp_depth != NULL) { @@ -1110,16 +1164,18 @@ static void material_opaque( static int first_ssr = 1; int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_refract) ? &first_ssr : &no_ssr; - *shgrp = DRW_shgroup_material_create(*gpumat, - (use_refract) ? psl->refract_pass : - (use_sss) ? psl->sss_pass : psl->material_pass); + *shgrp = DRW_shgroup_material_create( + *gpumat, + (use_refract) ? psl->refract_pass : + (use_sss) ? psl->sss_pass : psl->material_pass); add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false); if (use_sss) { struct GPUTexture *sss_tex_profile = NULL; - struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(*gpumat, - stl->effects->sss_sample_count, - &sss_tex_profile); + struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get( + *gpumat, + stl->effects->sss_sample_count, + &sss_tex_profile); if (sss_profile) { if (use_translucency) { @@ -1188,7 +1244,8 @@ static void material_opaque( static void material_transparent( Material *ma, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - bool do_cull, bool use_flat_nor, struct GPUMaterial **gpumat, struct DRWShadingGroup **shgrp, struct DRWShadingGroup **shgrp_depth) + bool do_cull, bool use_flat_nor, + struct GPUMaterial **gpumat, struct DRWShadingGroup **shgrp, struct DRWShadingGroup **shgrp_depth) { const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; @@ -1196,8 +1253,10 @@ static void material_transparent( EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; EEVEE_LampsInfo *linfo = sldata->lamps; - const bool use_refract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0); - + const bool use_refract = ( + ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && + ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0) + ); float *color_p = &ma->r; float *metal_p = &ma->ray_mirror; float *spec_p = &ma->spec; @@ -1209,8 +1268,9 @@ static void material_transparent( static float half = 0.5f; /* Shading */ - *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, true, (ma->blend_method == MA_BM_MULTIPLY), use_refract, - false, false, linfo->shadow_method); + *gpumat = EEVEE_material_mesh_get( + scene, ma, vedata, true, (ma->blend_method == MA_BM_MULTIPLY), use_refract, + false, false, linfo->shadow_method); switch (GPU_material_status(*gpumat)) { case GPU_MAT_SUCCESS: @@ -1251,8 +1311,11 @@ static void material_transparent( const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKSIDE) != 0); - DRWState all_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_CULL_BACK | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL | - DRW_STATE_BLEND | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY; + DRWState all_state = ( + DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_CULL_BACK | + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL | + DRW_STATE_BLEND | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY + ); DRWState cur_state = DRW_STATE_WRITE_COLOR; cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL; @@ -1383,10 +1446,11 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld char *auto_layer_names; int *auto_layer_is_srgb; int auto_layer_count; - struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len, - &auto_layer_names, - &auto_layer_is_srgb, - &auto_layer_count); + struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len, + &auto_layer_names, + &auto_layer_is_srgb, + &auto_layer_count); if (mat_geom) { for (int i = 0; i < materials_len; ++i) { EEVEE_ObjectEngineData *oedata = NULL; @@ -1440,17 +1504,20 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld struct GPUMaterial *gpumat; switch (ma->blend_shadow) { case MA_BS_SOLID: - EEVEE_lights_cache_shcaster_add(sldata, stl, mat_geom[i], ob); + EEVEE_lights_cache_shcaster_add( + sldata, stl, mat_geom[i], ob); *cast_shadow = true; break; case MA_BS_CLIP: gpumat = EEVEE_material_mesh_depth_get(scene, ma, false, true); - EEVEE_lights_cache_shcaster_material_add(sldata, psl, gpumat, mat_geom[i], ob, &ma->alpha_threshold); + EEVEE_lights_cache_shcaster_material_add( + sldata, psl, gpumat, mat_geom[i], ob, &ma->alpha_threshold); *cast_shadow = true; break; case MA_BS_HASHED: gpumat = EEVEE_material_mesh_depth_get(scene, ma, true, true); - EEVEE_lights_cache_shcaster_material_add(sldata, psl, gpumat, mat_geom[i], ob, NULL); + EEVEE_lights_cache_shcaster_material_add( + sldata, psl, gpumat, mat_geom[i], ob, NULL); *cast_shadow = true; break; case MA_BS_NONE: @@ -1563,6 +1630,45 @@ void EEVEE_materials_cache_finish(EEVEE_Data *vedata) { EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + /* Look-Dev */ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const View3D *v3d = draw_ctx->v3d; + if (v3d && v3d->drawtype == OB_MATERIAL) { + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + EEVEE_LampsInfo *linfo = sldata->lamps; + struct Gwn_Batch *sphere = DRW_cache_sphere_get(); + static float mat1[4][4]; + static float color[3] = {0.8f, 0.8f, 0.8f}; + static float metallic_on = 1.0f; + static float metallic_off = 0.00f; + static float specular_off = 0.5f; + static float specular_on = 1.0f; + static float roughness_off = 0.05f; + static float roughness_on = 1.00f; + + float view_mat[4][4]; + DRW_viewport_matrix_get(view_mat, DRW_MAT_VIEWINV); + + DRWShadingGroup *shgrp = EEVEE_lookdev_shading_group_get(sldata, vedata, false, linfo->shadow_method); + DRW_shgroup_uniform_vec3(shgrp, "basecol", color, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", &metallic_on, 1); + DRW_shgroup_uniform_float(shgrp, "specular", &specular_on, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", &roughness_off, 1); + unit_m4(mat1); + mul_m4_m4m4(mat1, mat1, view_mat); + translate_m4(mat1, -1.5f, 0.0f, -5.0f); + DRW_shgroup_call_add(shgrp, sphere, mat1); + + shgrp = EEVEE_lookdev_shading_group_get(sldata, vedata, false, linfo->shadow_method); + DRW_shgroup_uniform_vec3(shgrp, "basecol", color, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", &metallic_off, 1); + DRW_shgroup_uniform_float(shgrp, "specular", &specular_off, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", &roughness_on, 1); + translate_m4(mat1, 3.0f, 0.0f, 0.0f); + DRW_shgroup_call_add(shgrp, sphere, mat1); + } + /* END */ + BLI_ghash_free(stl->g_data->material_hash, NULL, MEM_freeN); BLI_ghash_free(stl->g_data->hair_material_hash, NULL, NULL); } @@ -1578,6 +1684,7 @@ void EEVEE_materials_free(void) DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh); DRW_SHADER_FREE_SAFE(e_data.default_prepass_clip_sh); DRW_SHADER_FREE_SAFE(e_data.default_background); + DRW_SHADER_FREE_SAFE(e_data.default_studiolight_background); DRW_SHADER_FREE_SAFE(e_data.update_noise_sh); DRW_TEXTURE_FREE_SAFE(e_data.util_tex); DRW_TEXTURE_FREE_SAFE(e_data.noise_tex); diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index 305daef87d1..f39fbe33a71 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -77,7 +77,7 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - if (scene_eval->flag & SCE_EEVEE_GTAO_ENABLED) { + if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) { const float *viewport_size = DRW_viewport_size_get(); const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; @@ -91,14 +91,14 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) common_data->ao_quality = 1.0f - scene_eval->eevee.gtao_quality; common_data->ao_settings = 1.0f; /* USE_AO */ - if (scene_eval->flag & SCE_EEVEE_GTAO_BENT_NORMALS) { + if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_BENT_NORMALS) { common_data->ao_settings += 2.0f; /* USE_BENT_NORMAL */ } - if (scene_eval->flag & SCE_EEVEE_GTAO_BOUNCE) { + if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_BOUNCE) { common_data->ao_settings += 4.0f; /* USE_DENOISE */ } - common_data->ao_bounce_fac = (scene_eval->flag & SCE_EEVEE_GTAO_BOUNCE) ? 1.0f : 0.0f; + common_data->ao_bounce_fac = (scene_eval->eevee.flag & SCE_EEVEE_GTAO_BOUNCE) ? 1.0f : 0.0f; effects->gtao_horizons = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_RGBA8, &draw_engine_eevee_type); @@ -141,7 +141,7 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - if (scene_eval->flag & SCE_EEVEE_GTAO_ENABLED) { + if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) { DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index c95e51548d0..10a53db5e35 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -101,28 +101,29 @@ enum { /* Material shader variations */ enum { - VAR_MAT_MESH = (1 << 0), - VAR_MAT_PROBE = (1 << 1), - VAR_MAT_HAIR = (1 << 2), - VAR_MAT_FLAT = (1 << 3), - VAR_MAT_BLEND = (1 << 4), - VAR_MAT_VSM = (1 << 5), - VAR_MAT_ESM = (1 << 6), - VAR_MAT_VOLUME = (1 << 7), + VAR_MAT_MESH = (1 << 0), + VAR_MAT_PROBE = (1 << 1), + VAR_MAT_HAIR = (1 << 2), + VAR_MAT_FLAT = (1 << 3), + VAR_MAT_BLEND = (1 << 4), + VAR_MAT_VSM = (1 << 5), + VAR_MAT_ESM = (1 << 6), + VAR_MAT_VOLUME = (1 << 7), + VAR_MAT_LOOKDEV = (1 << 8), /* Max number of variation */ /* IMPORTANT : Leave it last and set * it's value accordingly. */ - VAR_MAT_MAX = (1 << 8), + VAR_MAT_MAX = (1 << 9), /* These are options that are not counted in VAR_MAT_MAX * because they are not cumulative with the others above. */ - VAR_MAT_CLIP = (1 << 9), - VAR_MAT_HASH = (1 << 10), - VAR_MAT_MULT = (1 << 11), - VAR_MAT_SHADOW = (1 << 12), - VAR_MAT_REFRACT = (1 << 13), - VAR_MAT_SSS = (1 << 14), - VAR_MAT_TRANSLUC = (1 << 15), - VAR_MAT_SSSALBED = (1 << 16), + VAR_MAT_CLIP = (1 << 10), + VAR_MAT_HASH = (1 << 11), + VAR_MAT_MULT = (1 << 12), + VAR_MAT_SHADOW = (1 << 13), + VAR_MAT_REFRACT = (1 << 14), + VAR_MAT_SSS = (1 << 15), + VAR_MAT_TRANSLUC = (1 << 16), + VAR_MAT_SSSALBED = (1 << 17), }; typedef struct EEVEE_BoundSphere { @@ -205,6 +206,7 @@ typedef struct EEVEE_PassList { struct DRWPass *transparent_pass; struct DRWPass *background_pass; struct DRWPass *update_noise_pass; + struct DRWPass *lookdev_pass; } EEVEE_PassList; typedef struct EEVEE_FramebufferList { @@ -277,6 +279,7 @@ typedef struct EEVEE_StorageList { struct EEVEE_EffectsInfo *effects; struct EEVEE_PrivateData *g_data; + } EEVEE_StorageList; /* ************ LIGHT UBO ************* */ @@ -289,6 +292,9 @@ typedef struct EEVEE_Light { float forwardvec[3], lamptype; } EEVEE_Light; +/* Special type for elliptic area lamps, matches lamps_lib.glsl */ +#define LAMPTYPE_AREA_ELLIPSE 100.0f + typedef struct EEVEE_Shadow { float near, far, bias, exp; float shadow_start, data_start, multi_shadow_count, shadow_blur; @@ -449,6 +455,8 @@ typedef struct EEVEE_LightProbesInfo { float visibility_blur; float intensity_fac; int shres; + int studiolight_index; + float studiolight_rot_z; /* List of probes in the scene. */ /* XXX This is fragile, can get out of sync quickly. */ struct Object *probes_cube_ref[MAX_PROBE]; @@ -458,7 +466,7 @@ typedef struct EEVEE_LightProbesInfo { struct EEVEE_LightProbe probe_data[MAX_PROBE]; struct EEVEE_LightGrid grid_data[MAX_GRID]; struct EEVEE_PlanarReflection planar_data[MAX_PLANAR]; - /* Probe Visibility Group */ + /* Probe Visibility Collection */ EEVEE_LightProbeVisTest vis_data; } EEVEE_LightProbesInfo; @@ -780,6 +788,8 @@ typedef struct EEVEE_PrivateData { float persmat[4][4], persinv[4][4]; float viewmat[4][4], viewinv[4][4]; float winmat[4][4], wininv[4][4]; + float studiolight_matrix[3][3]; + /* Mist Settings */ float mist_start, mist_inv_dist, mist_falloff; } EEVEE_PrivateData; /* Transient data */ @@ -806,8 +816,10 @@ struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, struct struct GPUMaterial *EEVEE_material_mesh_get( struct Scene *scene, Material *ma, EEVEE_Data *vedata, bool use_blend, bool use_multiply, bool use_refract, bool use_sss, bool use_translucency, int shadow_method); -struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma); -struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, Material *ma, bool use_hashed_alpha, bool is_shadow); +struct GPUMaterial *EEVEE_material_mesh_volume_get( + struct Scene *scene, Material *ma); +struct GPUMaterial *EEVEE_material_mesh_depth_get( + struct Scene *scene, Material *ma, bool use_hashed_alpha, bool is_shadow); struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, int shadow_method); void EEVEE_materials_free(void); void EEVEE_draw_default_passes(EEVEE_PassList *psl); @@ -924,6 +936,10 @@ void EEVEE_render_cache(void *vedata, struct Object *ob, struct RenderEngine *en void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct RenderLayer *render_layer, const struct rcti *rect); void EEVEE_render_update_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer); +/** eevee_lookdev.c */ +void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, DRWShadingGroup **grp, GPUShader *shader, DRWPass *pass, EEVEE_LightProbesInfo *pinfo); +void EEVEE_lookdev_draw_background(EEVEE_Data *vedata); + /* Shadow Matrix */ static const float texcomat[4][4] = { /* From NDC to TexCo */ {0.5f, 0.0f, 0.0f, 0.0f}, diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index 1a46e0b5c33..6ee3b9cc286 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -150,7 +150,7 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - if (scene_eval->flag & SCE_EEVEE_SSS_ENABLED) { + if (scene_eval->eevee.flag & SCE_EEVEE_SSS_ENABLED) { DRW_texture_ensure_fullscreen_2D(&txl->sss_dir_accum, GPU_RGBA16F, 0); DRW_texture_ensure_fullscreen_2D(&txl->sss_col_accum, GPU_RGBA16F, 0); diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl index 55f66f5500a..9d27224b5c9 100644 --- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl @@ -184,7 +184,8 @@ void integrate_slice(vec3 normal, vec2 t_phi, vec2 horizons, inout float visibil bent_normal += vec3(sin(b_angle) * -t_phi, cos(b_angle) * 0.5); } -void gtao_deferred(vec3 normal, vec3 position, vec4 noise, float frag_depth, out float visibility, out vec3 bent_normal) +void gtao_deferred( + vec3 normal, vec3 position, vec4 noise, float frag_depth, out float visibility, out vec3 bent_normal) { /* Fetch early, hide latency! */ vec4 horizons = texelFetch(horizonBuffer, ivec2(gl_FragCoord.xy), 0); diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl index d5b54097638..aad71b3e48e 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl @@ -47,6 +47,16 @@ float direct_diffuse_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector) return ltc_evaluate_quad(corners, N); } +float direct_diffuse_ellipse(LightData ld, vec3 N, vec3 V, vec4 l_vector) +{ + vec3 points[3]; + points[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey; + points[1] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey; + points[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey; + + return ltc_evaluate_disk(N, V, mat3(1), points); +} + float direct_diffuse_unit_disc(LightData ld, vec3 N, vec3 V) { float NL = dot(N, -ld.l_forward); @@ -107,6 +117,26 @@ vec3 direct_ggx_sphere(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughn return spec; } +vec3 direct_ggx_ellipse(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) +{ + vec3 points[3]; + points[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey; + points[1] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey; + points[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey; + + vec2 uv = lut_coords(dot(N, V), sqrt(roughness)); + vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; + vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; + mat3 ltc_mat = ltc_matrix(ltc_lut); + + float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points); + bsdf *= brdf_lut.b; /* Bsdf intensity */ + + vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; + + return spec; +} + vec3 direct_ggx_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) { vec3 corners[4]; diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl index 6d941ae6ec3..fd1a10de548 100644 --- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl @@ -15,5 +15,9 @@ Closure nodetree_exec(void) Closure result = Closure(out_spec + out_diff * albedo, 1.0, vec4(ssr_spec, roughness), normal_encode(normalize(viewNormal), viewCameraVec), 0); +#ifdef LOOKDEV + gl_FragDepth = 0.0; +#endif + return result; } diff --git a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl index 90af87756f0..472d9c577b4 100644 --- a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl @@ -1,9 +1,57 @@ +#define M_PI 3.14159265358979323846 uniform float backgroundAlpha; +uniform mat4 ProjectionMatrix; +uniform mat4 ProjectionMatrixInverse; +uniform mat4 ViewMatrixInverse; +#ifdef LOOKDEV +uniform mat3 StudioLightMatrix; +uniform sampler2D image; +in vec3 viewPosition; +#else uniform vec3 color; +#endif out vec4 FragColor; +void background_transform_to_world(vec3 viewvec, out vec3 worldvec) +{ + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + worldvec = (ViewMatrixInverse * co).xyz; +} + +float hypot(float x, float y) +{ + return sqrt(x * x + y * y); +} + +void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color) +{ + vec3 nco = normalize(co); + float u = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5; + float v = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5; + + /* Fix pole bleeding */ + float half_width = 0.5 / float(textureSize(ima, 0).x); + v = clamp(v, half_width, 1.0 - half_width); + + /* Fix u = 0 seam */ + /* This is caused by texture filtering, since uv don't have smooth derivatives + * at u = 0 or 2PI, hardware filtering is using the smallest mipmap for certain + * texels. So we force the highest mipmap and don't do anisotropic filtering. */ + color = textureLod(ima, vec2(u, v), 0.0); +} + void main() { - FragColor = vec4(color, backgroundAlpha); +#ifdef LOOKDEV + vec3 worldvec; + vec4 color; + background_transform_to_world(viewPosition, worldvec); + node_tex_environment_equirectangular(StudioLightMatrix * worldvec, image, color); +#endif + + FragColor = vec4(clamp(color.rgb, vec3(0.0), vec3(1e10)), backgroundAlpha); } diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl index 198a05ccf97..0e6f976187a 100644 --- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl @@ -15,11 +15,13 @@ layout(std140) uniform light_block { }; /* type */ -#define POINT 0.0 -#define SUN 1.0 -#define SPOT 2.0 -#define HEMI 3.0 -#define AREA 4.0 +#define POINT 0.0 +#define SUN 1.0 +#define SPOT 2.0 +#define HEMI 3.0 +#define AREA_RECT 4.0 +/* Used to define the area lamp shape, doesn't directly correspond to a Blender lamp type. */ +#define AREA_ELLIPSE 100.0 #if defined(SHADOW_VSM) #define ShadowSample vec2 @@ -174,7 +176,7 @@ float light_visibility(LightData ld, vec3 W, vis *= spotmask; vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); } - else if (ld.l_type == AREA) { + else if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); } @@ -253,9 +255,12 @@ float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector) if (ld.l_type == SUN) { return direct_diffuse_unit_disc(ld, N, V); } - else if (ld.l_type == AREA) { + else if (ld.l_type == AREA_RECT) { return direct_diffuse_rectangle(ld, N, V, l_vector); } + else if (ld.l_type == AREA_ELLIPSE) { + return direct_diffuse_ellipse(ld, N, V, l_vector); + } else { return direct_diffuse_sphere(ld, N, l_vector); } @@ -275,9 +280,12 @@ vec3 light_specular(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness if (ld.l_type == SUN) { return direct_ggx_unit_disc(ld, N, V, roughness, f0); } - else if (ld.l_type == AREA) { + else if (ld.l_type == AREA_RECT) { return direct_ggx_rectangle(ld, N, V, l_vector, roughness, f0); } + else if (ld.l_type == AREA_ELLIPSE) { + return direct_ggx_ellipse(ld, N, V, l_vector, roughness, f0); + } else { return direct_ggx_sphere(ld, N, V, l_vector, roughness, f0); } @@ -373,8 +381,11 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale) /* XXX : Removing Area Power. */ /* TODO : put this out of the shader. */ float falloff; - if (ld.l_type == AREA) { + if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { vis *= (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0); + if (ld.l_type == AREA_ELLIPSE) { + vis *= M_PI * 0.25; + } vis *= 0.3 * 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */ vis /= (l_vector.w * l_vector.w); falloff = dot(N, l_vector.xyz / l_vector.w); @@ -412,7 +423,7 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale) vis *= spotmask; vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); } - else if (ld.l_type == AREA) { + else if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); } } diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl index 6c1571d5306..0ffc0cc4b49 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl @@ -120,7 +120,8 @@ float probe_attenuation_planar(PlanarData pd, vec3 W, vec3 N, float roughness) vec2 dist_to_clip; dist_to_clip.x = dot(pd.pl_clip_pos_x, W); dist_to_clip.y = dot(pd.pl_clip_pos_y, W); - fac *= step(2.0, dot(step(pd.pl_clip_edges, dist_to_clip.xxyy), vec2(-1.0, 1.0).xyxy)); /* compare and add all tests */ + /* compare and add all tests */ + fac *= step(2.0, dot(step(pd.pl_clip_edges, dist_to_clip.xxyy), vec2(-1.0, 1.0).xyxy)); /* Decrease influence for high roughness */ fac *= saturate(1.0 - roughness * 10.0); diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl index aa1dda6b3b5..d035a4329b1 100644 --- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -61,7 +61,8 @@ float refine_isect(float prev_delta, float curr_delta) return saturate(prev_delta / (prev_delta - curr_delta)); } -void prepare_raycast(vec3 ray_origin, vec3 ray_dir, float thickness, out vec4 ss_step, out vec4 ss_ray, out float max_time) +void prepare_raycast( + vec3 ray_origin, vec3 ray_dir, float thickness, out vec4 ss_step, out vec4 ss_ray, out float max_time) { /* Negate the ray direction if it goes towards the camera. * This way we don't need to care if the projected point diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl index 1a8167c2830..5f641c5d490 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl @@ -66,8 +66,11 @@ vec3 light_volume(LightData ld, vec4 l_vector) /* XXX : Removing Area Power. */ /* TODO : put this out of the shader. */ /* See eevee_light_setup(). */ - if (ld.l_type == AREA) { + if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0); + if (ld.l_type == AREA_ELLIPSE) { + power *= M_PI * 0.25; + } power *= 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */ } else if (ld.l_type == SUN) { diff --git a/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl index 19838161a73..4e44f6e1914 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl @@ -7,4 +7,4 @@ void main() } else { gl_FragDepth = 1.0; } -}
\ No newline at end of file +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl index 2550f44271b..88b715f55a8 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl @@ -1,5 +1,5 @@ #define NO_OBJECT_ID uint(0) - +#define EPSILON 0.00001 /* 4x4 bayer matrix prepared for 8bit UNORM precision error. */ #define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0)) const vec4 dither_mat4x4[4] = vec4[4]( @@ -62,3 +62,10 @@ void fresnel(vec3 I, vec3 N, float ior, out float kr) // As a consequence of the conservation of energy, transmittance is given by: // kt = 1 - kr; } + +vec4 calculate_transparent_accum(vec4 premultiplied) { + float a = min(1.0, premultiplied.a) * 8.0 + 0.01; + float b = -gl_FragCoord.z * 0.95 + 1.0; + float w = clamp(a * a * a * 1e8 * b * b * b, 1e-2, 3e2); + return premultiplied * w; +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl index 2d6f78082e3..12d6296655d 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_composite_frag.glsl @@ -2,7 +2,9 @@ out vec4 fragColor; uniform usampler2D objectId; uniform sampler2D transparentAccum; +#ifdef WORKBENCH_REVEALAGE_ENABLED uniform sampler2D transparentRevealage; +#endif uniform vec2 invertedViewportSize; layout(std140) uniform world_block { @@ -15,7 +17,9 @@ void main() vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize; uint object_id = texelFetch(objectId, texel, 0).r; vec4 transparent_accum = texelFetch(transparentAccum, texel, 0); - float revealage = texelFetch(transparentRevealage, texel, 0).r; +#ifdef WORKBENCH_REVEALAGE_ENABLED + float transparent_revealage = texelFetch(transparentRevealage, texel, 0).r; +#endif vec4 color; #ifdef V3D_SHADING_OBJECT_OUTLINE @@ -27,7 +31,11 @@ void main() if (object_id == NO_OBJECT_ID) { color = vec4(background_color(world_data, uv_viewport.y), 0.0); } else { - color = transparent_accum / transparent_accum.a; +#ifdef WORKBENCH_REVEALAGE_ENABLED + color = vec4((transparent_accum.xyz / max(transparent_accum.a, EPSILON)) * (1.0 - transparent_revealage), 1.0); +#else + color = vec4(transparent_accum.xyz / max(transparent_accum.a, EPSILON), 1.0); +#endif } fragColor = vec4(mix(world_data.object_outline_color.rgb, color.xyz, outline), 1.0); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl index 6428ed44f6b..309ae063284 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl @@ -17,12 +17,7 @@ layout(std140) uniform world_block { layout(location=0) out vec4 transparentAccum; -vec4 calculate_transparent_accum(vec4 premultiplied) { - float a = min(1.0, premultiplied.a) * 8.0 + 0.01; - float b = -gl_FragCoord.z * 0.95 + 1.0; - float w = clamp(a * a * a * 1e8 * b * b * b, 1e-2, 3e2); - return vec4(premultiplied.rgb, premultiplied.a); -} + void main() { vec4 diffuse_color; @@ -47,7 +42,7 @@ void main() vec3 shaded_color = diffuse_color.rgb; #endif /* V3D_LIGHTING_STUDIO */ - float alpha = 0.1; + float alpha = 0.5 ; vec4 premultiplied = vec4(shaded_color.rgb * alpha, alpha); transparentAccum = calculate_transparent_accum(premultiplied); } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl new file mode 100644 index 00000000000..da87fe8f542 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_revealage_frag.glsl @@ -0,0 +1,7 @@ +layout(location=0) out float transparentRevealage; + +void main() +{ + transparentRevealage = 0.5; +} + diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl index 5d286bd1090..32b31718cf8 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_caps_geom.glsl @@ -4,8 +4,6 @@ #define USE_INVOC_EXT #endif -#define DOUBLE_MANIFOLD - #ifdef DOUBLE_MANIFOLD # ifdef USE_INVOC_EXT # define invoc_ct 4 diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl index ff835326236..5a31aa34932 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl @@ -4,8 +4,6 @@ #define USE_INVOC_EXT #endif -#define DOUBLE_MANIFOLD - #ifdef DOUBLE_MANIFOLD # ifdef USE_INVOC_EXT # define invoc_ct 2 diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index 9f8023b38aa..bbd8c57a5b9 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -11,7 +11,7 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) if (v3d) { wpd->shading = v3d->shading; wpd->drawtype = v3d->drawtype; - wpd->studio_light = BKE_studiolight_find(wpd->shading.studio_light); + wpd->studio_light = BKE_studiolight_find(wpd->shading.studio_light, 0); } else { memset(&wpd->shading, 0, sizeof(wpd->shading)); diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 70de6f71ae8..6a96822984d 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -49,12 +49,19 @@ // #define DEBUG_SHADOW_VOLUME +#ifdef DEBUG_SHADOW_VOLUME +# include "draw_debug.h" +#endif + static struct { struct GPUShader *prepass_sh_cache[MAX_SHADERS]; struct GPUShader *composite_sh_cache[MAX_SHADERS]; struct GPUShader *shadow_fail_sh; + struct GPUShader *shadow_fail_manifold_sh; struct GPUShader *shadow_pass_sh; + struct GPUShader *shadow_pass_manifold_sh; struct GPUShader *shadow_caps_sh; + struct GPUShader *shadow_caps_manifold_sh; struct GPUTexture *object_id_tx; /* ref only, not alloced */ struct GPUTexture *color_buffer_tx; /* ref only, not alloced */ @@ -65,7 +72,7 @@ static struct { float light_direction_vs[3]; int next_object_id; float normal_world_matrix[3][3]; -} e_data = {NULL}; +} e_data = {{NULL}}; /* Shaders */ extern char datatoc_workbench_prepass_vert_glsl[]; @@ -83,8 +90,6 @@ extern char datatoc_workbench_data_lib_glsl[]; extern char datatoc_workbench_object_outline_lib_glsl[]; extern char datatoc_workbench_world_light_lib_glsl[]; - - static char *workbench_build_composite_frag(WORKBENCH_PrivateData *wpd) { char *str = NULL; @@ -123,15 +128,14 @@ static char *workbench_build_prepass_frag(void) return str; } - - static void ensure_deferred_shaders(WORKBENCH_PrivateData *wpd, int index, int drawtype) { if (e_data.prepass_sh_cache[index] == NULL) { char *defines = workbench_material_build_defines(wpd, drawtype); char *composite_frag = workbench_build_composite_frag(wpd); char *prepass_frag = workbench_build_prepass_frag(); - e_data.prepass_sh_cache[index] = DRW_shader_create(datatoc_workbench_prepass_vert_glsl, NULL, prepass_frag, defines); + e_data.prepass_sh_cache[index] = DRW_shader_create( + datatoc_workbench_prepass_vert_glsl, NULL, prepass_frag, defines); if (drawtype == OB_SOLID) { e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines); } @@ -161,6 +165,7 @@ static void workbench_init_object_data(ObjectEngineData *engine_data) { WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)engine_data; data->object_id = e_data.next_object_id++; + data->shadow_bbox_dirty = true; } void workbench_deferred_engine_init(WORKBENCH_Data *vedata) @@ -174,26 +179,44 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) memset(e_data.prepass_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); e_data.next_object_id = 1; - #ifdef DEBUG_SHADOW_VOLUME - const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl; - #else - const char *shadow_frag = NULL; - #endif - e_data.shadow_pass_sh = DRW_shader_create( - datatoc_workbench_shadow_vert_glsl, - datatoc_workbench_shadow_geom_glsl, - shadow_frag, - "#define SHADOW_PASS\n"); - e_data.shadow_fail_sh = DRW_shader_create( - datatoc_workbench_shadow_vert_glsl, - datatoc_workbench_shadow_geom_glsl, - shadow_frag, - "#define SHADOW_FAIL\n"); - e_data.shadow_caps_sh = DRW_shader_create( - datatoc_workbench_shadow_vert_glsl, - datatoc_workbench_shadow_caps_geom_glsl, - shadow_frag, - NULL); +#ifdef DEBUG_SHADOW_VOLUME + const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl; +#else + const char *shadow_frag = NULL; +#endif + e_data.shadow_pass_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_PASS\n" + "#define DOUBLE_MANIFOLD\n"); + e_data.shadow_pass_manifold_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_PASS\n"); + e_data.shadow_fail_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n" + "#define DOUBLE_MANIFOLD\n"); + e_data.shadow_fail_manifold_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n"); + e_data.shadow_caps_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_caps_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n" + "#define DOUBLE_MANIFOLD\n"); + e_data.shadow_caps_manifold_sh = DRW_shader_create( + datatoc_workbench_shadow_vert_glsl, + datatoc_workbench_shadow_caps_geom_glsl, + shadow_frag, + "#define SHADOW_FAIL\n"); } if (!stl->g_data) { @@ -208,12 +231,16 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; e_data.object_id_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_R32UI, &draw_engine_workbench_solid); e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid); - e_data.composite_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_solid); + e_data.composite_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_solid); if (NORMAL_ENCODING_ENABLED()) { - e_data.normal_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RG16, &draw_engine_workbench_solid); - } else { - e_data.normal_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA32F, &draw_engine_workbench_solid); + e_data.normal_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RG16, &draw_engine_workbench_solid); + } + else { + e_data.normal_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA32F, &draw_engine_workbench_solid); } GPU_framebuffer_ensure_config(&fbl->prepass_fb, { @@ -242,8 +269,11 @@ void workbench_deferred_engine_free() DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); } DRW_SHADER_FREE_SAFE(e_data.shadow_pass_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_pass_manifold_sh); DRW_SHADER_FREE_SAFE(e_data.shadow_fail_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_fail_manifold_sh); DRW_SHADER_FREE_SAFE(e_data.shadow_caps_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_caps_manifold_sh); } static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp) @@ -292,7 +322,8 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) e_data.display.shadow_shift = scene->display.shadow_shift; if (SHADOW_ENABLED(wpd)) { - psl->composite_pass = DRW_pass_create("Composite", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL); + psl->composite_pass = DRW_pass_create( + "Composite", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL); grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); workbench_composite_uniforms(wpd, grp); DRW_shgroup_stencil_mask(grp, 0x00); @@ -302,23 +333,36 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) DRW_shgroup_uniform_float(grp, "shadowShift", &scene->display.shadow_shift, 1); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + /* Stencil Shadow passes. */ #ifdef DEBUG_SHADOW_VOLUME - psl->shadow_depth_pass_pass = DRW_pass_create("Shadow Debug Pass", DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); - grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); - psl->shadow_depth_fail_pass = DRW_pass_create("Shadow Debug Fail", DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); - grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); - psl->shadow_depth_fail_caps_pass = DRW_pass_create("Shadow Depth Fail Caps", DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); - grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); + DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE; + DRWState depth_fail_state = DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE; #else - psl->shadow_depth_pass_pass = DRW_pass_create("Shadow Depth Pass", DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_PASS); + DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_PASS; + DRWState depth_fail_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL; +#endif + psl->shadow_depth_pass_pass = DRW_pass_create("Shadow Pass", depth_pass_state); + psl->shadow_depth_pass_mani_pass = DRW_pass_create("Shadow Pass Mani", depth_pass_state); + psl->shadow_depth_fail_pass = DRW_pass_create("Shadow Fail", depth_fail_state); + psl->shadow_depth_fail_mani_pass = DRW_pass_create("Shadow Fail Mani", depth_fail_state); + psl->shadow_depth_fail_caps_pass = DRW_pass_create("Shadow Fail Caps", depth_fail_state); + psl->shadow_depth_fail_caps_mani_pass = DRW_pass_create("Shadow Fail Caps Mani", depth_fail_state); + +#ifndef DEBUG_SHADOW_VOLUME + grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); DRW_shgroup_stencil_mask(grp, 0xFF); - psl->shadow_depth_fail_pass = DRW_pass_create("Shadow Depth Fail", DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL); + grp = DRW_shgroup_create(e_data.shadow_pass_manifold_sh, psl->shadow_depth_pass_mani_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); DRW_shgroup_stencil_mask(grp, 0xFF); - psl->shadow_depth_fail_caps_pass = DRW_pass_create("Shadow Depth Fail Caps", DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL); + grp = DRW_shgroup_create(e_data.shadow_fail_manifold_sh, psl->shadow_depth_fail_mani_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); DRW_shgroup_stencil_mask(grp, 0xFF); + grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, psl->shadow_depth_fail_caps_mani_pass); + DRW_shgroup_stencil_mask(grp, 0xFF); psl->composite_shadow_pass = DRW_pass_create("Composite Shadow", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL); grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_shadow_pass); @@ -330,16 +374,21 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) DRW_shgroup_uniform_float(grp, "shadowShift", &scene->display.shadow_shift, 1); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); #endif + + studiolight_update_light(wpd, e_data.display.light_direction); } else { - psl->composite_pass = DRW_pass_create("Composite", DRW_STATE_WRITE_COLOR); + psl->composite_pass = DRW_pass_create( + "Composite", DRW_STATE_WRITE_COLOR); grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); workbench_composite_uniforms(wpd, grp); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); } } } -static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int drawtype) + +static WORKBENCH_MaterialData *get_or_create_material_data( + WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int drawtype) { WORKBENCH_StorageList *stl = vedata->stl; WORKBENCH_PassList *psl = vedata->psl; @@ -359,7 +408,8 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat material = BLI_ghash_lookup(wpd->material_hash, SET_UINT_IN_POINTER(hash)); if (material == NULL) { material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); - material->shgrp = DRW_shgroup_create(drawtype == OB_SOLID ? wpd->prepass_solid_sh : wpd->prepass_texture_sh, psl->prepass_pass); + material->shgrp = DRW_shgroup_create( + drawtype == OB_SOLID ? wpd->prepass_solid_sh : wpd->prepass_texture_sh, psl->prepass_pass); DRW_shgroup_stencil_mask(material->shgrp, 0xFF); material->object_id = engine_object_data->object_id; copy_v4_v4(material->color, material_template.color); @@ -473,7 +523,8 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) gpumat_array[i] = NULL; } - struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len, NULL, NULL, NULL); + struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len, NULL, NULL, NULL); if (mat_geom) { for (int i = 0; i < materials_len; ++i) { Material *mat = give_current_material(ob, i + 1); @@ -485,7 +536,8 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) } if (SHADOW_ENABLED(wpd) && (ob->display.flag & OB_SHOW_SHADOW) > 0) { - struct Gwn_Batch *geom_shadow = DRW_cache_object_edge_detection_get(ob); + bool is_manifold; + struct Gwn_Batch *geom_shadow = DRW_cache_object_edge_detection_get(ob, &is_manifold); if (geom_shadow) { if (is_sculpt_mode) { /* Currently unsupported in sculpt mode. We could revert to the slow @@ -497,26 +549,60 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_object_engine_data_ensure( ob, &draw_engine_workbench_solid, sizeof(WORKBENCH_ObjectData), &workbench_init_object_data, NULL); - invert_m4_m4(ob->imat, ob->obmat); - mul_v3_mat3_m4v3(engine_object_data->shadow_dir, ob->imat, e_data.display.light_direction); + if (studiolight_object_cast_visible_shadow(wpd, ob, engine_object_data)) { - DRWShadingGroup *grp; - if (true) { - grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); - DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); - DRW_shgroup_call_object_add(grp, geom_shadow, ob); - } - else { - struct Gwn_Batch *geom_caps = DRW_cache_object_surface_get(ob); - if (geom_caps) { - grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); - DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); - DRW_shgroup_call_object_add(grp, geom_caps, ob); + invert_m4_m4(ob->imat, ob->obmat); + mul_v3_mat3_m4v3(engine_object_data->shadow_dir, ob->imat, e_data.display.light_direction); + + DRWShadingGroup *grp; + bool use_shadow_pass_technique = !studiolight_camera_in_object_shadow(wpd, ob, engine_object_data); + + /* Unless we expose a parameter to the user, it's better to use the depth pass technique if the object is + * non manifold. Exposing a switch to the user to force depth fail in this case can be beneficial for + * planes and non-closed terrains. */ + if (!is_manifold) { + use_shadow_pass_technique = true; } - grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); - DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); - DRW_shgroup_call_object_add(grp, geom_shadow, ob); + if (use_shadow_pass_technique) { + if (is_manifold) { + grp = DRW_shgroup_create(e_data.shadow_pass_manifold_sh, psl->shadow_depth_pass_mani_pass); + } + else { + grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass); + } + DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); + DRW_shgroup_call_add(grp, geom_shadow, ob->obmat); +#ifdef DEBUG_SHADOW_VOLUME + DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){1.0f, 0.0f, 0.0f, 1.0f}); +#endif + } + else { + /* TODO(fclem): only use caps if they are in the view frustum. */ + const bool need_caps = true; + if (need_caps) { + if (is_manifold) { + grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, psl->shadow_depth_fail_caps_mani_pass); + } + else { + grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass); + } + DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); + DRW_shgroup_call_add(grp, DRW_cache_object_surface_get(ob), ob->obmat); + } + + if (is_manifold) { + grp = DRW_shgroup_create(e_data.shadow_fail_manifold_sh, psl->shadow_depth_fail_mani_pass); + } + else { + grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass); + } + DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); + DRW_shgroup_call_add(grp, geom_shadow, ob->obmat); +#ifdef DEBUG_SHADOW_VOLUME + DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){0.0f, 1.0f, 0.0f, 1.0f}); +#endif + } } } } @@ -560,14 +646,16 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata) #ifdef DEBUG_SHADOW_VOLUME GPU_framebuffer_bind(fbl->composite_fb); DRW_draw_pass(psl->composite_pass); - DRW_draw_pass(psl->shadow_depth_pass_pass); - DRW_draw_pass(psl->shadow_depth_fail_pass); - DRW_draw_pass(psl->shadow_depth_fail_caps_pass); #else GPU_framebuffer_bind(dfbl->depth_only_fb); +#endif DRW_draw_pass(psl->shadow_depth_pass_pass); + DRW_draw_pass(psl->shadow_depth_pass_mani_pass); DRW_draw_pass(psl->shadow_depth_fail_pass); + DRW_draw_pass(psl->shadow_depth_fail_mani_pass); DRW_draw_pass(psl->shadow_depth_fail_caps_pass); + DRW_draw_pass(psl->shadow_depth_fail_caps_mani_pass); +#ifndef DEBUG_SHADOW_VOLUME GPU_framebuffer_bind(fbl->composite_fb); DRW_draw_pass(psl->composite_pass); DRW_draw_pass(psl->composite_shadow_pass); diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 823ca904415..d2c262bc4ac 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -50,21 +50,28 @@ static struct { struct GPUShader *composite_sh_cache[MAX_SHADERS]; struct GPUShader *transparent_accum_sh_cache[MAX_SHADERS]; + struct GPUShader *transparent_revealage_sh; struct GPUShader *object_outline_sh; struct GPUShader *depth_sh; struct GPUShader *checker_depth_sh; struct GPUTexture *object_id_tx; /* ref only, not alloced */ struct GPUTexture *transparent_accum_tx; /* ref only, not alloced */ +#ifdef WORKBENCH_REVEALAGE_ENABLED + struct GPUTexture *transparent_revealage_tx; /* ref only, not alloced */ +#endif struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */ int next_object_id; float normal_world_matrix[3][3]; -} e_data = {NULL}; +} e_data = {{NULL}}; /* Shaders */ extern char datatoc_workbench_forward_composite_frag_glsl[]; extern char datatoc_workbench_forward_depth_frag_glsl[]; extern char datatoc_workbench_forward_transparent_accum_frag_glsl[]; +#ifdef WORKBENCH_REVEALAGE_ENABLED +extern char datatoc_workbench_forward_transparent_revealage_frag_glsl[]; +#endif extern char datatoc_workbench_data_lib_glsl[]; extern char datatoc_workbench_background_lib_glsl[]; extern char datatoc_workbench_checkerboard_depth_frag_glsl[]; @@ -104,6 +111,22 @@ static char *workbench_build_forward_transparent_accum_frag(void) return str; } +#ifdef WORKBENCH_REVEALAGE_ENABLED +static char *workbench_build_forward_transparent_revealage_frag(void) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + + BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); + BLI_dynstr_append(ds, datatoc_workbench_forward_transparent_revealage_frag_glsl); + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; +} +#endif + static char *workbench_build_forward_composite_frag(void) { char *str = NULL; @@ -127,7 +150,8 @@ static void workbench_init_object_data(ObjectEngineData *engine_data) data->object_id = e_data.next_object_id++; } -static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int drawtype) +static WORKBENCH_MaterialData *get_or_create_material_data( + WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int drawtype) { WORKBENCH_StorageList *stl = vedata->stl; WORKBENCH_PassList *psl = vedata->psl; @@ -150,7 +174,9 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__); /* transparent accum */ - grp = DRW_shgroup_create(drawtype == OB_SOLID ? wpd->transparent_accum_sh : wpd->transparent_accum_texture_sh, psl->transparent_accum_pass); + grp = DRW_shgroup_create( + drawtype == OB_SOLID ? wpd->transparent_accum_sh : wpd->transparent_accum_texture_sh, + psl->transparent_accum_pass); DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); workbench_material_set_normal_world_matrix(grp, wpd, e_data.normal_world_matrix); copy_v4_v4(material->color, material_template.color); @@ -190,7 +216,8 @@ static void ensure_forward_shaders(WORKBENCH_PrivateData *wpd, int index, int dr if (e_data.transparent_accum_sh_cache[index] == NULL) { char *defines = workbench_material_build_defines(wpd, drawtype); char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag(); - e_data.transparent_accum_sh_cache[index] = DRW_shader_create(datatoc_workbench_prepass_vert_glsl, NULL, transparent_accum_frag, defines); + e_data.transparent_accum_sh_cache[index] = DRW_shader_create( + datatoc_workbench_prepass_vert_glsl, NULL, transparent_accum_frag, defines); MEM_freeN(transparent_accum_frag); MEM_freeN(defines); @@ -231,12 +258,21 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); memset(e_data.transparent_accum_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS); - /* XXX: forward depth does not use any defines ATM. */ char *defines = workbench_material_build_defines(wpd, OB_SOLID); char *forward_depth_frag = workbench_build_forward_depth_frag(); - e_data.object_outline_sh = DRW_shader_create(datatoc_workbench_prepass_vert_glsl, NULL, forward_depth_frag, defines); + e_data.object_outline_sh = DRW_shader_create( + datatoc_workbench_prepass_vert_glsl, NULL, forward_depth_frag, defines); + +#ifdef WORKBENCH_REVEALAGE_ENABLED + char *forward_transparent_revealage_frag = workbench_build_forward_transparent_revealage_frag(); + e_data.transparent_revealage_sh = DRW_shader_create( + datatoc_workbench_prepass_vert_glsl, NULL, forward_transparent_revealage_frag, defines); + MEM_freeN(forward_transparent_revealage_frag); +#endif + e_data.depth_sh = DRW_shader_create_3D_depth_only(); - e_data.checker_depth_sh = DRW_shader_create_fullscreen(datatoc_workbench_checkerboard_depth_frag_glsl, NULL); + e_data.checker_depth_sh = DRW_shader_create_fullscreen( + datatoc_workbench_checkerboard_depth_frag_glsl, NULL); MEM_freeN(forward_depth_frag); MEM_freeN(defines); } @@ -245,9 +281,16 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) const float *viewport_size = DRW_viewport_size_get(); const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - e_data.object_id_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_R32UI, &draw_engine_workbench_transparent); - e_data.transparent_accum_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); - e_data.composite_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); + e_data.object_id_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_R32UI, &draw_engine_workbench_transparent); + e_data.transparent_accum_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); +#ifdef WORKBENCH_REVEALAGE_ENABLED + e_data.transparent_revealage_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_R16F, &draw_engine_workbench_transparent); +#endif + e_data.composite_buffer_tx = DRW_texture_pool_query_2D( + size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent); GPU_framebuffer_ensure_config(&fbl->object_outline_fb, { GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx), @@ -256,6 +299,14 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.transparent_accum_tx), }); + +#ifdef WORKBENCH_REVEALAGE_ENABLED + GPU_framebuffer_ensure_config(&fbl->transparent_revealage_fb, { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(e_data.transparent_revealage_tx), + }); +#endif + GPU_framebuffer_ensure_config(&fbl->composite_fb, { GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx), @@ -264,6 +315,12 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) DRW_stats_group_start("Clear Buffers"); GPU_framebuffer_bind(fbl->transparent_accum_fb); GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color); + +#ifdef WORKBENCH_REVEALAGE_ENABLED + const float clear_color1[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + GPU_framebuffer_bind(fbl->transparent_revealage_fb); + GPU_framebuffer_clear_color(fbl->transparent_revealage_fb, clear_color1); +#endif GPU_framebuffer_bind(fbl->object_outline_fb); GPU_framebuffer_clear_color_depth(fbl->object_outline_fb, clear_color, 1.0f); DRW_stats_group_end(); @@ -273,6 +330,17 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) int state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE_FULL; psl->transparent_accum_pass = DRW_pass_create("Transparent Accum", state); } + +#ifdef WORKBENCH_REVEALAGE_ENABLED + /* Treansparecy Revealage */ + { + int state = DRW_STATE_WRITE_COLOR | DRW_STATE_TRANSPARENT_REVEALAGE; + psl->transparent_revealage_pass = DRW_pass_create("Transparent Revealage", state); + grp = DRW_shgroup_create(e_data.transparent_revealage_sh, psl->transparent_revealage_pass); + wpd->transparent_revealage_shgrp = grp; + } +#endif + /* Depth */ { int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; @@ -286,6 +354,9 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass); DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); DRW_shgroup_uniform_texture_ref(grp, "transparentAccum", &e_data.transparent_accum_tx); +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.transparent_revealage_tx); +#endif DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); @@ -305,6 +376,9 @@ void workbench_forward_engine_free() DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); DRW_SHADER_FREE_SAFE(e_data.transparent_accum_sh_cache[index]); } +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_SHADER_FREE_SAFE(e_data.transparent_revealage_sh); +#endif DRW_SHADER_FREE_SAFE(e_data.object_outline_sh); DRW_SHADER_FREE_SAFE(e_data.checker_depth_sh); } @@ -315,6 +389,10 @@ void workbench_forward_cache_init(WORKBENCH_Data *UNUSED(vedata)) static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, Object *ob) { +#ifdef WORKBENCH_REVEALAGE_ENABLED + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->g_data; +#endif const DRWContextState *draw_ctx = DRW_context_state_get(); if (ob == draw_ctx->object_edit) { return; @@ -335,6 +413,9 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O if (draw_as == PART_DRAW_PATH) { struct Gwn_Batch *geom = DRW_cache_particles_get_hair(ob, psys, NULL); WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, ob, NULL, NULL, OB_SOLID); +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_add(wpd->transparent_revealage_shgrp, geom, mat); +#endif DRW_shgroup_call_add(material->shgrp_object_outline, geom, mat); DRW_shgroup_call_add(material->shgrp, geom, mat); } @@ -376,6 +457,9 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) mat_drawtype = OB_TEXTURE; } material = get_or_create_material_data(vedata, ob, mat, image, mat_drawtype); +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_object_add(wpd->transparent_revealage_shgrp, geom_array[i], ob); +#endif DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob); DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); } @@ -391,10 +475,16 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); if (geom) { if (is_sculpt_mode) { +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_sculpt_add(wpd->transparent_revealage_shgrp, ob, ob->obmat); +#endif DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat); DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat); } else { +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_object_add(wpd->transparent_revealage_shgrp, geom, ob); +#endif DRW_shgroup_call_object_add(material->shgrp_object_outline, geom, ob); DRW_shgroup_call_object_add(material->shgrp, geom, ob); } @@ -407,11 +497,15 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) gpumat_array[i] = NULL; } - struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len, NULL, NULL, NULL); + struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len, NULL, NULL, NULL); if (mat_geom) { for (int i = 0; i < materials_len; ++i) { Material *mat = give_current_material(ob, i + 1); material = get_or_create_material_data(vedata, ob, mat, NULL, OB_SOLID); +#ifdef WORKBENCH_REVEALAGE_ENABLED + DRW_shgroup_call_object_add(wpd->transparent_revealage_shgrp, mat_geom[i], ob); +#endif DRW_shgroup_call_object_add(material->shgrp_object_outline, mat_geom[i], ob); DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); } @@ -450,7 +544,10 @@ void workbench_forward_draw_scene(WORKBENCH_Data *vedata) /* Shade */ GPU_framebuffer_bind(fbl->transparent_accum_fb); DRW_draw_pass(psl->transparent_accum_pass); - +#ifdef WORKBENCH_REVEALAGE_ENABLED + GPU_framebuffer_bind(fbl->transparent_revealage_fb); + DRW_draw_pass(psl->transparent_revealage_pass); +#endif /* Composite */ GPU_framebuffer_bind(fbl->composite_fb); DRW_draw_pass(psl->composite_pass); diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 9b364d8ff09..6028d3816d4 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -77,6 +77,10 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, int drawtype) BLI_dynstr_appendf(ds, "#define WORKBENCH_ENCODE_NORMALS\n"); } +#ifdef WORKBENCH_REVEALAGE_ENABLED + BLI_dynstr_appendf(ds, "#define WORKBENCH_REVEALAGE_ENABLED\n"); +#endif + str = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); return str; @@ -117,7 +121,8 @@ int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, int drawtype return index; } -void workbench_material_set_normal_world_matrix(DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]) +void workbench_material_set_normal_world_matrix( + DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]) { if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) { float view_matrix_inverse[4][4]; diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 087ed5100d9..bffac99c6d7 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -44,6 +44,7 @@ #define SHADOW_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_SHADOW) #define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (wpd->shading.light & V3D_LIGHTING_STUDIO || SHADOW_ENABLED(wpd)) #define NORMAL_ENCODING_ENABLED() (true) +#define WORKBENCH_REVEALAGE_ENABLED #define STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd) (wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD) @@ -55,6 +56,10 @@ typedef struct WORKBENCH_FramebufferList { /* Forward render buffers */ struct GPUFrameBuffer *object_outline_fb; struct GPUFrameBuffer *transparent_accum_fb; + +#ifdef WORKBENCH_REVEALAGE_ENABLED + struct GPUFrameBuffer *transparent_revealage_fb; +#endif } WORKBENCH_FramebufferList; typedef struct WORKBENCH_StorageList { @@ -65,13 +70,19 @@ typedef struct WORKBENCH_PassList { /* deferred rendering */ struct DRWPass *prepass_pass; struct DRWPass *shadow_depth_pass_pass; + struct DRWPass *shadow_depth_pass_mani_pass; struct DRWPass *shadow_depth_fail_pass; + struct DRWPass *shadow_depth_fail_mani_pass; struct DRWPass *shadow_depth_fail_caps_pass; + struct DRWPass *shadow_depth_fail_caps_mani_pass; struct DRWPass *composite_pass; struct DRWPass *composite_shadow_pass; /* forward rendering */ struct DRWPass *transparent_accum_pass; +#ifdef WORKBENCH_REVEALAGE_ENABLED + struct DRWPass *transparent_revealage_pass; +#endif struct DRWPass *object_outline_pass; struct DRWPass *depth_pass; struct DRWPass *checker_depth_pass; @@ -111,8 +122,19 @@ typedef struct WORKBENCH_PrivateData { struct GPUUniformBuffer *world_ubo; struct DRWShadingGroup *shadow_shgrp; struct DRWShadingGroup *depth_shgrp; +#ifdef WORKBENCH_REVEALAGE_ENABLED + struct DRWShadingGroup *transparent_revealage_shgrp; +#endif WORKBENCH_UBO_World world_data; float shadow_multiplier; + float cached_shadow_direction[3]; + float shadow_mat[4][4]; + float shadow_inv[4][4]; + float shadow_near_corners[4][3]; /* Near plane corners in shadow space. */ + float shadow_near_min[3]; /* min and max of shadow_near_corners. allow fast test */ + float shadow_near_max[3]; + float shadow_near_sides[2][4]; /* This is a parallelogram, so only 2 normal and distance to the edges. */ + bool shadow_changed; } WORKBENCH_PrivateData; /* Transient data */ typedef struct WORKBENCH_MaterialData { @@ -137,6 +159,9 @@ typedef struct WORKBENCH_ObjectData { int recalc; /* Shadow direction in local object space. */ float shadow_dir[3]; + float shadow_min[3], shadow_max[3]; /* Min, max in shadow space */ + BoundBox shadow_bbox; + bool shadow_bbox_dirty; int object_id; } WORKBENCH_ObjectData; @@ -172,10 +197,14 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, int drawtype) void workbench_material_get_solid_color(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, float *color); uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template); int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, int drawtype); -void workbench_material_set_normal_world_matrix(DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]); +void workbench_material_set_normal_world_matrix( + DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3]); /* workbench_studiolight.c */ void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd); +void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3]); +bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed); +bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed); /* workbench_data.c */ void workbench_private_data_init(WORKBENCH_PrivateData *wpd); diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c index 2142be3eaf4..4db89717b2a 100644 --- a/source/blender/draw/engines/workbench/workbench_studiolight.c +++ b/source/blender/draw/engines/workbench/workbench_studiolight.c @@ -27,7 +27,10 @@ #include "DRW_engine.h" #include "workbench_private.h" +#include "BKE_object.h" + #include "BLI_math.h" +#include "BKE_global.h" void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd) { @@ -40,3 +43,139 @@ void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd) copy_v3_v3(wd->diffuse_light_z_pos, sl->diffuse_light[STUDIOLIGHT_Z_POS]); copy_v3_v3(wd->diffuse_light_z_neg, sl->diffuse_light[STUDIOLIGHT_Z_NEG]); } + +static void compute_parallel_lines_nor_and_dist(const float v1[2], const float v2[2], const float v3[2], float r_line[2]) +{ + sub_v2_v2v2(r_line, v2, v1); + /* Find orthogonal vector. */ + SWAP(float, r_line[0], r_line[1]); + r_line[0] = -r_line[0]; + /* Edge distances. */ + r_line[2] = dot_v2v2(r_line, v1); + r_line[3] = dot_v2v2(r_line, v3); + /* Make sure r_line[2] is the minimum. */ + if (r_line[2] > r_line[3]) { + SWAP(float, r_line[2], r_line[3]); + } +} + +void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3]) +{ + wpd->shadow_changed = !compare_v3v3(wpd->cached_shadow_direction, light_direction, 1e-5f); + + if (wpd->shadow_changed) { + float up[3] = {0.0f, 0.0f, 1.0f}; + unit_m4(wpd->shadow_mat); + + /* TODO fix singularity. */ + copy_v3_v3(wpd->shadow_mat[2], light_direction); + cross_v3_v3v3(wpd->shadow_mat[0], wpd->shadow_mat[2], up); + normalize_v3(wpd->shadow_mat[0]); + cross_v3_v3v3(wpd->shadow_mat[1], wpd->shadow_mat[2], wpd->shadow_mat[0]); + + invert_m4_m4(wpd->shadow_inv, wpd->shadow_mat); + + copy_v3_v3(wpd->cached_shadow_direction, light_direction); + + } + + BoundBox frustum_corners; + DRW_culling_frustum_corners_get(&frustum_corners); + + mul_v3_mat3_m4v3(wpd->shadow_near_corners[0], wpd->shadow_inv, frustum_corners.vec[0]); + mul_v3_mat3_m4v3(wpd->shadow_near_corners[1], wpd->shadow_inv, frustum_corners.vec[3]); + mul_v3_mat3_m4v3(wpd->shadow_near_corners[2], wpd->shadow_inv, frustum_corners.vec[7]); + mul_v3_mat3_m4v3(wpd->shadow_near_corners[3], wpd->shadow_inv, frustum_corners.vec[4]); + + INIT_MINMAX(wpd->shadow_near_min, wpd->shadow_near_max); + for (int i = 0; i < 4; ++i) { + minmax_v3v3_v3(wpd->shadow_near_min, wpd->shadow_near_max, wpd->shadow_near_corners[i]); + } + + compute_parallel_lines_nor_and_dist(wpd->shadow_near_corners[0], wpd->shadow_near_corners[1], wpd->shadow_near_corners[2], wpd->shadow_near_sides[0]); + compute_parallel_lines_nor_and_dist(wpd->shadow_near_corners[1], wpd->shadow_near_corners[2], wpd->shadow_near_corners[0], wpd->shadow_near_sides[1]); +} + +static BoundBox *studiolight_object_shadow_bbox_get(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +{ + if ((oed->shadow_bbox_dirty) || (wpd->shadow_changed)) { + float tmp_mat[4][4]; + mul_m4_m4m4(tmp_mat, wpd->shadow_inv, ob->obmat); + + /* Get AABB in shadow space. */ + INIT_MINMAX(oed->shadow_min, oed->shadow_max); + + /* From object space to shadow space */ + BoundBox *bbox = BKE_object_boundbox_get(ob); + for (int i = 0; i < 8; ++i) { + float corner[3]; + mul_v3_m4v3(corner, tmp_mat, bbox->vec[i]); + minmax_v3v3_v3(oed->shadow_min, oed->shadow_max, corner); + } + /* Extend towards infinity. */ + oed->shadow_max[2] += 1e4; + + /* Get extended AABB in world space. */ + BKE_boundbox_init_from_minmax(&oed->shadow_bbox, oed->shadow_min, oed->shadow_max); + for (int i = 0; i < 8; ++i) { + mul_m4_v3(wpd->shadow_mat, oed->shadow_bbox.vec[i]); + } + } + + return &oed->shadow_bbox; +} + +bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +{ + BoundBox *shadow_bbox = studiolight_object_shadow_bbox_get(wpd, ob, oed); + return DRW_culling_box_test(shadow_bbox); +} + +bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed) +{ + /* Just to be sure the min, max are updated. */ + studiolight_object_shadow_bbox_get(wpd, ob, oed); + + /* Test if near plane is in front of the shadow. */ + if (oed->shadow_min[2] > wpd->shadow_near_max[2]) { + return false; + } + + /* Separation Axis Theorem test */ + + /* Test bbox sides first (faster) */ + if ((oed->shadow_min[0] > wpd->shadow_near_max[0]) || + (oed->shadow_max[0] < wpd->shadow_near_min[0]) || + (oed->shadow_min[1] > wpd->shadow_near_max[1]) || + (oed->shadow_max[1] < wpd->shadow_near_min[1])) + { + return false; + } + + /* Test projected near rectangle sides */ + float pts[4][2] = { + {oed->shadow_min[0], oed->shadow_min[1]}, + {oed->shadow_min[0], oed->shadow_max[1]}, + {oed->shadow_max[0], oed->shadow_min[1]}, + {oed->shadow_max[0], oed->shadow_max[1]} + }; + + for (int i = 0; i < 2; ++i) { + float min_dst = FLT_MAX, max_dst = -FLT_MAX; + for (int j = 0; j < 4; ++j) { + float dst = dot_v2v2(wpd->shadow_near_sides[i], pts[j]); + /* Do min max */ + if (min_dst > dst) min_dst = dst; + if (max_dst < dst) max_dst = dst; + } + + if ((wpd->shadow_near_sides[i][2] > max_dst) || + (wpd->shadow_near_sides[i][3] < min_dst)) + { + return false; + } + } + + /* No separation axis found. Both shape intersect. */ + return true; +} diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 8af3e6c7859..25806062f68 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -152,7 +152,9 @@ typedef struct DrawEngineType { void (*view_update)(void *vedata); void (*id_update)(void *vedata, struct ID *id); - void (*render_to_image)(void *vedata, struct RenderEngine *engine, struct RenderLayer *layer, const struct rcti *rect); + void (*render_to_image)( + void *vedata, struct RenderEngine *engine, + struct RenderLayer *layer, const struct rcti *rect); } DrawEngineType; #ifndef __DRW_ENGINE_H__ @@ -280,6 +282,7 @@ typedef enum { DRW_STATE_BLEND_PREMUL = (1 << 21), /* Use that if color is already premult by alpha. */ DRW_STATE_WIRE_SMOOTH = (1 << 22), DRW_STATE_TRANS_FEEDBACK = (1 << 23), + DRW_STATE_TRANSPARENT_REVEALAGE = (1 << 24), DRW_STATE_WRITE_STENCIL = (1 << 27), DRW_STATE_WRITE_STENCIL_SHADOW_PASS = (1 << 28), @@ -317,10 +320,14 @@ DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(struct GPUMaterial DRWShadingGroup *DRW_shgroup_instance_create( struct GPUShader *shader, DRWPass *pass, struct Gwn_Batch *geom, struct Gwn_VertFormat *format); DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass); -DRWShadingGroup *DRW_shgroup_line_batch_create_with_format(struct GPUShader *shader, DRWPass *pass, struct Gwn_VertFormat *format); -DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass); -DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DRWPass *pass, int size); -DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, DRWPass *pass, struct Gwn_VertBuf *tf_target); +DRWShadingGroup *DRW_shgroup_line_batch_create_with_format( + struct GPUShader *shader, DRWPass *pass, struct Gwn_VertFormat *format); +DRWShadingGroup *DRW_shgroup_line_batch_create( + struct GPUShader *shader, DRWPass *pass); +DRWShadingGroup *DRW_shgroup_empty_tri_batch_create( + struct GPUShader *shader, DRWPass *pass, int size); +DRWShadingGroup *DRW_shgroup_transform_feedback_create( + struct GPUShader *shader, DRWPass *pass, struct Gwn_VertBuf *tf_target); typedef void (DRWCallGenerateFn)( DRWShadingGroup *shgroup, @@ -439,8 +446,10 @@ void DRW_render_instance_buffer_finish(void); /* ViewLayers */ void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type); -void **DRW_view_layer_engine_data_ensure_ex(struct ViewLayer *view_layer, DrawEngineType *engine_type, void (*callback)(void *storage)); -void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type, void (*callback)(void *storage)); +void **DRW_view_layer_engine_data_ensure_ex( + struct ViewLayer *view_layer, DrawEngineType *engine_type, void (*callback)(void *storage)); +void **DRW_view_layer_engine_data_ensure( + DrawEngineType *engine_type, void (*callback)(void *storage)); /* Objects */ ObjectEngineData *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type); @@ -488,6 +497,8 @@ bool DRW_culling_sphere_test(BoundSphere *bsphere); bool DRW_culling_box_test(BoundBox *bbox); bool DRW_culling_plane_test(float plane[4]); +void DRW_culling_frustum_corners_get(BoundBox *corners); + /* Selection */ void DRW_select_load_id(uint id); diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index ed2b52700d9..ed9bb6f8ca9 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -134,7 +134,7 @@ static void drw_shgroup_bone_octahedral( const float bone_color[4], const float hint_color[4], const float outline_color[4]) { if (g_data.bone_octahedral_outline == NULL) { - struct Gwn_Batch *geom = DRW_cache_bone_octahedral_get(); + struct Gwn_Batch *geom = DRW_cache_bone_octahedral_wire_get(); g_data.bone_octahedral_outline = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom); } if (g_data.bone_octahedral_solid == NULL) { @@ -155,7 +155,7 @@ static void drw_shgroup_bone_box( const float bone_color[4], const float hint_color[4], const float outline_color[4]) { if (g_data.bone_box_wire == NULL) { - struct Gwn_Batch *geom = DRW_cache_bone_box_get(); + struct Gwn_Batch *geom = DRW_cache_bone_box_wire_get(); g_data.bone_box_outline = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom); } if (g_data.bone_box_solid == NULL) { @@ -313,19 +313,32 @@ static void drw_shgroup_bone_envelope( /* Custom (geometry) */ -static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4], const float color[4], Object *custom) +static void drw_shgroup_bone_custom_solid( + const float (*bone_mat)[4], + const float bone_color[4], const float hint_color[4], const float outline_color[4], + Object *custom) { /* grr, not re-using instances! */ struct Gwn_Batch *geom = DRW_cache_object_surface_get(custom); if (geom) { - DRWShadingGroup *shgrp_geom_solid = shgroup_instance_solid(g_data.passes.bone_solid, geom); + DRWShadingGroup *shgrp_geom_solid = shgroup_instance_bone_shape_solid(g_data.passes.bone_solid, geom); + float final_bonemat[4][4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, bone_color, hint_color); + } + + geom = DRW_cache_object_edge_detection_get(custom, NULL); + if (geom && outline_color[3] > 0.0f) { + DRWShadingGroup *shgrp_geom_wire = shgroup_instance_bone_shape_outline(g_data.passes.bone_outline, geom); float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); - DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, color); + DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, outline_color); } } -static void drw_shgroup_bone_custom_wire(const float (*bone_mat)[4], const float color[4], Object *custom) +static void drw_shgroup_bone_custom_wire( + const float (*bone_mat)[4], + const float color[4], Object *custom) { /* grr, not re-using instances! */ struct Gwn_Batch *geom = DRW_cache_object_wire_outline_get(custom); @@ -373,7 +386,8 @@ static void drw_shgroup_bone_axes(const float (*bone_mat)[4], const float color[ static void drw_shgroup_bone_relationship_lines(const float start[3], const float end[3]) { if (g_data.lines_relationship == NULL) { - g_data.lines_relationship = shgroup_dynlines_dashed_uniform_color(g_data.passes.relationship_lines, g_theme.wire_color); + g_data.lines_relationship = shgroup_dynlines_dashed_uniform_color( + g_data.passes.relationship_lines, g_theme.wire_color); } /* reverse order to have less stipple overlap */ float v[3]; @@ -956,7 +970,8 @@ static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_S size_to_mat4(bscalemat, bscale); - /* Note: don't multiply by inverse scale mat here, as it causes problems with scaling shearing and breaking segment chains */ + /* Note: don't multiply by inverse scale mat here, + * as it causes problems with scaling shearing and breaking segment chains */ mul_m4_series(result_array[a], result_array[a], bscalemat); } } @@ -1055,7 +1070,8 @@ static void draw_axes(EditBone *eBone, bPoseChannel *pchan) const float *col = (g_theme.const_color) ? g_theme.const_color : (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? g_theme.text_hi_color : g_theme.text_color; copy_v4_v4(final_col, col); - final_col[3] = (g_theme.const_color) ? 1.0 : (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? 0.3 : 0.8; /* Mix with axes color. */ + /* Mix with axes color. */ + final_col[3] = (g_theme.const_color) ? 1.0 : (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? 0.3 : 0.8; drw_shgroup_bone_axes(BONE_VAR(eBone, pchan, disp_mat), final_col); } @@ -1107,8 +1123,9 @@ static void draw_points( if (eBone) { if (!((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))) { if (is_envelope_draw) { - drw_shgroup_bone_envelope(eBone->disp_mat, col_solid_root, col_hint_root, col_wire_root, - &eBone->rad_head, &envelope_ignore); + drw_shgroup_bone_envelope( + eBone->disp_mat, col_solid_root, col_hint_root, col_wire_root, + &eBone->rad_head, &envelope_ignore); } else { drw_shgroup_bone_point(eBone->disp_mat, col_solid_root, col_hint_root, col_wire_root); @@ -1119,8 +1136,9 @@ static void draw_points( Bone *bone = pchan->bone; if (!((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))) { if (is_envelope_draw) { - drw_shgroup_bone_envelope(pchan->disp_mat, col_solid_root, col_hint_root, col_wire_root, - &bone->rad_head, &envelope_ignore); + drw_shgroup_bone_envelope( + pchan->disp_mat, col_solid_root, col_hint_root, col_wire_root, + &bone->rad_head, &envelope_ignore); } else { drw_shgroup_bone_point(pchan->disp_mat, col_solid_root, col_hint_root, col_wire_root); @@ -1137,7 +1155,8 @@ static void draw_points( if (is_envelope_draw) { const float *rad_tail = eBone ? &eBone->rad_tail : &pchan->bone->rad_tail; drw_shgroup_bone_envelope( - BONE_VAR(eBone, pchan, disp_mat), col_solid_tail, col_hint_tail, col_wire_tail, &envelope_ignore, rad_tail); + BONE_VAR(eBone, pchan, disp_mat), col_solid_tail, col_hint_tail, col_wire_tail, + &envelope_ignore, rad_tail); } else { drw_shgroup_bone_point(BONE_VAR(eBone, pchan, disp_tail_mat), col_solid_tail, col_hint_tail, col_wire_tail); @@ -1163,6 +1182,7 @@ static void draw_bone_custom_shape( { const float *col_solid = get_bone_solid_color(eBone, pchan, arm, boneflag, constflag); const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag); + const float *col_hint = get_bone_hint_color(eBone, pchan, arm, boneflag, constflag); const float (*disp_mat)[4] = pchan->disp_mat; if (select_id != -1) { @@ -1170,9 +1190,11 @@ static void draw_bone_custom_shape( } if ((boneflag & BONE_DRAWWIRE) == 0) { - drw_shgroup_bone_custom_solid(disp_mat, col_solid, pchan->custom); + drw_shgroup_bone_custom_solid(disp_mat, col_solid, col_hint, col_wire, pchan->custom); + } + else { + drw_shgroup_bone_custom_wire(disp_mat, col_wire, pchan->custom); } - drw_shgroup_bone_custom_wire(disp_mat, col_wire, pchan->custom); if (select_id != -1) { DRW_select_load_id(-1); @@ -1211,7 +1233,9 @@ static void draw_bone_envelope( DRW_select_load_id(select_id | BONESEL_BONE); } - drw_shgroup_bone_envelope(BONE_VAR(eBone, pchan, disp_mat), col_solid, col_hint, col_wire, rad_head, rad_tail); + drw_shgroup_bone_envelope( + BONE_VAR(eBone, pchan, disp_mat), col_solid, col_hint, col_wire, + rad_head, rad_tail); if (select_id != -1) { DRW_select_load_id(-1); diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 6065e7f0fc5..b08735860c9 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -72,7 +72,8 @@ static struct DRWShapeCache { Gwn_Batch *drw_lamp; Gwn_Batch *drw_lamp_shadows; Gwn_Batch *drw_lamp_sunrays; - Gwn_Batch *drw_lamp_area; + Gwn_Batch *drw_lamp_area_square; + Gwn_Batch *drw_lamp_area_disk; Gwn_Batch *drw_lamp_hemi; Gwn_Batch *drw_lamp_spot; Gwn_Batch *drw_lamp_spot_square; @@ -502,11 +503,11 @@ Gwn_Batch *DRW_cache_object_wire_outline_get(Object *ob) } /* Returns a buffer texture. */ -Gwn_Batch *DRW_cache_object_edge_detection_get(Object *ob) +Gwn_Batch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold) { switch (ob->type) { case OB_MESH: - return DRW_cache_mesh_edge_detection_get(ob); + return DRW_cache_mesh_edge_detection_get(ob, r_is_manifold); /* TODO, should match 'DRW_cache_object_surface_get' */ default: @@ -1122,9 +1123,9 @@ Gwn_Batch *DRW_cache_lamp_sunrays_get(void) return SHC.drw_lamp_sunrays; } -Gwn_Batch *DRW_cache_lamp_area_get(void) +Gwn_Batch *DRW_cache_lamp_area_square_get(void) { - if (!SHC.drw_lamp_area) { + if (!SHC.drw_lamp_area_square) { float v1[3] = {0.0f, 0.0f, 0.0f}; /* Position Only 3D format */ @@ -1151,9 +1152,40 @@ Gwn_Batch *DRW_cache_lamp_area_get(void) v1[1] = 0.5f; GWN_vertbuf_attr_set(vbo, attr_id.pos, 7, v1); - SHC.drw_lamp_area = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + SHC.drw_lamp_area_square = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); } - return SHC.drw_lamp_area; + return SHC.drw_lamp_area_square; +} + +Gwn_Batch *DRW_cache_lamp_area_disk_get(void) +{ +#define NSEGMENTS 32 + if (!SHC.drw_lamp_area_disk) { + /* Position Only 3D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + } + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, 2 * NSEGMENTS); + + float v[3] = {0.0f, 0.5f, 0.0f}; + GWN_vertbuf_attr_set(vbo, attr_id.pos, 0, v); + for (int a = 1; a < NSEGMENTS; a++) { + v[0] = 0.5f * sinf(2.0f * (float)M_PI * a / NSEGMENTS); + v[1] = 0.5f * cosf(2.0f * (float)M_PI * a / NSEGMENTS); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * a - 1, v); + GWN_vertbuf_attr_set(vbo, attr_id.pos, 2 * a, v); + } + copy_v3_fl3(v, 0.0f, 0.5f, 0.0f); + GWN_vertbuf_attr_set(vbo, attr_id.pos, (2 * NSEGMENTS) - 1, v); + + SHC.drw_lamp_area_disk = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO); + } + return SHC.drw_lamp_area_disk; +#undef NSEGMENTS } Gwn_Batch *DRW_cache_lamp_hemi_get(void) @@ -1562,6 +1594,7 @@ static const float bone_octahedral_smooth_normals[6][3] = { }; #if 0 /* UNUSED */ + static const uint bone_octahedral_wire[24] = { 0, 1, 1, 5, 5, 3, 3, 0, 0, 4, 4, 5, 5, 2, 2, 0, @@ -1600,6 +1633,13 @@ static const uint bone_octahedral_solid_tris[8][3] = { * the first vertex of the first face aka. vertex 2): * {0, 12, 1, 10, 2, 3} **/ +static const uint bone_octahedral_wire_lines_adjacency[12][4] = { + { 0, 1, 2, 6}, { 0, 12, 1, 6}, { 0, 3, 12, 6}, { 0, 2, 3, 6}, + { 1, 6, 2, 3}, { 1, 12, 6, 3}, { 1, 0, 12, 3}, { 1, 2, 0, 3}, + { 2, 0, 1, 12}, { 2, 3, 0, 12}, { 2, 6, 3, 12}, { 2, 1, 6, 12}, +}; + +#if 0 /* UNUSED */ static const uint bone_octahedral_solid_tris_adjacency[8][6] = { { 0, 12, 1, 10, 2, 3}, { 3, 15, 4, 1, 5, 6}, @@ -1611,6 +1651,7 @@ static const uint bone_octahedral_solid_tris_adjacency[8][6] = { {18, 16, 19, 8, 20, 23}, {21, 19, 22, 11, 23, 14}, }; +#endif /* aligned with bone_octahedral_solid_tris */ static const float bone_octahedral_solid_normals[8][3] = { @@ -1641,30 +1682,43 @@ Gwn_Batch *DRW_cache_bone_octahedral_get(void) Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); GWN_vertbuf_data_alloc(vbo, 24); - Gwn_IndexBufBuilder elb; - GWN_indexbuf_init_ex(&elb, GWN_PRIM_TRIS_ADJ, 6 * 8, 24, false); - for (int i = 0; i < 8; i++) { - GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]); - GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][0]]); - GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]); - GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]); - GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][1]]); - GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]); - GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]); - GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][2]]); - GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]); - for (int j = 0; j < 6; ++j) { - GWN_indexbuf_add_generic_vert(&elb, bone_octahedral_solid_tris_adjacency[i][j]); + for (int j = 0; j < 3; ++j) { + GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]); + GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][j]]); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][j]]); } } - SHC.drw_bone_octahedral = GWN_batch_create_ex(GWN_PRIM_TRIS_ADJ, vbo, GWN_indexbuf_build(&elb), - GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX); + SHC.drw_bone_octahedral = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, + GWN_BATCH_OWNS_VBO); } return SHC.drw_bone_octahedral; } +Gwn_Batch *DRW_cache_bone_octahedral_wire_get(void) +{ + if (!SHC.drw_bone_octahedral_wire) { + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, 12, 24); + + for (int i = 0; i < 12; i++) { + GWN_indexbuf_add_line_adj_verts(&elb, + bone_octahedral_wire_lines_adjacency[i][0], + bone_octahedral_wire_lines_adjacency[i][1], + bone_octahedral_wire_lines_adjacency[i][2], + bone_octahedral_wire_lines_adjacency[i][3]); + } + + /* HACK Reuse vertex buffer. */ + Gwn_Batch *pos_nor_batch = DRW_cache_bone_octahedral_get(); + + SHC.drw_bone_octahedral_wire = GWN_batch_create_ex(GWN_PRIM_LINES_ADJ, pos_nor_batch->verts[0], GWN_indexbuf_build(&elb), + GWN_BATCH_OWNS_INDEX); + } + return SHC.drw_bone_octahedral_wire; +} + /* XXX TODO move that 1 unit cube to more common/generic place? */ static const float bone_box_verts[8][3] = { { 1.0f, 0.0f, 1.0f}, @@ -1728,6 +1782,13 @@ static const uint bone_box_solid_tris[12][3] = { * Store indices of generated verts from bone_box_solid_tris to define adjacency infos. * See bone_octahedral_solid_tris for more infos. **/ +static const uint bone_box_wire_lines_adjacency[12][4] = { + { 4, 2, 0, 11}, { 0, 1, 2, 8}, { 2, 4, 1, 14}, { 1, 0, 4, 20}, /* bottom */ + { 0, 8, 11, 14}, { 2, 14, 8, 20}, { 1, 20, 14, 11}, { 4, 11, 20, 8}, /* top */ + { 20, 0, 11, 2}, { 11, 2, 8, 1}, { 8, 1, 14, 4}, { 14, 4, 20, 0}, /* sides */ +}; + +#if 0 /* UNUSED */ static const uint bone_box_solid_tris_adjacency[12][6] = { { 0, 5, 1, 14, 2, 8}, { 3, 26, 4, 20, 5, 1}, @@ -1747,6 +1808,7 @@ static const uint bone_box_solid_tris_adjacency[12][6] = { {30, 9, 31, 15, 32, 35}, {33, 31, 34, 21, 35, 27}, }; +#endif /* aligned with bone_box_solid_tris */ static const float bone_box_solid_normals[12][3] = { @@ -1786,26 +1848,43 @@ Gwn_Batch *DRW_cache_bone_box_get(void) Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); GWN_vertbuf_data_alloc(vbo, 36); - Gwn_IndexBufBuilder elb; - GWN_indexbuf_init_ex(&elb, GWN_PRIM_TRIS_ADJ, 6 * 12, 36, false); - for (int i = 0; i < 12; i++) { for (int j = 0; j < 3; j++) { GWN_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_box_solid_normals[i]); GWN_vertbuf_attr_set(vbo, attr_id.snor, v_idx, bone_box_smooth_normals[bone_box_solid_tris[i][j]]); GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_box_verts[bone_box_solid_tris[i][j]]); } - for (int j = 0; j < 6; ++j) { - GWN_indexbuf_add_generic_vert(&elb, bone_box_solid_tris_adjacency[i][j]); - } } - SHC.drw_bone_box = GWN_batch_create_ex(GWN_PRIM_TRIS_ADJ, vbo, GWN_indexbuf_build(&elb), - GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX); + SHC.drw_bone_box = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, + GWN_BATCH_OWNS_VBO); } return SHC.drw_bone_box; } +Gwn_Batch *DRW_cache_bone_box_wire_get(void) +{ + if (!SHC.drw_bone_box_wire) { + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, 12, 36); + + for (int i = 0; i < 12; i++) { + GWN_indexbuf_add_line_adj_verts(&elb, + bone_box_wire_lines_adjacency[i][0], + bone_box_wire_lines_adjacency[i][1], + bone_box_wire_lines_adjacency[i][2], + bone_box_wire_lines_adjacency[i][3]); + } + + /* HACK Reuse vertex buffer. */ + Gwn_Batch *pos_nor_batch = DRW_cache_bone_box_get(); + + SHC.drw_bone_box_wire = GWN_batch_create_ex(GWN_PRIM_LINES_ADJ, pos_nor_batch->verts[0], GWN_indexbuf_build(&elb), + GWN_BATCH_OWNS_INDEX); + } + return SHC.drw_bone_box_wire; +} + /* Helpers for envelope bone's solid sphere-with-hidden-equatorial-cylinder. * Note that here we only encode head/tail in forth component of the vector. */ static void benv_lat_lon_to_co(const float lat, const float lon, float r_nor[3]) @@ -2014,9 +2093,9 @@ Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void) for (int a = 0; a < CIRCLE_RESOL; a++) { v1[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); v1[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); - GWN_vertbuf_attr_set(vbo, attr_id.pos0, v , v0); + GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0); GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1); - GWN_vertbuf_attr_set(vbo, attr_id.pos0, v , v0); + GWN_vertbuf_attr_set(vbo, attr_id.pos0, v, v0); GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1); copy_v2_v2(v0, v1); } @@ -2506,12 +2585,12 @@ Gwn_Batch *DRW_cache_mesh_wire_outline_get(Object *ob) return DRW_mesh_batch_cache_get_fancy_edges(me); } -Gwn_Batch *DRW_cache_mesh_edge_detection_get(Object *ob) +Gwn_Batch *DRW_cache_mesh_edge_detection_get(Object *ob, bool *r_is_manifold) { BLI_assert(ob->type == OB_MESH); Mesh *me = ob->data; - return DRW_mesh_batch_cache_get_edge_detection(me); + return DRW_mesh_batch_cache_get_edge_detection(me, r_is_manifold); } Gwn_Batch *DRW_cache_mesh_surface_get(Object *ob) diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 8bc609ffe1f..1fd6b22c221 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -48,7 +48,7 @@ struct Gwn_Batch *DRW_cache_screenspace_circle_get(void); /* Common Object */ struct Gwn_Batch *DRW_cache_object_wire_outline_get(struct Object *ob); -struct Gwn_Batch *DRW_cache_object_edge_detection_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_object_edge_detection_get(struct Object *ob, bool *r_is_manifold); struct Gwn_Batch *DRW_cache_object_surface_get(struct Object *ob); struct Gwn_Batch **DRW_cache_object_surface_material_get( struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len, @@ -78,7 +78,8 @@ struct Gwn_Batch *DRW_cache_field_cone_limit_get(void); struct Gwn_Batch *DRW_cache_lamp_get(void); struct Gwn_Batch *DRW_cache_lamp_shadows_get(void); struct Gwn_Batch *DRW_cache_lamp_sunrays_get(void); -struct Gwn_Batch *DRW_cache_lamp_area_get(void); +struct Gwn_Batch *DRW_cache_lamp_area_square_get(void); +struct Gwn_Batch *DRW_cache_lamp_area_disk_get(void); struct Gwn_Batch *DRW_cache_lamp_hemi_get(void); struct Gwn_Batch *DRW_cache_lamp_spot_get(void); struct Gwn_Batch *DRW_cache_lamp_spot_square_get(void); @@ -98,7 +99,9 @@ struct Gwn_Batch *DRW_cache_lightprobe_planar_get(void); /* Bones */ struct Gwn_Batch *DRW_cache_bone_octahedral_get(void); +struct Gwn_Batch *DRW_cache_bone_octahedral_wire_get(void); struct Gwn_Batch *DRW_cache_bone_box_get(void); +struct Gwn_Batch *DRW_cache_bone_box_wire_get(void); struct Gwn_Batch *DRW_cache_bone_envelope_solid_get(void); struct Gwn_Batch *DRW_cache_bone_envelope_outline_get(void); struct Gwn_Batch *DRW_cache_bone_envelope_head_wire_outline_get(void); @@ -117,7 +120,7 @@ void DRW_cache_mesh_normals_overlay_get( struct Gwn_Batch **r_tris, struct Gwn_Batch **r_ledges, struct Gwn_Batch **r_lverts); struct Gwn_Batch *DRW_cache_face_centers_get(struct Object *ob); struct Gwn_Batch *DRW_cache_mesh_wire_outline_get(struct Object *ob); -struct Gwn_Batch *DRW_cache_mesh_edge_detection_get(struct Object *ob); +struct Gwn_Batch *DRW_cache_mesh_edge_detection_get(struct Object *ob, bool *r_is_manifold); struct Gwn_Batch *DRW_cache_mesh_surface_get(struct Object *ob); struct Gwn_Batch *DRW_cache_mesh_surface_weights_get(struct Object *ob); struct Gwn_Batch *DRW_cache_mesh_surface_vert_colors_get(struct Object *ob); @@ -166,11 +169,16 @@ struct Gwn_Batch *DRW_cache_lattice_wire_get(struct Object *ob, bool use_weight) struct Gwn_Batch *DRW_cache_lattice_vert_overlay_get(struct Object *ob); /* Particles */ -struct Gwn_Batch *DRW_cache_particles_get_hair(struct Object *object, struct ParticleSystem *psys, struct ModifierData *md); -struct Gwn_Batch *DRW_cache_particles_get_dots(struct Object *object, struct ParticleSystem *psys); -struct Gwn_Batch *DRW_cache_particles_get_edit_strands(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); -struct Gwn_Batch *DRW_cache_particles_get_edit_inner_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); -struct Gwn_Batch *DRW_cache_particles_get_edit_tip_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_cache_particles_get_hair( + struct Object *object, struct ParticleSystem *psys, struct ModifierData *md); +struct Gwn_Batch *DRW_cache_particles_get_dots( + struct Object *object, struct ParticleSystem *psys); +struct Gwn_Batch *DRW_cache_particles_get_edit_strands( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_cache_particles_get_edit_inner_points( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_cache_particles_get_edit_tip_points( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); struct Gwn_Batch *DRW_cache_particles_get_prim(int type); /* Metaball */ diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 3ca53b92946..f77dafc9b31 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -64,7 +64,8 @@ struct Gwn_Batch *DRW_curve_batch_cache_get_normal_edge( struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_edges(struct Curve *cu); struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(struct Curve *cu); -struct Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(struct Curve *cu, struct CurveCache *ob_curve_cache); +struct Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals( + struct Curve *cu, struct CurveCache *ob_curve_cache); struct Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded( struct Curve *cu, struct CurveCache *ob_curve_cache, struct GPUMaterial **gpumat_array, uint gpumat_array_len); @@ -109,7 +110,7 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mes struct Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(struct Mesh *me); -struct Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(struct Mesh *me); +struct Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(struct Mesh *me, bool *r_is_manifold); struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me); @@ -124,10 +125,15 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me, void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me); /* Particles */ -struct Gwn_Batch *DRW_particles_batch_cache_get_hair(struct Object *object, struct ParticleSystem *psys, struct ModifierData *md); -struct Gwn_Batch *DRW_particles_batch_cache_get_dots(struct Object *object, struct ParticleSystem *psys); -struct Gwn_Batch *DRW_particles_batch_cache_get_edit_strands(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); -struct Gwn_Batch *DRW_particles_batch_cache_get_edit_inner_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); -struct Gwn_Batch *DRW_particles_batch_cache_get_edit_tip_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_particles_batch_cache_get_hair( + struct Object *object, struct ParticleSystem *psys, struct ModifierData *md); +struct Gwn_Batch *DRW_particles_batch_cache_get_dots( + struct Object *object, struct ParticleSystem *psys); +struct Gwn_Batch *DRW_particles_batch_cache_get_edit_strands( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_particles_batch_cache_get_edit_inner_points( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); +struct Gwn_Batch *DRW_particles_batch_cache_get_edit_tip_points( + struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); #endif /* __DRAW_CACHE_IMPL_H__ */ diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c index 09531220d9a..3eecff024a1 100644 --- a/source/blender/draw/intern/draw_cache_impl_displist.c +++ b/source/blender/draw/intern/draw_cache_impl_displist.c @@ -176,7 +176,8 @@ Gwn_IndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb) Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(ListBase *lb, uint gpumat_array_len) { - Gwn_IndexBuf **shaded_triangles_in_order = MEM_callocN(sizeof(*shaded_triangles_in_order) * gpumat_array_len, __func__); + Gwn_IndexBuf **shaded_triangles_in_order = MEM_callocN( + sizeof(*shaded_triangles_in_order) * gpumat_array_len, __func__); Gwn_IndexBufBuilder *elb = BLI_array_alloca(elb, gpumat_array_len); const int tri_len = curve_render_surface_tri_len_get(lb); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index e8add4890d8..cf972434ba5 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -1633,6 +1633,9 @@ typedef struct MeshBatchCache { /* XXX, only keep for as long as sculpt mode uses shaded drawing. */ bool is_sculpt_points_tag; + + /* Valid only if edges_adjacency is up to date. */ + bool is_manifold; } MeshBatchCache; /* Gwn_Batch cache management. */ @@ -1953,7 +1956,8 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata, GWN_vertformat_alias_add(format, attrib_name); /* +1 include null terminator. */ - auto_ofs += 1 + BLI_snprintf_rlen(cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name); + auto_ofs += 1 + BLI_snprintf_rlen( + cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name); cache->auto_layer_is_srgb[auto_id++] = 0; /* tag as not srgb */ if (i == rdata->cd.layers.uv_active) { @@ -1988,7 +1992,8 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata, GWN_vertformat_alias_add(format, attrib_name); /* +1 include null terminator. */ - auto_ofs += 1 + BLI_snprintf_rlen(cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name); + auto_ofs += 1 + BLI_snprintf_rlen( + cache->auto_layer_names + auto_ofs, auto_names_len - auto_ofs, "b%s", attrib_name); cache->auto_layer_is_srgb[auto_id++] = 1; /* tag as srgb */ } @@ -3232,6 +3237,8 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata, const int vert_len = mesh_render_data_verts_len_get(rdata); const int tri_len = mesh_render_data_looptri_len_get(rdata); + cache->is_manifold = true; + /* Allocate max but only used indices are sent to GPU. */ Gwn_IndexBufBuilder elb; GWN_indexbuf_init(&elb, GWN_PRIM_LINES_ADJ, tri_len * 3, vert_len); @@ -3277,6 +3284,7 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata, /* Don't share edge if triangles have non matching winding. */ GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0); GWN_indexbuf_add_line_adj_verts(&elb, v_opposite, v1, v2, v_opposite); + cache->is_manifold = false; } else { GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v_opposite); @@ -3301,6 +3309,7 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata, SWAP(unsigned int, v1, v2); } GWN_indexbuf_add_line_adj_verts(&elb, v0, v1, v2, v0); + cache->is_manifold = false; } BLI_edgehashIterator_free(ehi); BLI_edgehash_free(eh, NULL); @@ -3820,7 +3829,7 @@ Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me) return cache->fancy_edges; } -Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me) +Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold) { MeshBatchCache *cache = mesh_batch_cache_get(me); @@ -3829,12 +3838,17 @@ Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me) MeshRenderData *rdata = mesh_render_data_create(me, options); - cache->edge_detection = GWN_batch_create_ex(GWN_PRIM_LINES_ADJ, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), - mesh_batch_cache_get_edges_adjacency(rdata, cache), 0); + cache->edge_detection = GWN_batch_create_ex( + GWN_PRIM_LINES_ADJ, mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache), + mesh_batch_cache_get_edges_adjacency(rdata, cache), 0); mesh_render_data_free(rdata); } + if (r_is_manifold) { + *r_is_manifold = cache->is_manifold; + } + return cache->edge_detection; } diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index c6cc243638b..c89ea67a39c 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -599,7 +599,9 @@ static void particle_batch_cache_ensure_pos(Object *object, val = len_v3(pa->state.vel) / psys->part->color_vec_max; break; case PART_DRAW_COL_ACC: - val = len_v3v3(pa->state.vel, pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * psys->part->color_vec_max); + val = len_v3v3( + pa->state.vel, + pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * psys->part->color_vec_max); break; default: val = -1.0f; diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index b51b15b20ed..11e04306143 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -224,8 +224,8 @@ DRWShadingGroup *shgroup_dynlines_flat_color(DRWPass *pass) GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_FLAT_COLOR); DRW_shgroup_instance_format(g_formats.dynlines_color, { - {"pos" , DRW_ATTRIB_FLOAT, 3}, - {"color" , DRW_ATTRIB_FLOAT, 4} + {"pos", DRW_ATTRIB_FLOAT, 3}, + {"color", DRW_ATTRIB_FLOAT, 4} }); DRWShadingGroup *grp = DRW_shgroup_line_batch_create_with_format(sh, pass, g_formats.dynlines_color); @@ -288,7 +288,7 @@ DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Gwn_Batch *g DRW_shgroup_instance_format(g_formats.instance_screenspace, { {"world_pos", DRW_ATTRIB_FLOAT, 3}, - {"color" , DRW_ATTRIB_FLOAT, 3} + {"color", DRW_ATTRIB_FLOAT, 3} }); DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_screenspace); @@ -307,7 +307,7 @@ DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct Gwn_Batch *geom) DRW_shgroup_instance_format(g_formats.instance_color, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"color" , DRW_ATTRIB_FLOAT, 4} + {"color", DRW_ATTRIB_FLOAT, 4} }); DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color); @@ -322,7 +322,7 @@ DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct Gwn_Batch *geom) DRW_shgroup_instance_format(g_formats.instance_color, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"color" , DRW_ATTRIB_FLOAT, 4} + {"color", DRW_ATTRIB_FLOAT, 4} }); DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color); @@ -335,8 +335,8 @@ DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass, struct Gwn_Batch GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED); DRW_shgroup_instance_format(g_formats.instance_screen_aligned, { - {"color" , DRW_ATTRIB_FLOAT, 3}, - {"size" , DRW_ATTRIB_FLOAT, 1}, + {"color", DRW_ATTRIB_FLOAT, 3}, + {"size", DRW_ATTRIB_FLOAT, 1}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -351,8 +351,8 @@ DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct Gwn_Batch *ge GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS); DRW_shgroup_instance_format(g_formats.instance_screen_aligned, { - {"color" , DRW_ATTRIB_FLOAT, 3}, - {"size" , DRW_ATTRIB_FLOAT, 1}, + {"color", DRW_ATTRIB_FLOAT, 3}, + {"size", DRW_ATTRIB_FLOAT, 1}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -367,8 +367,8 @@ DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass, struct Gwn_Batch *geom) GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE); DRW_shgroup_instance_format(g_formats.instance_scaled, { - {"color" , DRW_ATTRIB_FLOAT, 3}, - {"size" , DRW_ATTRIB_FLOAT, 3}, + {"color", DRW_ATTRIB_FLOAT, 3}, + {"size", DRW_ATTRIB_FLOAT, 3}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -382,8 +382,8 @@ DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Gwn_Batch *geom) GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE); DRW_shgroup_instance_format(g_formats.instance_sized, { - {"color" , DRW_ATTRIB_FLOAT, 3}, - {"size" , DRW_ATTRIB_FLOAT, 1}, + {"color", DRW_ATTRIB_FLOAT, 3}, + {"size", DRW_ATTRIB_FLOAT, 1}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -397,8 +397,8 @@ DRWShadingGroup *shgroup_instance_outline(DRWPass *pass, struct Gwn_Batch *geom, GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE); DRW_shgroup_instance_format(g_formats.instance_outline, { - {"callId" , DRW_ATTRIB_INT, 1}, - {"size" , DRW_ATTRIB_FLOAT, 1}, + {"callId", DRW_ATTRIB_INT, 1}, + {"size", DRW_ATTRIB_FLOAT, 1}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -413,10 +413,10 @@ DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Gwn_Batch *geom) GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_CAMERA); DRW_shgroup_instance_format(g_formats.instance_camera, { - {"color" , DRW_ATTRIB_FLOAT, 3}, - {"corners" , DRW_ATTRIB_FLOAT, 8}, - {"depth" , DRW_ATTRIB_FLOAT, 1}, - {"tria" , DRW_ATTRIB_FLOAT, 4}, + {"color", DRW_ATTRIB_FLOAT, 3}, + {"corners", DRW_ATTRIB_FLOAT, 8}, + {"depth", DRW_ATTRIB_FLOAT, 1}, + {"tria", DRW_ATTRIB_FLOAT, 4}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -431,9 +431,9 @@ DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Gwn_Batch static float point_size = 4.0f; DRW_shgroup_instance_format(g_formats.instance_distance_lines, { - {"color" , DRW_ATTRIB_FLOAT, 3}, - {"start" , DRW_ATTRIB_FLOAT, 1}, - {"end" , DRW_ATTRIB_FLOAT, 1}, + {"color", DRW_ATTRIB_FLOAT, 3}, + {"start", DRW_ATTRIB_FLOAT, 1}, + {"end", DRW_ATTRIB_FLOAT, 1}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -450,7 +450,7 @@ DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom) static const int False = false; DRW_shgroup_instance_format(g_formats.instance_spot, { - {"color" , DRW_ATTRIB_FLOAT, 3}, + {"color", DRW_ATTRIB_FLOAT, 3}, {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16} }); @@ -472,12 +472,13 @@ DRWShadingGroup *shgroup_instance_bone_axes(DRWPass *pass) DRW_shgroup_instance_format(g_formats.instance_color, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"color" , DRW_ATTRIB_FLOAT, 4} + {"color", DRW_ATTRIB_FLOAT, 4} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_axes, - pass, DRW_cache_bone_arrows_get(), - g_formats.instance_color); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_axes, + pass, DRW_cache_bone_arrows_get(), + g_formats.instance_color); DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2); return grp; @@ -492,15 +493,16 @@ DRWShadingGroup *shgroup_instance_bone_envelope_outline(DRWPass *pass) } DRW_shgroup_instance_format(g_formats.instance_bone_envelope_outline, { - {"headSphere" , DRW_ATTRIB_FLOAT, 4}, - {"tailSphere" , DRW_ATTRIB_FLOAT, 4}, - {"outlineColorSize" , DRW_ATTRIB_FLOAT, 4}, - {"xAxis" , DRW_ATTRIB_FLOAT, 3} + {"headSphere", DRW_ATTRIB_FLOAT, 4}, + {"tailSphere", DRW_ATTRIB_FLOAT, 4}, + {"outlineColorSize", DRW_ATTRIB_FLOAT, 4}, + {"xAxis", DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_envelope_outline, - pass, DRW_cache_bone_envelope_outline_get(), - g_formats.instance_bone_envelope_outline); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_envelope_outline, + pass, DRW_cache_bone_envelope_outline_get(), + g_formats.instance_bone_envelope_outline); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); return grp; @@ -515,14 +517,15 @@ DRWShadingGroup *shgroup_instance_bone_envelope_distance(DRWPass *pass) } DRW_shgroup_instance_format(g_formats.instance_bone_envelope_distance, { - {"headSphere" , DRW_ATTRIB_FLOAT, 4}, - {"tailSphere" , DRW_ATTRIB_FLOAT, 4}, - {"xAxis" , DRW_ATTRIB_FLOAT, 3} + {"headSphere", DRW_ATTRIB_FLOAT, 4}, + {"tailSphere", DRW_ATTRIB_FLOAT, 4}, + {"xAxis", DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_envelope_distance, - pass, DRW_cache_bone_envelope_solid_get(), - g_formats.instance_bone_envelope_distance); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_envelope_distance, + pass, DRW_cache_bone_envelope_solid_get(), + g_formats.instance_bone_envelope_distance); return grp; } @@ -536,16 +539,17 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass) } DRW_shgroup_instance_format(g_formats.instance_bone_envelope, { - {"headSphere" , DRW_ATTRIB_FLOAT, 4}, - {"tailSphere" , DRW_ATTRIB_FLOAT, 4}, - {"boneColor" , DRW_ATTRIB_FLOAT, 3}, - {"stateColor" , DRW_ATTRIB_FLOAT, 3}, - {"xAxis" , DRW_ATTRIB_FLOAT, 3} + {"headSphere", DRW_ATTRIB_FLOAT, 4}, + {"tailSphere", DRW_ATTRIB_FLOAT, 4}, + {"boneColor", DRW_ATTRIB_FLOAT, 3}, + {"stateColor", DRW_ATTRIB_FLOAT, 3}, + {"xAxis", DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_envelope, - pass, DRW_cache_bone_envelope_solid_get(), - g_formats.instance_bone_envelope); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_envelope, + pass, DRW_cache_bone_envelope_solid_get(), + g_formats.instance_bone_envelope); return grp; } @@ -559,14 +563,15 @@ DRWShadingGroup *shgroup_instance_mball_handles(DRWPass *pass) } DRW_shgroup_instance_format(g_formats.instance_mball_handles, { - {"ScaleTranslationMatrix" , DRW_ATTRIB_FLOAT, 12}, - {"radius" , DRW_ATTRIB_FLOAT, 1}, - {"color" , DRW_ATTRIB_FLOAT, 3} + {"ScaleTranslationMatrix", DRW_ATTRIB_FLOAT, 12}, + {"radius", DRW_ATTRIB_FLOAT, 1}, + {"color", DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.mball_handles, pass, - DRW_cache_screenspace_circle_get(), - g_formats.instance_mball_handles); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.mball_handles, pass, + DRW_cache_screenspace_circle_get(), + g_formats.instance_mball_handles); DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); return grp; @@ -585,11 +590,12 @@ DRWShadingGroup *shgroup_instance_bone_shape_outline(DRWPass *pass, struct Gwn_B DRW_shgroup_instance_format(g_formats.instance_bone_outline, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"outlineColorSize" , DRW_ATTRIB_FLOAT, 4} + {"outlineColorSize", DRW_ATTRIB_FLOAT, 4} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.shape_outline, - pass, geom, g_formats.instance_bone_outline); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.shape_outline, + pass, geom, g_formats.instance_bone_outline); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); return grp; @@ -605,12 +611,13 @@ DRWShadingGroup *shgroup_instance_bone_shape_solid(DRWPass *pass, struct Gwn_Bat DRW_shgroup_instance_format(g_formats.instance_bone, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"boneColor" , DRW_ATTRIB_FLOAT, 3}, - {"stateColor" , DRW_ATTRIB_FLOAT, 3} + {"boneColor", DRW_ATTRIB_FLOAT, 3}, + {"stateColor", DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.shape_solid, - pass, geom, g_formats.instance_bone); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.shape_solid, + pass, geom, g_formats.instance_bone); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); return grp; @@ -626,12 +633,13 @@ DRWShadingGroup *shgroup_instance_bone_sphere_solid(DRWPass *pass) DRW_shgroup_instance_format(g_formats.instance_bone, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"boneColor" , DRW_ATTRIB_FLOAT, 3}, - {"stateColor" , DRW_ATTRIB_FLOAT, 3} + {"boneColor", DRW_ATTRIB_FLOAT, 3}, + {"stateColor", DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_sphere, - pass, DRW_cache_bone_point_get(), g_formats.instance_bone); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_sphere, + pass, DRW_cache_bone_point_get(), g_formats.instance_bone); return grp; } @@ -646,12 +654,13 @@ DRWShadingGroup *shgroup_instance_bone_sphere_outline(DRWPass *pass) DRW_shgroup_instance_format(g_formats.instance_bone_outline, { {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"outlineColorSize" , DRW_ATTRIB_FLOAT, 4} + {"outlineColorSize", DRW_ATTRIB_FLOAT, 4} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_sphere_outline, - pass, DRW_cache_bone_point_wire_outline_get(), - g_formats.instance_bone_outline); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_sphere_outline, + pass, DRW_cache_bone_point_wire_outline_get(), + g_formats.instance_bone_outline); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); return grp; @@ -667,16 +676,17 @@ DRWShadingGroup *shgroup_instance_bone_stick(DRWPass *pass) DRW_shgroup_instance_format(g_formats.instance_bone_stick, { {"boneStart", DRW_ATTRIB_FLOAT, 3}, - {"boneEnd" , DRW_ATTRIB_FLOAT, 3}, + {"boneEnd", DRW_ATTRIB_FLOAT, 3}, {"wireColor", DRW_ATTRIB_FLOAT, 4}, /* TODO port theses to uchar color */ {"boneColor", DRW_ATTRIB_FLOAT, 4}, {"headColor", DRW_ATTRIB_FLOAT, 4}, {"tailColor", DRW_ATTRIB_FLOAT, 4} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_stick, - pass, DRW_cache_bone_stick_get(), - g_formats.instance_bone_stick); + DRWShadingGroup *grp = DRW_shgroup_instance_create( + g_shaders.bone_stick, + pass, DRW_cache_bone_stick_get(), + g_formats.instance_bone_stick); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); return grp; @@ -727,10 +737,10 @@ int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color case TH_ACTIVE: *r_color = ts.colorActive; break; case TH_SELECT: *r_color = ts.colorSelect; break; case TH_TRANSFORM: *r_color = ts.colorTransform; break; - case OB_SPEAKER: *r_color = ts.colorSpeaker; break; - case OB_CAMERA: *r_color = ts.colorCamera; break; - case OB_EMPTY: *r_color = ts.colorEmpty; break; - case OB_LAMP: *r_color = ts.colorLamp; break; + case TH_SPEAKER: *r_color = ts.colorSpeaker; break; + case TH_CAMERA: *r_color = ts.colorCamera; break; + case TH_EMPTY: *r_color = ts.colorEmpty; break; + case TH_LAMP: *r_color = ts.colorLamp; break; default: *r_color = ts.colorWire; break; } } @@ -749,10 +759,10 @@ float *DRW_color_background_blend_get(int theme_id) case TH_ACTIVE: ret = colors[1]; break; case TH_SELECT: ret = colors[2]; break; case TH_TRANSFORM: ret = colors[5]; break; - case OB_SPEAKER: ret = colors[6]; break; - case OB_CAMERA: ret = colors[7]; break; - case OB_EMPTY: ret = colors[8]; break; - case OB_LAMP: ret = colors[9]; break; + case TH_SPEAKER: ret = colors[6]; break; + case TH_CAMERA: ret = colors[7]; break; + case TH_EMPTY: ret = colors[8]; break; + case TH_LAMP: ret = colors[9]; break; default: ret = colors[10]; break; } diff --git a/source/blender/draw/intern/draw_debug.c b/source/blender/draw/intern/draw_debug.c new file mode 100644 index 00000000000..b30f7936758 --- /dev/null +++ b/source/blender/draw/intern/draw_debug.c @@ -0,0 +1,151 @@ +/* + * Copyright 2018, Blender Foundation. + * + * 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/intern/draw_debug.c + * \ingroup draw + * + * \brief Simple API to draw debug shapes in the viewport. + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_object_types.h" + +#include "BLI_link_utils.h" + +#include "GPU_immediate.h" + +#include "draw_debug.h" +#include "draw_manager.h" + +/* --------- Register --------- */ + +/* Matrix applied to all points before drawing. Could be a stack if needed. */ +static float g_modelmat[4][4]; + +void DRW_debug_modelmat_reset(void) +{ + unit_m4(g_modelmat); +} + +void DRW_debug_modelmat(const float modelmat[4][4]) +{ + copy_m4_m4(g_modelmat, modelmat); +} + +void DRW_debug_line_v3v3(const float v1[3], const float v2[3], const float color[4]) +{ + DRWDebugLine *line = MEM_mallocN(sizeof(DRWDebugLine), "DRWDebugLine"); + mul_v3_m4v3(line->pos[0], g_modelmat, v1); + mul_v3_m4v3(line->pos[1], g_modelmat, v2); + copy_v4_v4(line->color, color); + BLI_LINKS_PREPEND(DST.debug.lines, line); +} + +void DRW_debug_polygon_v3(const float (*v)[3], const int vert_len, const float color[4]) +{ + BLI_assert(vert_len > 1); + + for (int i = 0; i < vert_len; ++i) { + DRW_debug_line_v3v3(v[i], v[(i+1)%vert_len], color); + } +} + +/* NOTE: g_modelmat is still applied on top. */ +void DRW_debug_m4(const float m[4][4]) +{ + float v0[3] = {0.0f, 0.0f, 0.0f}; + float v1[3] = {1.0f, 0.0f, 0.0f}; + float v2[3] = {0.0f, 1.0f, 0.0f}; + float v3[3] = {0.0f, 0.0f, 1.0f}; + + mul_m4_v3(m, v0); + mul_m4_v3(m, v1); + mul_m4_v3(m, v2); + mul_m4_v3(m, v3); + + DRW_debug_line_v3v3(v0, v1, (float[4]){1.0f, 0.0f, 0.0f, 1.0f}); + DRW_debug_line_v3v3(v0, v2, (float[4]){0.0f, 1.0f, 0.0f, 1.0f}); + DRW_debug_line_v3v3(v0, v3, (float[4]){0.0f, 0.0f, 1.0f, 1.0f}); +} + +void DRW_debug_bbox(const BoundBox *bbox, const float color[4]) +{ + DRW_debug_line_v3v3(bbox->vec[0], bbox->vec[1], color); + DRW_debug_line_v3v3(bbox->vec[1], bbox->vec[2], color); + DRW_debug_line_v3v3(bbox->vec[2], bbox->vec[3], color); + DRW_debug_line_v3v3(bbox->vec[3], bbox->vec[0], color); + + DRW_debug_line_v3v3(bbox->vec[4], bbox->vec[5], color); + DRW_debug_line_v3v3(bbox->vec[5], bbox->vec[6], color); + DRW_debug_line_v3v3(bbox->vec[6], bbox->vec[7], color); + DRW_debug_line_v3v3(bbox->vec[7], bbox->vec[4], color); + + DRW_debug_line_v3v3(bbox->vec[0], bbox->vec[4], color); + DRW_debug_line_v3v3(bbox->vec[1], bbox->vec[5], color); + DRW_debug_line_v3v3(bbox->vec[2], bbox->vec[6], color); + DRW_debug_line_v3v3(bbox->vec[3], bbox->vec[7], color); +} + +/* --------- Render --------- */ + +static void drw_debug_draw_lines(void) +{ + int count = BLI_linklist_count((LinkNode *)DST.debug.lines); + + if (count == 0) { + return; + } + + Gwn_VertFormat *vert_format = immVertexFormat(); + uint pos = GWN_vertformat_attr_add(vert_format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + uint col = GWN_vertformat_attr_add(vert_format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + immBegin(GWN_PRIM_LINES, count * 2); + + while (DST.debug.lines) { + void *next = DST.debug.lines->next; + + immAttrib4fv(col, DST.debug.lines->color); + immVertex3fv(pos, DST.debug.lines->pos[0]); + + immAttrib4fv(col, DST.debug.lines->color); + immVertex3fv(pos, DST.debug.lines->pos[1]); + + MEM_freeN(DST.debug.lines); + DST.debug.lines = next; + } + immEnd(); + + immUnbindProgram(); +} + +void drw_debug_draw(void) +{ + drw_debug_draw_lines(); +} + +void drw_debug_init(void) +{ + DRW_debug_modelmat_reset(); +}
\ No newline at end of file diff --git a/source/blender/draw/intern/draw_debug.h b/source/blender/draw/intern/draw_debug.h new file mode 100644 index 00000000000..1dab431fc88 --- /dev/null +++ b/source/blender/draw/intern/draw_debug.h @@ -0,0 +1,39 @@ +/* + * Copyright 2018, Blender Foundation. + * + * 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file draw_debug.h + * \ingroup draw + */ + +#ifndef __DRAW_DEBUG_H__ +#define __DRAW_DEBUG_H__ + +struct BoundBox; + +void DRW_debug_modelmat_reset(void); +void DRW_debug_modelmat(const float modelmat[4][4]); + +void DRW_debug_line_v3v3(const float v1[3], const float v2[3], const float color[4]); +void DRW_debug_polygon_v3(const float (*v)[3], const int vert_len, const float color[4]); +void DRW_debug_m4(const float m[4][4]); +void DRW_debug_bbox(const BoundBox *bbox, const float color[4]); + +#endif /* __DRAW_DEBUG_H__ */ diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h index a4a02941ddb..bc3c0c2e04c 100644 --- a/source/blender/draw/intern/draw_instance_data.h +++ b/source/blender/draw/intern/draw_instance_data.h @@ -31,7 +31,7 @@ #include "GPU_batch.h" -#define MAX_INSTANCE_DATA_SIZE 42 /* Can be adjusted for more */ +#define MAX_INSTANCE_DATA_SIZE 48 /* Can be adjusted for more */ typedef struct DRWInstanceData DRWInstanceData; typedef struct DRWInstanceDataList DRWInstanceDataList; diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 29adb6b47f4..a57a91363eb 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -587,7 +587,8 @@ static void drw_viewport_var_init(void) void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type) { BLI_assert(type >= 0 && type < DRW_MAT_COUNT); - BLI_assert(((DST.override_mat & (1 << type)) != 0) || DST.draw_ctx.rv3d != NULL); /* Can't use this in render mode. */ + /* Can't use this in render mode. */ + BLI_assert(((DST.override_mat & (1 << type)) != 0) || DST.draw_ctx.rv3d != NULL); copy_m4_m4(mat, DST.view_data.matstate.mat[type]); } @@ -700,7 +701,8 @@ void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type) return NULL; } -void **DRW_view_layer_engine_data_ensure_ex(ViewLayer *view_layer, DrawEngineType *engine_type, void (*callback)(void *storage)) +void **DRW_view_layer_engine_data_ensure_ex( + ViewLayer *view_layer, DrawEngineType *engine_type, void (*callback)(void *storage)) { ViewLayerEngineData *sled; @@ -1023,7 +1025,7 @@ static void drw_engines_enable_from_engine(RenderEngineType *engine_type, int dr case OB_SOLID: case OB_TEXTURE: - if (shading_flags & V3D_SHADING_SEE_THROUGH) { + if (shading_flags & V3D_SHADING_XRAY) { use_drw_engine(&draw_engine_workbench_transparent); } else { @@ -1273,6 +1275,8 @@ void DRW_draw_render_loop_ex( /* Update ubos */ DRW_globals_update(); + drw_debug_init(); + /* No framebuffer allowed before drawing. */ BLI_assert(GPU_framebuffer_current_get() == 0); @@ -1340,6 +1344,8 @@ void DRW_draw_render_loop_ex( DRW_state_reset(); + drw_debug_draw(); + drw_engines_draw_text(); if (DST.draw_ctx.evil_C) { @@ -1558,7 +1564,8 @@ static void draw_select_framebuffer_setup(const rcti *rect) } if (g_select_buffer.texture_depth == NULL) { - g_select_buffer.texture_depth = GPU_texture_create_2D(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), GPU_DEPTH_COMPONENT24, NULL, NULL); + g_select_buffer.texture_depth = GPU_texture_create_2D( + BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), GPU_DEPTH_COMPONENT24, NULL, NULL); GPU_framebuffer_texture_attach(g_select_buffer.framebuffer, g_select_buffer.texture_depth, 0, 0); diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 0f9a68552fe..267826d2d9a 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -272,6 +272,14 @@ typedef struct ViewUboStorage { float clipplanes[2][4]; } ViewUboStorage; +/* ------------- DRAW DEBUG ------------ */ + +typedef struct DRWDebugLine { + struct DRWDebugLine *next; /* linked list */ + float pos[2][3]; + float color[4]; +} DRWDebugLine; + /* ------------- DRAW MANAGER ------------ */ #define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */ @@ -359,6 +367,11 @@ typedef struct DRWManager { char *bound_ubo_slots; int bind_ubo_inc; } RST; + + struct { + /* TODO(fclem) optimize: use chunks. */ + DRWDebugLine *lines; + } debug; } DRWManager; extern DRWManager DST; /* TODO : get rid of this and allow multithreaded rendering */ @@ -374,4 +387,7 @@ void *drw_viewport_engine_data_ensure(void *engine_type); void drw_state_set(DRWState state); +void drw_debug_draw(void); +void drw_debug_init(void); + #endif /* __DRAW_MANAGER_H__ */ diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 1e2036714bf..b4dce47413e 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -797,7 +797,8 @@ DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPas return shgroup; } -DRWShadingGroup *DRW_shgroup_line_batch_create_with_format(struct GPUShader *shader, DRWPass *pass, Gwn_VertFormat *format) +DRWShadingGroup *DRW_shgroup_line_batch_create_with_format( + struct GPUShader *shader, DRWPass *pass, Gwn_VertFormat *format) { DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); shgroup->type = DRW_SHG_LINE_BATCH; diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 9f4adac0106..110691373ab 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -221,7 +221,8 @@ void drw_state_set(DRWState state) int test; if (CHANGED_ANY_STORE_VAR( DRW_STATE_BLEND | DRW_STATE_BLEND_PREMUL | DRW_STATE_ADDITIVE | - DRW_STATE_MULTIPLY | DRW_STATE_TRANSMISSION | DRW_STATE_ADDITIVE_FULL, + DRW_STATE_MULTIPLY | DRW_STATE_TRANSMISSION | DRW_STATE_ADDITIVE_FULL | + DRW_STATE_TRANSPARENT_REVEALAGE, test)) { if (test) { @@ -240,6 +241,9 @@ void drw_state_set(DRWState state) else if ((state & DRW_STATE_TRANSMISSION) != 0) { glBlendFunc(GL_ONE, GL_SRC_ALPHA); } + else if ((state & DRW_STATE_TRANSPARENT_REVEALAGE) != 0) { + glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); + } else if ((state & DRW_STATE_ADDITIVE) != 0) { /* Do not let alpha accumulate but premult the source RGB by it. */ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, /* RGB */ @@ -329,8 +333,8 @@ void drw_state_set(DRWState state) } else if ((state & DRW_STATE_WRITE_STENCIL_SHADOW_FAIL) != 0) { glStencilMask(0xFF); - glStencilOpSeparate(GL_BACK, GL_KEEP, GL_INCR_WRAP, GL_KEEP); - glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR_WRAP, GL_KEEP); + glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP); + glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP); } /* Stencil Test */ else if ((state & (DRW_STATE_STENCIL_EQUAL | DRW_STATE_STENCIL_NEQUAL)) != 0) { @@ -703,6 +707,12 @@ bool DRW_culling_plane_test(float plane[4]) return false; } +void DRW_culling_frustum_corners_get(BoundBox *corners) +{ + draw_clipping_setup_from_view(); + memcpy(corners, &DST.clipping.frustum_corners, sizeof(BoundBox)); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -818,7 +828,8 @@ static void draw_geometry_execute_ex( } /* step 2 : bind vertex array & draw */ - GWN_batch_program_set_no_use(geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader)); + GWN_batch_program_set_no_use( + geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader)); /* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */ geom->program_in_use = true; diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c index 2c4e5f8b151..726d77a9925 100644 --- a/source/blender/draw/intern/draw_view.c +++ b/source/blender/draw/intern/draw_view.c @@ -682,7 +682,7 @@ void DRW_draw_cursor(void) immUniformThemeColor3(TH_VIEW_OVERLAY); immBegin(GWN_PRIM_LINES, 12); - const float scale = ED_view3d_pixel_size(rv3d, cursor->location) * 20; + const float scale = ED_view3d_pixel_size_no_ui_scale(rv3d, cursor->location) * U.widget_unit; #define CURSOR_VERT(axis_vec, axis, fac) \ immVertex3f( \ diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c index 8ac3cff2e1c..c0c4e7e4295 100644 --- a/source/blender/draw/modes/edit_metaball_mode.c +++ b/source/blender/draw/modes/edit_metaball_mode.c @@ -116,7 +116,9 @@ static void EDIT_METABALL_cache_init(void *vedata) { /* Create a pass */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_WIRE; + DRWState state = ( + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND | DRW_STATE_WIRE); psl->pass = DRW_pass_create("My Pass", state); /* Create a shadingGroup using a function in draw_common.c or custom one */ diff --git a/source/blender/draw/modes/edit_surface_mode.c b/source/blender/draw/modes/edit_surface_mode.c index b5cbb1baa55..7074ba3d024 100644 --- a/source/blender/draw/modes/edit_surface_mode.c +++ b/source/blender/draw/modes/edit_surface_mode.c @@ -149,7 +149,9 @@ static void EDIT_SURFACE_cache_init(void *vedata) { /* Create a pass */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_WIRE; + DRWState state = ( + DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND | DRW_STATE_WIRE); psl->pass = DRW_pass_create("My Pass", state); /* Create a shadingGroup using a function in draw_common.c or custom one */ diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 58cdfd4e413..52749a5429f 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -175,7 +175,8 @@ typedef struct OBJECT_PrivateData { DRWShadingGroup *lamp_distance; DRWShadingGroup *lamp_buflimit; DRWShadingGroup *lamp_buflimit_points; - DRWShadingGroup *lamp_area; + DRWShadingGroup *lamp_area_square; + DRWShadingGroup *lamp_area_disk; DRWShadingGroup *lamp_hemi; DRWShadingGroup *lamp_spot_cone; DRWShadingGroup *lamp_spot_blend; @@ -288,6 +289,7 @@ enum { PLANE_YZ = (1 << 6), CLIP_ZPOS = (1 << 7), CLIP_ZNEG = (1 << 8), + GRID_BACK = (1 << 9), }; /* *********** FUNCTIONS *********** */ @@ -446,18 +448,21 @@ static void OBJECT_engine_init(void *vedata) e_data.grid_flag |= SHOW_AXIS_Y; e_data.grid_flag |= SHOW_AXIS_Z; e_data.grid_flag |= SHOW_GRID; + e_data.grid_flag |= GRID_BACK; } else if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) { e_data.grid_flag = PLANE_XY; e_data.grid_flag |= SHOW_AXIS_X; e_data.grid_flag |= SHOW_AXIS_Y; e_data.grid_flag |= SHOW_GRID; + e_data.grid_flag |= GRID_BACK; } else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) { e_data.grid_flag = PLANE_XZ; e_data.grid_flag |= SHOW_AXIS_X; e_data.grid_flag |= SHOW_AXIS_Z; e_data.grid_flag |= SHOW_GRID; + e_data.grid_flag |= GRID_BACK; } else { /* RV3D_VIEW_USER */ e_data.grid_flag = PLANE_XY; @@ -987,7 +992,7 @@ static void OBJECT_cache_init(void *vedata) { /* Solid bones */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; psl->bone_solid = DRW_pass_create("Bone Solid Pass", state); psl->bone_outline = DRW_pass_create("Bone Outline Pass", state); } @@ -1164,8 +1169,11 @@ static void OBJECT_cache_init(void *vedata) stl->g_data->lamp_groundline = shgroup_groundlines_uniform_color(psl->non_meshes, ts.colorLamp); stl->g_data->lamp_groundpoint = shgroup_groundpoints_uniform_color(psl->non_meshes, ts.colorLamp); - geom = DRW_cache_lamp_area_get(); - stl->g_data->lamp_area = shgroup_instance(psl->non_meshes, geom); + geom = DRW_cache_lamp_area_square_get(); + stl->g_data->lamp_area_square = shgroup_instance(psl->non_meshes, geom); + + geom = DRW_cache_lamp_area_disk_get(); + stl->g_data->lamp_area_disk = shgroup_instance(psl->non_meshes, geom); geom = DRW_cache_lamp_hemi_get(); stl->g_data->lamp_hemi = shgroup_instance(psl->non_meshes, geom); @@ -1398,13 +1406,18 @@ static void DRW_shgroup_lamp(OBJECT_StorageList *stl, Object *ob, ViewLayer *vie else if (la->type == LA_AREA) { float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4]; - if (la->area_shape == LA_AREA_RECT) { + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { size[1] = la->area_sizey / la->area_size; size_to_mat4(sizemat, size); mul_m4_m4m4(shapemat, shapemat, sizemat); } - DRW_shgroup_call_dynamic_add(stl->g_data->lamp_area, color, &la->area_size, shapemat); + if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_area_disk, color, &la->area_size, shapemat); + } + else { + DRW_shgroup_call_dynamic_add(stl->g_data->lamp_area_square, color, &la->area_size, shapemat); + } } /* Line and point going to the ground */ diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c index e2b381347ff..c4b64e03c48 100644 --- a/source/blender/draw/modes/overlay_mode.c +++ b/source/blender/draw/modes/overlay_mode.c @@ -76,7 +76,8 @@ static void overlay_engine_init(void *vedata) if (!e_data.face_orientation_sh) { /* Face orientation */ - e_data.face_orientation_sh = DRW_shader_create(datatoc_overlay_face_orientation_vert_glsl, NULL, datatoc_overlay_face_orientation_frag_glsl, "\n"); + e_data.face_orientation_sh = DRW_shader_create( + datatoc_overlay_face_orientation_vert_glsl, NULL, datatoc_overlay_face_orientation_frag_glsl, "\n"); } } @@ -100,7 +101,8 @@ static void overlay_cache_init(void *vedata) if (stl->g_data->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) { int state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND; psl->face_orientation_pass = DRW_pass_create("Face Orientation", state); - stl->g_data->face_orientation_shgrp = DRW_shgroup_create(e_data.face_orientation_sh, psl->face_orientation_pass); + stl->g_data->face_orientation_shgrp = DRW_shgroup_create( + e_data.face_orientation_sh, psl->face_orientation_pass); } } diff --git a/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl index dc7ed5e202a..11924b19cf8 100644 --- a/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl @@ -1,11 +1,9 @@ -/* TODO: See perf with multiple invocations. */ -layout(triangles_adjacency) in; -layout(triangle_strip, max_vertices = 16) out; +layout(lines_adjacency) in; +layout(triangle_strip, max_vertices = 6) out; in vec4 pPos[]; -in float vZ[]; -in float vFacing[]; +in vec3 vPos[]; in vec2 ssPos[]; in vec2 ssNor[]; in vec4 vColSize[]; @@ -22,21 +20,18 @@ vec2 compute_dir(vec2 v0, vec2 v1) return dir; } -void emit_edge(const ivec3 edges, vec2 thick, bool is_persp) +void emit_edge(vec2 edge_dir, vec2 hidden_dir, vec2 thick, bool is_persp) { - vec2 edge_dir = compute_dir(ssPos[edges.x], ssPos[edges.y]); - vec2 hidden_dir = normalize(ssPos[edges.z] - ssPos[edges.x]); - float fac = dot(-hidden_dir, edge_dir); - vec2 t = thick * (is_persp ? vZ[edges.x] : 1.0); - gl_Position = pPos[edges.x]; + vec2 t = thick * (is_persp ? abs(vPos[1].z) : 1.0); + gl_Position = pPos[1]; EmitVertex(); gl_Position.xy += t * edge_dir * sign(fac); EmitVertex(); - t = thick * (is_persp ? vZ[edges.y] : 1.0); - gl_Position = pPos[edges.y]; + t = thick * (is_persp ? abs(vPos[2].z) : 1.0); + gl_Position = pPos[2]; EmitVertex(); gl_Position.xy += t * edge_dir * sign(fac); EmitVertex(); @@ -45,7 +40,7 @@ void emit_edge(const ivec3 edges, vec2 thick, bool is_persp) void emit_corner(const int e, vec2 thick, bool is_persp) { vec2 corner_dir = ssNor[e]; - vec2 t = thick * (is_persp ? vZ[e] : 1.0); + vec2 t = thick * (is_persp ? abs(vPos[e].z) : 1.0); gl_Position = pPos[e] + vec4(t * corner_dir, 0.0, 0.0); EmitVertex(); @@ -55,41 +50,38 @@ void main(void) { finalColor = vec4(vColSize[0].rgb, 1.0); - vec2 thick = vColSize[0].w * (lineThickness / viewportSize); bool is_persp = (ProjectionMatrix[3][3] == 0.0); - const ivec3 edges = ivec3(0, 2, 4); - vec4 facing = vec4(vFacing[1], vFacing[3], vFacing[5], vFacing[0]); - bvec4 do_edge = greaterThanEqual(facing, vec4(0.0)); + vec3 view_vec = (is_persp) ? normalize(vPos[1]) : vec3(0.0, 0.0, -1.0); + vec3 v10 = vPos[0] - vPos[1]; + vec3 v12 = vPos[2] - vPos[1]; + vec3 v13 = vPos[3] - vPos[1]; - /* Only generate outlines from backfaces. */ - if (do_edge.w) - return; + vec3 n0 = cross(v12, v10); + vec3 n3 = cross(v13, v12); - if (do_edge.x) { - emit_corner(edges.x, thick, is_persp); - emit_edge(edges.xyz, thick, is_persp); - } + float fac0 = dot(view_vec, n0); + float fac3 = dot(view_vec, n3); - if (any(do_edge.xy)) { - emit_corner(edges.y, thick, is_persp); - } + /* If both adjacent verts are facing the camera the same way, + * then it isn't an outline edge. */ + if (sign(fac0) == sign(fac3)) + return; - if (do_edge.y) { - emit_edge(edges.yzx, thick, is_persp); - } - else { - EndPrimitive(); - } + /* Don't outline if concave edge. */ + if (dot(n0, v13) > 0.0) + return; - if (any(do_edge.yz)) { - emit_corner(edges.z, thick, is_persp); - } + vec2 thick = vColSize[0].w * (lineThickness / viewportSize); + vec2 edge_dir = compute_dir(ssPos[1], ssPos[2]); - if (do_edge.z) { - emit_edge(edges.zxy, thick, is_persp); - emit_corner(edges.x, thick, is_persp); - } + /* Take the farthest point to compute edge direction + * (avoid problems with point behind near plane). */ + vec2 hidden_point = (vPos[0].z < vPos[3].z) ? ssPos[0] : ssPos[3]; + vec2 hidden_dir = normalize(hidden_point - ssPos[1]); + emit_corner(1, thick, is_persp); + emit_edge(edge_dir, hidden_dir, thick, is_persp); + emit_corner(2, thick, is_persp); EndPrimitive(); } diff --git a/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl index 0d09114579c..3e7a185bb62 100644 --- a/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl @@ -15,8 +15,7 @@ in mat4 InstanceModelMatrix; in vec4 outlineColorSize; out vec4 pPos; -out float vZ; -out float vFacing; +out vec3 vPos; out vec2 ssPos; out vec2 ssNor; out vec4 vColSize; @@ -34,25 +33,15 @@ void main() mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); vec4 viewpos = ViewMatrix * (InstanceModelMatrix * vec4(pos, 1.0)); - pPos = ProjectionMatrix * viewpos; - vZ = abs(viewpos.z); - /* if perspective */ - vec3 V = (ProjectionMatrix[3][3] == 0.0) ? normalize(-viewpos.xyz) : vec3(0.0, 0.0, 1.0); + vPos = viewpos.xyz; + pPos = ProjectionMatrix * viewpos; /* TODO FIX: there is still a problem with this vector * when the bone is scaled or in persp mode. But it's * barelly visible at the outline corners. */ ssNor = normalize((NormalMatrix * snor).xy); - vec3 normal = normalize(NormalMatrix * nor); - /* Add a small bias to avoid loosing outline - * on faces orthogonal to the view. - * (test case: octahedral bone without rotation in front view.) */ - normal.z += 1e-6; - - vFacing = dot(V, normal); - ssPos = proj(pPos); vColSize = outlineColorSize; diff --git a/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl b/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl index 248281f4e79..89f4d97f29b 100644 --- a/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_solid_frag.glsl @@ -1,5 +1,5 @@ -flat in vec4 finalColor; +in vec4 finalColor; out vec4 fragColor; diff --git a/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl index 701fc9c38ab..505868c9dcf 100644 --- a/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl @@ -16,7 +16,7 @@ in mat4 InstanceModelMatrix; in vec3 boneColor; in vec3 stateColor; -flat out vec4 finalColor; +out vec4 finalColor; void main() { diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl index baf508fd854..2b04bb0d855 100644 --- a/source/blender/draw/modes/shaders/object_grid_frag.glsl +++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl @@ -29,22 +29,23 @@ uniform int gridFlag; #define PLANE_XY (1 << 4) #define PLANE_XZ (1 << 5) #define PLANE_YZ (1 << 6) +#define GRID_BACK (1 << 9) /* grid is behind objects */ #define GRID_LINE_SMOOTH 1.15 -float get_grid(vec3 co, vec3 fwidthCos, float grid_size) +float get_grid(vec2 co, vec2 fwidthCos, float grid_size) { float half_size = grid_size / 2.0; - /* triangular wave pattern, amplitude is [0, grid_size] */ - vec3 grid_domain = abs(mod(co + half_size, grid_size) - half_size); + /* triangular wave pattern, amplitude is [0, half_size] */ + vec2 grid_domain = abs(mod(co + half_size, grid_size) - half_size); /* modulate by the absolute rate of change of the coordinates * (make lines have the same width under perspective) */ grid_domain /= fwidthCos; /* collapse waves and normalize */ - grid_domain.x = min(grid_domain.x, min(grid_domain.y, grid_domain.z)) / grid_size; + grid_domain.x = min(grid_domain.x, grid_domain.y) / half_size; - return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH / grid_size, grid_domain.x); + return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH / grid_size, grid_domain.x * 0.5); } vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size) @@ -137,18 +138,6 @@ void main() } } - /* Manual, non hard, depth test: - * Progressively fade the grid below occluders - * (avoids poping visuals due to depth buffer precision) */ - float scene_depth = texture(depthBuffer, sPos).r; - /* Add a small bias so the grid will always - * be on top of a mesh with the same depth. */ - float grid_depth = gl_FragCoord.z - 1e-8; - /* Harder settings tend to flicker more, - * but have less "see through" appearance. */ - const float test_hardness = 1e4; - fade *= 1.0 - clamp((grid_depth - scene_depth) * test_hardness, 0.0, 1.0); - if ((gridFlag & GRID) > 0) { float grid_res = log(dist * gridResolution) * gridOneOverLogSubdiv; @@ -160,9 +149,23 @@ void main() float scaleB = gridScale * pow(gridSubdiv, max(lvl + 0.0, 0.0)); float scaleC = gridScale * pow(gridSubdiv, max(lvl + 1.0, 1.0)); - float gridA = get_grid(wPos, fwidthPos, scaleA); - float gridB = get_grid(wPos, fwidthPos, scaleB); - float gridC = get_grid(wPos, fwidthPos, scaleC); + vec2 grid_pos, grid_fwidth; + if ((gridFlag & PLANE_XZ) > 0) { + grid_pos = wPos.xz; + grid_fwidth = fwidthPos.xz; + } + else if ((gridFlag & PLANE_YZ) > 0) { + grid_pos = wPos.yz; + grid_fwidth = fwidthPos.yz; + } + else { + grid_pos = wPos.xy; + grid_fwidth = fwidthPos.xy; + } + + float gridA = get_grid(grid_pos, grid_fwidth, scaleA); + float gridB = get_grid(grid_pos, grid_fwidth, scaleB); + float gridC = get_grid(grid_pos, grid_fwidth, scaleC); FragColor = vec4(colorGrid.rgb, gridA * blend); FragColor = mix(FragColor, vec4(mix(colorGrid.rgb, colorGridEmphasise.rgb, blend), 1.0), gridB); @@ -203,5 +206,22 @@ void main() } } + float scene_depth = texture(depthBuffer, sPos).r; + if ((gridFlag & GRID_BACK) > 0) { + fade *= (scene_depth == 1.0) ? 1.0 : 0.0; + } + else { + /* Manual, non hard, depth test: + * Progressively fade the grid below occluders + * (avoids poping visuals due to depth buffer precision) */ + /* Add a small bias so the grid will always + * be on top of a mesh with the same depth. */ + float grid_depth = gl_FragCoord.z - 1e-8; + /* Harder settings tend to flicker more, + * but have less "see through" appearance. */ + const float test_hardness = 1e4; + fade *= 1.0 - clamp((grid_depth - scene_depth) * test_hardness, 0.0, 1.0); + } + FragColor.a *= fade; } diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index abdc6450abd..9169df1407b 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -79,6 +79,9 @@ void ANIM_list_elem_update(Scene *scene, bAnimListElem *ale) if (adt) { adt->recalc |= ADT_RECALC_ANIM; DEG_id_tag_update(id, OB_RECALC_TIME); + if (adt->action != NULL) { + DEG_id_tag_update(&adt->action->id, DEG_TAG_COPY_ON_WRITE); + } } /* update data */ diff --git a/source/blender/editors/animation/anim_intern.h b/source/blender/editors/animation/anim_intern.h index c571da1ba74..824c1d58f44 100644 --- a/source/blender/editors/animation/anim_intern.h +++ b/source/blender/editors/animation/anim_intern.h @@ -79,6 +79,7 @@ void ANIM_OT_keying_set_active_set(struct wmOperatorType *ot); /* Driver management operators for UI buttons (RMB menu) */ void ANIM_OT_driver_button_add(struct wmOperatorType *ot); void ANIM_OT_driver_button_remove(struct wmOperatorType *ot); +void ANIM_OT_driver_button_edit(struct wmOperatorType *ot); void ANIM_OT_copy_driver_button(struct wmOperatorType *ot); void ANIM_OT_paste_driver_button(struct wmOperatorType *ot); diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index eace5af4701..1136dcd129e 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -512,6 +512,7 @@ void ED_operatortypes_anim(void) WM_operatortype_append(ANIM_OT_driver_button_add); WM_operatortype_append(ANIM_OT_driver_button_remove); + WM_operatortype_append(ANIM_OT_driver_button_edit); WM_operatortype_append(ANIM_OT_copy_driver_button); WM_operatortype_append(ANIM_OT_paste_driver_button); diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index f792bd2ea9b..2c28ecfac5d 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -41,6 +41,7 @@ #include "DNA_anim_types.h" #include "DNA_object_types.h" +#include "DNA_space_types.h" #include "DNA_texture_types.h" #include "BKE_animsys.h" @@ -967,6 +968,46 @@ void ANIM_OT_driver_button_remove(wmOperatorType *ot) RNA_def_boolean(ot->srna, "all", 1, "All", "Delete drivers for all elements of the array"); } +/* Edit Driver Button Operator ------------------------ */ + +static int edit_driver_button_exec(bContext *C, wmOperator *op) +{ + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; + int index; + const bool all = 0; // RNA_boolean_get(op->ptr, "all"); + + /* try to find driver using property retrieved from UI */ + UI_context_active_but_prop_get(C, &ptr, &prop, &index); + + if (all) + index = -1; + + if (ptr.id.data && ptr.data && prop) { + UI_popover_panel_invoke(C, SPACE_IPO, RGN_TYPE_UI, "GRAPH_PT_drivers_popover", true, op->reports); + } + + return OPERATOR_INTERFACE; +} + +void ANIM_OT_driver_button_edit(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Edit Driver"; + ot->idname = "ANIM_OT_driver_button_edit"; + ot->description = "Edit the drivers for the property connected represented by the highlighted button"; + + /* callbacks */ + ot->exec = edit_driver_button_exec; + //op->poll = ??? // TODO: need to have some driver to be able to do this... + + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; + + /* properties */ + //RNA_def_boolean(ot->srna, "all", 1, "All", "Edit drivers for all elements of the array"); +} + /* Copy Driver Button Operator ------------------------ */ static int copy_driver_button_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index b03aa66df04..f0dc680598c 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -299,7 +299,22 @@ void ED_pose_deselect_all_multi(Object **objects, uint objects_len, int select_m for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob_iter = objects[ob_index]; + bArmature *arm = ob_iter->data; + ED_pose_deselect_all(ob_iter, select_mode, ignore_visibility); + + /* if there are some dependencies for visualizing armature state + * (e.g. Mask Modifier in 'Armature' mode), force update + */ + if (arm->flag & ARM_HAS_VIZ_DEPS) { + /* NOTE: ob not ob_act here is intentional - it's the source of the + * bones being selected [T37247] + */ + DEG_id_tag_update(&ob_iter->id, OB_RECALC_DATA); + } + + /* need to tag armature for cow updates, or else selection doesn't update */ + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); } } @@ -368,6 +383,9 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve /* mask modifier ('armature' mode), etc. */ DEG_id_tag_update(&base->object->id, OB_RECALC_DATA); } + + /* need to tag armature for cow updates, or else selection doesn't update */ + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); return OPERATOR_FINISHED; } @@ -907,6 +925,9 @@ static int pose_select_grouped_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } + /* need to tag armature for cow updates, or else selection doesn't update */ + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); + /* report done status */ if (changed) return OPERATOR_FINISHED; @@ -1001,6 +1022,9 @@ static int pose_select_mirror_exec(bContext *C, wmOperator *op) } WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); + + /* need to tag armature for cow updates, or else selection doesn't update */ + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); } FOREACH_OBJECT_IN_MODE_END; diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index af9d94c0bac..1657fe4eaea 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -780,6 +780,7 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op, ViewLayer *view_layer = CTX_data_view_layer(C); FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_POSE, ob_iter) { + Object *ob_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), ob_iter); // XXX: UGLY HACK (for autokey + clear transforms) ListBase dsources = {NULL, NULL}; bool changed = false; @@ -797,6 +798,11 @@ static int pose_clear_transform_generic_exec(bContext *C, wmOperator *op, } /* tag for autokeying later */ ANIM_relative_keyingset_add_source(&dsources, &ob_iter->id, &RNA_PoseBone, pchan); + +#if 1 /* XXX: Ugly Hack - Run clearing function on evaluated copy of pchan */ + bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name); + clear_func(pchan_eval); +#endif } else { /* add unkeyed tags */ diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index eb180c6bde9..1987fe56bdb 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -5026,7 +5026,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) const float mval[2] = {UNPACK2(event->mval)}; struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), vc.scene, CTX_data_depsgraph(C), 0, vc.ar, vc.v3d); + vc.scene, CTX_data_depsgraph(C), 0, vc.ar, vc.v3d); ED_transform_snap_object_project_view3d( snap_context, diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index a91d373ac46..b10d915553e 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -248,6 +248,7 @@ int ED_operator_screen_mainwinactive(struct bContext *C); int ED_operator_areaactive(struct bContext *C); int ED_operator_regionactive(struct bContext *C); +int ED_operator_scene(struct bContext *C); int ED_operator_scene_editable(struct bContext *C); int ED_operator_objectmode(struct bContext *C); diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 36f87e1b494..c005f83b3fb 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -103,6 +103,7 @@ enum TfmMode { #define CTX_MASK (1 << 7) #define CTX_PAINT_CURVE (1 << 8) #define CTX_GPENCIL_STROKES (1 << 9) +#define CTX_CURSOR (1 << 10) /* Standalone call to get the transformation center corresponding to the current situation * returns 1 if successful, 0 otherwise (usually means there's no selection) @@ -153,7 +154,8 @@ int BIF_countTransformOrientation(const struct bContext *C); #define P_NO_TEXSPACE (1 << 11) #define P_CENTER (1 << 12) #define P_GPENCIL_EDIT (1 << 13) -#define P_CLNOR_INVALIDATE (1 << 14) +#define P_CURSOR_EDIT (1 << 14) +#define P_CLNOR_INVALIDATE (1 << 15) void Transform_Properties(struct wmOperatorType *ot, int flags); diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index 8ac7dfcf9d8..18d5101ebf7 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -79,9 +79,9 @@ struct SnapObjectParams { typedef struct SnapObjectContext SnapObjectContext; SnapObjectContext *ED_transform_snap_object_context_create( - struct Main *bmain, struct Scene *scene, struct Depsgraph *depsgraph, int flag); + struct Scene *scene, struct Depsgraph *depsgraph, int flag); SnapObjectContext *ED_transform_snap_object_context_create_view3d( - struct Main *bmain, struct Scene *scene, struct Depsgraph *depsgraph, int flag, + struct Scene *scene, struct Depsgraph *depsgraph, int flag, /* extra args for view3d */ const struct ARegion *ar, const struct View3D *v3d); void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx); diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index d6e8b6e9504..4d5e4585221 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -54,6 +54,11 @@ bool ED_uvedit_minmax(struct Scene *scene, struct Image *ima, struct Object *obe bool ED_uvedit_center(Scene *scene, Image *ima, struct Object *obedit, float cent[2], char mode); void ED_uvedit_select_all(struct BMesh *bm); +bool ED_uvedit_minmax_multi( + struct Scene *scene, struct Image *ima, struct Object **objects_edit, uint objects_len, float r_min[2], float r_max[2]); +bool ED_uvedit_center_multi( + Scene *scene, Image *ima, struct Object **objects_edit, uint objects_len, float r_cent[2], char mode); + bool ED_object_get_active_image( struct Object *ob, int mat_nr, struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node, struct bNodeTree **r_ntree); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 28e2c5e0d71..e1a6d59a748 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -106,9 +106,11 @@ void ED_view3d_cursor3d_update(struct bContext *C, const int mval[2]); struct Camera *ED_view3d_camera_data_get(struct View3D *v3d, struct RegionView3D *rv3d); void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist); -void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist); +void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float *dist); -void ED_view3d_from_object(struct Object *ob, float ofs[3], float quat[4], float *dist, float *lens); +void ED_view3d_from_object( + const struct Object *ob, + float ofs[3], float quat[4], float *dist, float *lens); void ED_view3d_to_object( const struct Depsgraph *depsgraph, struct Object *ob, const float ofs[3], const float quat[4], const float dist); @@ -227,6 +229,7 @@ eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *ar, const fl eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag); float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3]); +float ED_view3d_pixel_size_no_ui_scale(const struct RegionView3D *rv3d, const float co[3]); float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip); bool ED_view3d_clip_segment(const struct RegionView3D *rv3d, float ray_start[3], float ray_end[3]); @@ -304,12 +307,14 @@ float ED_view3d_radius_to_dist_persp(const float angle, const float radius); float ED_view3d_radius_to_dist_ortho(const float lens, const float radius); float ED_view3d_radius_to_dist( const struct View3D *v3d, const struct ARegion *ar, + const struct Depsgraph *depsgraph, const char persp, const bool use_aspect, const float radius); void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos); /* backbuffer select and draw support */ +void ED_view3d_backbuf_validate_with_select_mode(struct ViewContext *vc, short select_mode); void ED_view3d_backbuf_validate(struct ViewContext *vc); struct ImBuf *ED_view3d_backbuf_read( struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 142f4590c16..896d161f664 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -429,11 +429,9 @@ void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *b typedef struct uiPopover uiPopover; -void UI_popover_panel_from_type( - struct bContext *C, struct uiLayout *layout, struct PanelType *pt); int UI_popover_panel_invoke( struct bContext *C, int space_id, int region_id, const char *idname, - struct ReportList *reports); + bool keep_open, struct ReportList *reports); uiPopover *UI_popover_begin(struct bContext *C) ATTR_NONNULL(1); void UI_popover_end(struct bContext *C, struct uiPopover *head, struct wmKeyMap *keymap); @@ -949,6 +947,7 @@ const char *uiLayoutIntrospect(uiLayout *layout); // XXX - testing struct MenuType *UI_but_menutype_get(uiBut *but); struct PanelType *UI_but_paneltype_get(uiBut *but); void UI_menutype_draw(struct bContext *C, struct MenuType *mt, struct uiLayout *layout); +void UI_paneltype_draw(struct bContext *C, struct PanelType *pt, struct uiLayout *layout); /* Only for convenience. */ void uiLayoutSetContextFromBut(uiLayout *layout, uiBut *but); @@ -962,6 +961,7 @@ void uiLayoutSetKeepAspect(uiLayout *layout, bool keepaspect); void uiLayoutSetScaleX(uiLayout *layout, float scale); void uiLayoutSetScaleY(uiLayout *layout, float scale); void uiLayoutSetEmboss(uiLayout *layout, char emboss); +void uiLayoutSetPropSep(uiLayout *layout, bool is_sep); int uiLayoutGetOperatorContext(uiLayout *layout); bool uiLayoutGetActive(uiLayout *layout); @@ -973,6 +973,7 @@ int uiLayoutGetWidth(uiLayout *layout); float uiLayoutGetScaleX(uiLayout *layout); float uiLayoutGetScaleY(uiLayout *layout); int uiLayoutGetEmboss(uiLayout *layout); +bool uiLayoutGetPropSep(uiLayout *layout); /* layout specifiers */ uiLayout *uiLayoutRow(uiLayout *layout, int align); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index e4b298fecf0..a9995001659 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2887,7 +2887,7 @@ void ui_but_update_ex(uiBut *but, const bool validate) switch (but->type) { case UI_BTYPE_MENU: - if (BLI_rctf_size_x(&but->rect) > 24.0f) { + if (BLI_rctf_size_x(&but->rect) >= (UI_UNIT_X * 2)) { /* only needed for menus in popup blocks that don't recreate buttons on redraw */ if (but->block->flag & UI_BLOCK_LOOP) { if (but->rnaprop && (RNA_property_type(but->rnaprop) == PROP_ENUM)) { @@ -3212,7 +3212,9 @@ static uiBut *ui_def_but( } #ifdef USE_NUMBUTS_LR_ALIGN else if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) { - but->drawflag |= UI_BUT_TEXT_LEFT; + if (slen != 0) { + but->drawflag |= UI_BUT_TEXT_LEFT; + } } #endif @@ -4626,6 +4628,9 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) PointerRNA *opptr = UI_but_operator_ptr_get(but); wmOperatorType *ot = but->optype; + /* so the context is passed to itemf functions */ + WM_operator_properties_sanitize(opptr, false); + /* if the default property of the operator is enum and it is set, * fetch the tooltip of the selected value so that "Snap" and "Mirror" * operator menus in the Anim Editors will show tooltips for the different @@ -4645,9 +4650,6 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...) if (!item) { int i; - /* so the context is passed to itemf functions */ - WM_operator_properties_sanitize(ptr, false); - RNA_property_enum_items_gettexted(C, ptr, prop, &items, &totitems, &free_items); for (i = 0, item = items; i < totitems; i++, item++) { if (item->identifier[0] && item->value == value) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 70cd53c440f..0ebe079703b 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1780,23 +1780,20 @@ static bool ui_but_drag_init( /* TODO support more button pointer types */ if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) { - RNA_property_float_get_array(&but->rnapoin, but->rnaprop, drag_info->color); + ui_but_v3_get(but, drag_info->color); drag_info->gamma_corrected = true; valid = true; } else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) { - RNA_property_float_get_array(&but->rnapoin, but->rnaprop, drag_info->color); + ui_but_v3_get(but, drag_info->color); drag_info->gamma_corrected = false; valid = true; } - else if (but->pointype == UI_BUT_POIN_FLOAT) { + else if (ELEM(but->pointype, UI_BUT_POIN_FLOAT, UI_BUT_POIN_CHAR)) { + ui_but_v3_get(but, drag_info->color); copy_v3_v3(drag_info->color, (float *)but->poin); valid = true; } - else if (but->pointype == UI_BUT_POIN_CHAR) { - rgb_uchar_to_float(drag_info->color, (unsigned char *)but->poin); - valid = true; - } if (valid) { WM_event_start_drag(C, ICON_COLOR, WM_DRAG_COLOR, drag_info, 0.0, WM_DRAG_FREE_DATA); @@ -6783,8 +6780,11 @@ static bool ui_but_menu(bContext *C, uiBut *but) ICON_NONE, "ANIM_OT_paste_driver_button"); } + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Edit Driver"), + ICON_DRIVER, "ANIM_OT_driver_button_edit"); + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"), - ICON_DRIVER, "SCREEN_OT_drivers_editor_show"); + ICON_NONE, "SCREEN_OT_drivers_editor_show"); } else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) { /* pass */ @@ -6809,7 +6809,7 @@ static bool ui_but_menu(bContext *C, uiBut *but) } uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"), - ICON_DRIVER, "SCREEN_OT_drivers_editor_show"); + ICON_NONE, "SCREEN_OT_drivers_editor_show"); } /* Keying Sets */ diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 51c3cff721a..bacea087677 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -783,7 +783,7 @@ static DrawInfo *icon_create_drawinfo(Icon *icon) IconImage *img = MEM_mallocN(sizeof(IconImage), __func__); img->w = STUDIOLIGHT_SIZE; img->h = STUDIOLIGHT_SIZE; - img->rect = BKE_studiolight_preview(sl, STUDIOLIGHT_SIZE); + img->rect = BKE_studiolight_preview(sl, STUDIOLIGHT_SIZE, icon->id_type); di->data.buffer.image = img; } else { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index b851d1d8c5b..c7cf03a44dd 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -794,6 +794,8 @@ void ui_resources_free(void); void ui_layout_add_but(uiLayout *layout, uiBut *but); void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop); void ui_layout_list_set_labels_active(uiLayout *layout); +/* menu callback */ +void ui_item_paneltype_func(struct bContext *C, struct uiLayout *layout, void *arg_pt); /* interface_align.c */ bool ui_but_can_align(const uiBut *but) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 3a4d35296f7..7991f03ea31 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -71,6 +71,7 @@ return_statement; \ } (void)0 \ +#define UI_ITEM_PROP_SEP_DIVIDE 0.5f /* uiLayoutRoot */ @@ -128,6 +129,7 @@ enum { UI_ITEM_MIN = 1 << 1, UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */ + UI_ITEM_PROP_SEP = 1 << 3, }; typedef struct uiButtonItem { @@ -181,7 +183,7 @@ static const char *ui_item_name_add_colon(const char *name, char namestr[UI_MAX_ int len = strlen(name); if (len != 0 && len + 1 < UI_MAX_NAME_STR) { - BLI_strncpy(namestr, name, UI_MAX_NAME_STR); + memcpy(namestr, name, len); namestr[len] = ':'; namestr[len + 1] = '\0'; return namestr; @@ -394,7 +396,7 @@ static void ui_layer_but_cb(bContext *C, void *arg_but, void *arg_index) static void ui_item_array( uiLayout *layout, uiBlock *block, const char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int len, int x, int y, int w, int UNUSED(h), - bool expand, bool slider, bool toggle, bool icon_only, bool compact) + bool expand, bool slider, bool toggle, bool icon_only, bool compact, bool show_text) { uiStyle *style = layout->root->style; uiBut *but; @@ -411,8 +413,9 @@ static void ui_item_array( UI_block_layout_set_current(block, sub); /* create label */ - if (name[0]) + if (name[0] && show_text) { uiDefBut(block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + } /* create buttons */ if (type == PROP_BOOLEAN && ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) { @@ -530,7 +533,7 @@ static void ui_item_array( /* layout for known array subtypes */ char str[3] = {'\0'}; - if (!icon_only) { + if (!icon_only && show_text) { if (type != PROP_BOOLEAN) { str[1] = ':'; } @@ -542,19 +545,21 @@ static void ui_item_array( RNA_property_boolean_get_array(ptr, prop, boolarr); } + const char *str_buf = show_text ? str: ""; for (a = 0; a < len; a++) { int width_item; - if (!icon_only) { + if (!icon_only && show_text) { str[0] = RNA_property_array_item_char(prop, a); } if (boolarr) { icon = boolarr[a] ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; } + width_item = (compact && type == PROP_BOOLEAN) ? - min_ii(w, ui_text_icon_width(layout, str, icon, false)) : w; + min_ii(w, ui_text_icon_width(layout, str_buf, icon, false)) : w; - but = uiDefAutoButR(block, ptr, prop, a, str, icon, 0, 0, width_item, UI_UNIT_Y); + but = uiDefAutoButR(block, ptr, prop, a, str_buf, icon, 0, 0, width_item, UI_UNIT_Y); if (slider && but->type == UI_BTYPE_NUM) but->type = UI_BTYPE_NUM_SLIDER; if (toggle && but->type == UI_BTYPE_CHECKBOX) @@ -1401,7 +1406,8 @@ static void ui_item_rna_size( if (index == RNA_NO_INDEX && len > 0) { if (!name[0] && icon == ICON_NONE) h = 0; - + if (layout->item.flag & UI_ITEM_PROP_SEP) + h = 0; if (ELEM(subtype, PROP_LAYER, PROP_LAYER_MEMBER)) h += 2 * UI_UNIT_Y; else if (subtype == PROP_MATRIX) @@ -1431,6 +1437,7 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index int len, w, h; bool slider, toggle, expand, icon_only, no_bg, compact; bool is_array; + const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0); UI_block_layout_set_current(block, layout); @@ -1456,17 +1463,23 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index /* pass */ } else if (ELEM(type, PROP_INT, PROP_FLOAT, PROP_STRING, PROP_POINTER)) { - name = ui_item_name_add_colon(name, namestr); + if (use_prop_sep == false) { + name = ui_item_name_add_colon(name, namestr); + } } else if (type == PROP_BOOLEAN && is_array && index == RNA_NO_INDEX) { - name = ui_item_name_add_colon(name, namestr); + if (use_prop_sep == false) { + name = ui_item_name_add_colon(name, namestr); + } } else if (type == PROP_ENUM && index != RNA_ENUM_VALUE) { if (flag & UI_ITEM_R_COMPACT) { name = ""; } else { - name = ui_item_name_add_colon(name, namestr); + if (use_prop_sep == false) { + name = ui_item_name_add_colon(name, namestr); + } } } @@ -1505,11 +1518,56 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index layout->emboss = UI_EMBOSS_NONE; } + /* Split the label / property. */ + if (use_prop_sep) { + uiLayout *layout_split = uiLayoutSplit(layout, UI_ITEM_PROP_SEP_DIVIDE, true); + layout_split->space = 0; + uiLayout *layout_sub = uiLayoutColumn(layout_split, true); + layout_sub->space = 0; + + if (index == RNA_NO_INDEX && is_array) { + char name_with_suffix[UI_MAX_DRAW_STR + 2]; + char str[2] = {'\0'}; + for (int a = 0; a < len; a++) { + str[0] = RNA_property_array_item_char(prop, a); + const bool use_prefix = (a == 0 && name && name[0]); + if (use_prefix) { + char *s = name_with_suffix; + s += STRNCPY_RLEN(name_with_suffix, name); + *s++ = ' '; + *s++ = str[0]; + *s++ = '\0'; + } + but = uiDefBut( + block, UI_BTYPE_LABEL, 0, use_prefix ? name_with_suffix : str, + 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; + } + } + else { + if (name) { + but = uiDefBut( + 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; + } + } + + /* Watch out! We can only write into the new column now. */ + layout = uiLayoutColumn(layout_split, true); + layout->space = 0; + name = ""; + } + /* End split. */ + /* array property */ - if (index == RNA_NO_INDEX && is_array) + if (index == RNA_NO_INDEX && is_array) { ui_item_array( - layout, block, name, icon, ptr, prop, len, 0, 0, w, h, - expand, slider, toggle, icon_only, compact); + layout, block, name, icon, ptr, prop, len, 0, 0, w, h, + expand, slider, toggle, icon_only, compact, !use_prop_sep); + } /* enum item */ else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) { if (icon && name[0] && !icon_only) @@ -1848,19 +1906,13 @@ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt) layout->root->block->flag ^= UI_BLOCK_IS_FLIP; } -static void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt) +void ui_item_paneltype_func(bContext *C, uiLayout *layout, void *arg_pt) { PanelType *pt = (PanelType *)arg_pt; + UI_paneltype_draw(C, pt, layout); - if (layout->context) { - CTX_store_set(C, layout->context); - } - - UI_popover_panel_from_type(C, layout, pt); - - if (layout->context) { - CTX_store_set(C, NULL); - } + /* panels are created flipped (from event handling pov) */ + layout->root->block->flag ^= UI_BLOCK_IS_FLIP; } static uiBut *ui_item_menu( @@ -2935,6 +2987,7 @@ 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); BLI_addtail(&layout->items, litem); } @@ -3169,6 +3222,16 @@ void uiLayoutSetEmboss(uiLayout *layout, char emboss) layout->emboss = emboss; } +bool uiLayoutGetPropSep(uiLayout *layout) +{ + return (layout->item.flag & UI_ITEM_PROP_SEP) != 0; +} + +void uiLayoutSetPropSep(uiLayout *layout, bool is_sep) +{ + SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_SEP); +} + bool uiLayoutGetActive(uiLayout *layout) { return layout->active; @@ -3740,3 +3803,32 @@ void UI_menutype_draw(bContext *C, MenuType *mt, struct uiLayout *layout) CTX_store_set(C, NULL); } } + +/** + * Used for popup panels only. + */ +void UI_paneltype_draw(bContext *C, PanelType *pt, uiLayout *layout) +{ + Panel *panel = MEM_callocN(sizeof(Panel), "popover panel"); + panel->type = pt; + + if (layout->context) { + CTX_store_set(C, layout->context); + } + + if (pt->draw_header) { + panel->layout = uiLayoutRow(layout, false); + pt->draw_header(C, panel); + panel->layout = NULL; + } + + panel->layout = layout; + pt->draw(C, panel); + panel->layout = NULL; + + if (layout->context) { + CTX_store_set(C, NULL); + } + + MEM_freeN(panel); +} diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 7bf70b3d6fe..5711f76e3e9 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -753,12 +753,12 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con /* draw collapse icon */ /* itemrect smaller */ - itemrect.xmin = headrect.xmin + 5.0f / block->aspect; + itemrect.xmin = headrect.xmin + 3.0f / block->aspect; itemrect.xmax = itemrect.xmin + BLI_rcti_size_y(&headrect); itemrect.ymin = headrect.ymin; itemrect.ymax = headrect.ymax; - BLI_rctf_scale(&itemrect, 0.35f); + BLI_rctf_scale(&itemrect, 0.25f); if (is_closed_y) ui_draw_tria_rect(&itemrect, 'h'); diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c index b6248d3daa1..9d10713c868 100644 --- a/source/blender/editors/interface/interface_region_popover.c +++ b/source/blender/editors/interface/interface_region_popover.c @@ -189,17 +189,20 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v UI_block_flag_enable(block, UI_BLOCK_LOOP); UI_block_direction_set(block, block->direction); block->minbounds = UI_MENU_WIDTH_MIN; + bool use_place_under_active = !handle->refresh; - uiBut *but = NULL; - for (but = block->buttons.first; but; but = but->next) { - if (but->flag & (UI_SELECT | UI_SELECT_DRAW)) { - break; + if (use_place_under_active) { + uiBut *but = NULL; + for (but = block->buttons.first; but; but = but->next) { + if (but->flag & (UI_SELECT | UI_SELECT_DRAW)) { + break; + } } - } - if (but) { - offset[0] = -(but->rect.xmin + 0.8f * BLI_rctf_size_x(&but->rect)); - offset[1] = -(but->rect.ymin + 0.5f * BLI_rctf_size_y(&but->rect)); + if (but) { + offset[0] = -(but->rect.xmin + 0.8f * BLI_rctf_size_x(&but->rect)); + offset[1] = -(but->rect.ymin + 0.5f * BLI_rctf_size_y(&but->rect)); + } } UI_block_bounds_set_popup(block, block_margin, offset[0], offset[1]); @@ -256,30 +259,9 @@ uiPopupBlockHandle *ui_popover_panel_create( /** \name Standard Popover Panels * \{ */ - -void UI_popover_panel_from_type(bContext *C, uiLayout *layout, PanelType *pt) -{ - /* TODO: move into UI_paneltype_draw */ - Panel *panel = MEM_callocN(sizeof(Panel), "popover panel"); - panel->type = pt; - - - if (pt->draw_header) { - panel->layout = uiLayoutRow(layout, false); - pt->draw_header(C, panel); - panel->layout = NULL; - } - - panel->layout = layout; - pt->draw(C, panel); - panel->layout = NULL; - - MEM_freeN(panel); -} - int UI_popover_panel_invoke( bContext *C, int space_id, int region_id, const char *idname, - ReportList *reports) + bool keep_open, ReportList *reports) { uiLayout *layout; PanelType *pt = UI_paneltype_find(space_id, region_id, idname); @@ -296,13 +278,15 @@ int UI_popover_panel_invoke( return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } - uiPopover *pup = UI_popover_begin(C); - - layout = UI_popover_layout(pup); - - UI_popover_panel_from_type(C, layout, pt); - - UI_popover_end(C, pup, NULL); + if (keep_open) { + ui_popover_panel_create(C, NULL, NULL, ui_item_paneltype_func, pt); + } + else { + uiPopover *pup = UI_popover_begin(C); + layout = UI_popover_layout(pup); + UI_paneltype_draw(C, pt, layout); + UI_popover_end(C, pup, NULL); + } return OPERATOR_INTERFACE; } @@ -371,6 +355,9 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap) * The begin/end stype of calling popups doesn't allow to 'can_refresh' to be set. * For now close this style of popvers when accessed. */ UI_block_flag_disable(pup->block, UI_BLOCK_KEEP_OPEN); + + /* panels are created flipped (from event handling pov) */ + pup->block->flag ^= UI_BLOCK_IS_FLIP; } uiLayout *UI_popover_layout(uiPopover *pup) @@ -386,7 +373,3 @@ void UI_popover_once_clear(uiPopover *pup) #endif /** \} */ - -/* We may want to support this in future */ -/* Similar to UI_popup_menu_invoke */ -// int UI_popover_panel_invoke(bContext *C, const char *idname, ReportList *reports); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 0cea9824249..e4faac5129e 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1881,7 +1881,9 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b } #ifdef USE_NUMBUTS_LR_ALIGN - if (!drawstr_right && ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) && + if (!drawstr_right && + (but->drawflag & UI_BUT_TEXT_LEFT) && + ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) && /* if we're editing or multi-drag (fake editing), then use left alignment */ (but->editstr == NULL) && (drawstr == but->drawstr)) { @@ -4755,7 +4757,7 @@ void ui_draw_popover_back(ARegion *ar, uiStyle *UNUSED(style), uiBlock *block, r if (block) { float mval_origin[2] = {block->mx, block->my}; ui_window_to_block_fl(ar, block, &mval_origin[0], &mval_origin[1]); - ui_draw_popover_back_impl(&wcol_menu_back, rect, block->direction, mval_origin); + ui_draw_popover_back_impl(wt->wcol_theme, rect, block->direction, mval_origin); } else { wt->state(wt, 0); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index acfae0a6f0a..979a2164199 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -165,6 +165,9 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo case SPACE_TOPBAR: ts = &btheme->ttopbar; break; + case SPACE_STATUSBAR: + ts = &btheme->tstatusbar; + break; default: ts = &btheme->tv3d; break; @@ -1238,6 +1241,9 @@ void ui_theme_init_default(void) copy_v4_v4_char(tmp, btheme->ttopbar.header); copy_v4_v4_char(btheme->ttopbar.header, btheme->ttopbar.tab_inactive); copy_v4_v4_char(btheme->ttopbar.back, tmp); + + /* space statusbar */ + btheme->tstatusbar = btheme->tv3d; } void ui_style_init_default(void) @@ -3001,6 +3007,12 @@ void init_userdef_do_versions(void) } } + if (!USER_VERSION_ATLEAST(280, 16)) { + for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) { + btheme->tstatusbar = btheme->tv3d; + } + } + /** * Include next version bump. */ diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index 4081e3b0302..64d890a7314 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -29,6 +29,8 @@ * \ingroup edmesh */ +#include "MEM_guardedalloc.h" + #include "DNA_scene_types.h" #include "DNA_object_types.h" #include "DNA_mesh_types.h" @@ -41,6 +43,7 @@ #include "BLI_math.h" #include "BLI_linklist.h" +#include "BKE_layer.h" #include "BKE_context.h" #include "BKE_editmesh.h" #include "BKE_report.h" @@ -726,67 +729,87 @@ void MESH_OT_shortest_path_pick(wmOperatorType *ot) static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMesh *bm = em->bm; - BMIter iter; - BMEditSelection *ese_src, *ese_dst; - BMElem *ele_src = NULL, *ele_dst = NULL, *ele; + bool found_valid_elements = false; + + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + BMIter iter; + BMEditSelection *ese_src, *ese_dst; + BMElem *ele_src = NULL, *ele_dst = NULL, *ele; + + if ((em->bm->totvertsel == 0) && + (em->bm->totedgesel == 0) && + (em->bm->totfacesel == 0)) + { + continue; + } - /* first try to find vertices in edit selection */ - ese_src = bm->selected.last; - if (ese_src && (ese_dst = ese_src->prev) && (ese_src->htype == ese_dst->htype)) { - ele_src = ese_src->ele; - ele_dst = ese_dst->ele; - } - else { - /* if selection history isn't available, find two selected elements */ - ele_src = ele_dst = NULL; - if ((em->selectmode & SCE_SELECT_VERTEX) && (bm->totvertsel >= 2)) { - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - if (ele_src == NULL) ele_src = ele; - else if (ele_dst == NULL) ele_dst = ele; - else break; + /* first try to find vertices in edit selection */ + ese_src = bm->selected.last; + if (ese_src && (ese_dst = ese_src->prev) && (ese_src->htype == ese_dst->htype)) { + ele_src = ese_src->ele; + ele_dst = ese_dst->ele; + } + else { + /* if selection history isn't available, find two selected elements */ + ele_src = ele_dst = NULL; + if ((em->selectmode & SCE_SELECT_VERTEX) && (bm->totvertsel >= 2)) { + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { + if (ele_src == NULL) ele_src = ele; + else if (ele_dst == NULL) ele_dst = ele; + else break; + } } } - } - if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_EDGE) && (bm->totedgesel >= 2)) { - ele_src = NULL; - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - if (ele_src == NULL) ele_src = ele; - else if (ele_dst == NULL) ele_dst = ele; - else break; + if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_EDGE) && (bm->totedgesel >= 2)) { + ele_src = NULL; + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { + if (ele_src == NULL) ele_src = ele; + else if (ele_dst == NULL) ele_dst = ele; + else break; + } } } - } - if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_FACE) && (bm->totfacesel >= 2)) { - ele_src = NULL; - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - if (ele_src == NULL) ele_src = ele; - else if (ele_dst == NULL) ele_dst = ele; - else break; + if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_FACE) && (bm->totfacesel >= 2)) { + ele_src = NULL; + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { + if (ele_src == NULL) ele_src = ele; + else if (ele_dst == NULL) ele_dst = ele; + else break; + } } } } - } - if (ele_src && ele_dst) { - struct PathSelectParams op_params; - path_select_params_from_op(op, &op_params); + if (ele_src && ele_dst) { + struct PathSelectParams op_params; + path_select_params_from_op(op, &op_params); - edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst); + edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst); - return OPERATOR_FINISHED; + found_valid_elements = true; + } } - else { - BKE_report(op->reports, RPT_WARNING, "Path selection requires two matching elements to be selected"); + MEM_freeN(objects); + + if (!found_valid_elements) { + BKE_report(op->reports, + RPT_WARNING, + "Path selection requires two matching elements to be selected"); return OPERATOR_CANCELLED; } + + return OPERATOR_FINISHED; } void MESH_OT_shortest_path_select(wmOperatorType *ot) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 11f87b3710d..fd8efcd84e3 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -397,6 +397,18 @@ bool EDBM_backbuf_circle_init( * to avoid the bias interfering with distance comparisons when mixing types. * \{ */ +#define FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, select_mode_required) \ + short select_mode = select_mode_required; \ + bool fake_select_mode = (select_mode & (vc)->scene->toolsettings->selectmode) == 0; \ + if (fake_select_mode) { \ + (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \ + } ((void)0) + +#define FAKE_SELECT_MODE_END(vc, fake_select_mode) \ + if (fake_select_mode) { \ + (vc)->v3d->flag |= V3D_INVALID_BACKBUF; \ + } ((void)0) + #define FIND_NEAR_SELECT_BIAS 5 #define FIND_NEAR_CYCLE_THRESHOLD_MIN 3 @@ -470,11 +482,16 @@ BMVert *EDBM_vert_find_nearest_ex( BMVert *eve; /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ - ED_view3d_backbuf_validate(vc); + { + FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX); + ED_view3d_backbuf_validate_with_select_mode(vc, select_mode); - index = ED_view3d_backbuf_sample_rect( - vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); - eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; + index = ED_view3d_backbuf_sample_rect( + vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); + eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; + + FAKE_SELECT_MODE_END(vc, fake_select_mode); + } if (eve) { if (dist_test < *r_dist) { @@ -657,23 +674,16 @@ BMEdge *EDBM_edge_find_nearest_ex( unsigned int index; BMEdge *eed; - /* Make sure that the edges also are considered to find nearest. - * TODO: cleanup: add `selectmode` as a parameter - * XXX: Without selectmode as parameter we need to resort to this super ugly hack, - * because we should never write to evaluate data. */ - const short ts_selectmode = vc->scene->toolsettings->selectmode; - - Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id); - scene_eval->toolsettings->selectmode |= SCE_SELECT_EDGE; - /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ - ED_view3d_backbuf_validate(vc); - - /* restore `selectmode` */ - scene_eval->toolsettings->selectmode = ts_selectmode; - - index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); - eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; + { + FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE); + ED_view3d_backbuf_validate_with_select_mode(vc, select_mode); + + index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); + eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; + + FAKE_SELECT_MODE_END(vc, fake_select_mode); + } if (r_eed_zbuf) { *r_eed_zbuf = eed; @@ -834,10 +844,15 @@ BMFace *EDBM_face_find_nearest_ex( unsigned int index; BMFace *efa; - ED_view3d_backbuf_validate(vc); + { + FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE); + ED_view3d_backbuf_validate_with_select_mode(vc, select_mode); + + index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]); + efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; - index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]); - efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; + FAKE_SELECT_MODE_END(vc, fake_select_mode); + } if (r_efa_zbuf) { *r_efa_zbuf = efa; @@ -1067,6 +1082,9 @@ static bool unified_findnearest( return (hit.v.ele || hit.e.ele || hit.f.ele); } +#undef FAKE_SELECT_MODE_BEGIN +#undef FAKE_SELECT_MODE_END + /** \} */ /* -------------------------------------------------------------------- */ @@ -1703,17 +1721,6 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de mvalf[1] = (float)(vc.mval[1] = mval[1]); em = vc.em; - /* Make sure that the edges are also considered for selection. - * TODO: cleanup: add `selectmode` as a parameter */ - const short ts_selectmode = vc.scene->toolsettings->selectmode; - vc.scene->toolsettings->selectmode |= SCE_SELECT_EDGE; - - /* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */ - ED_view3d_backbuf_validate(&vc); - - /* restore `selectmode` */ - vc.scene->toolsettings->selectmode = ts_selectmode; - eed = EDBM_edge_find_nearest_ex(&vc, &dist, NULL, true, true, NULL); if (eed == NULL) { return false; diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 77c90a6591b..07812cefb6b 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -372,7 +372,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em) ED_view3d_init_mats_rv3d(obedit, ar->regiondata); struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), CTX_data_depsgraph(C), 0, + CTX_data_scene(C), CTX_data_depsgraph(C), 0, ar, CTX_wm_view3d(C)); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -444,7 +444,7 @@ static int edbm_delete_exec(bContext *C, wmOperator *op) break; case MESH_DELETE_EDGE: /* Erase Edges */ if (!(em->bm->totedgesel && - EDBM_op_callf(em, op, "delete geom=%he context=%i", BM_ELEM_SELECT, DEL_FACES))) + EDBM_op_callf(em, op, "delete geom=%he context=%i", BM_ELEM_SELECT, DEL_EDGES))) { continue; } @@ -2318,7 +2318,7 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot) RNA_def_int(ot->srna, "repeat", 1, 1, 1000, "Number of iterations to smooth the mesh", "", 1, 200); - RNA_def_float(ot->srna, "lambda_factor", 5e-5f, 1e-7f, 1000.0f, + RNA_def_float(ot->srna, "lambda_factor", 1.0f, 1e-7f, 1000.0f, "Lambda factor", "", 1e-7f, 1000.0f); RNA_def_float(ot->srna, "lambda_border", 5e-5f, 1e-7f, 1000.0f, "Lambda factor in border", "", 1e-7f, 1000.0f); @@ -5453,11 +5453,12 @@ static int edbm_split_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); - - if (em->bm->totfacesel == 0) { + if ((em->bm->totvertsel == 0) && + (em->bm->totedgesel == 0) && + (em->bm->totfacesel == 0)) + { continue; } - BMOperator bmop; EDBM_op_init(em, &bmop, op, "split geom=%hvef use_only_faces=%b", BM_ELEM_SELECT, false); BMO_op_exec(em->bm, &bmop); diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 6b22521eedd..77514ca1e8e 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -631,6 +631,10 @@ static int apply_objects_internal( la->area_shape = LA_AREA_RECT; la->area_sizey = la->area_size; } + else if ((la->area_shape == LA_AREA_DISK) && !keeps_aspect_ratio) { + la->area_shape = LA_AREA_ELLIPSE; + la->area_sizey = la->area_size; + } la->area_size *= rsmat[0][0]; la->area_sizey *= rsmat[1][1]; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 7fc3cb8863f..b8a5c138a57 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -428,7 +428,11 @@ static void PE_set_view3d_data(bContext *C, PEData *data) static bool PE_create_shape_tree(PEData *data, Object *shapeob) { - Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_object(shapeob, 0); + ModifierEvalContext ctx = { + .depsgraph = data->depsgraph, + .flag = 0, + }; + Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_object(&ctx, shapeob); memset(&data->shape_bvh, 0, sizeof(data->shape_bvh)); @@ -2959,7 +2963,7 @@ static void PE_mirror_x( } else { newpa->num_dmcache = psys_particle_dm_face_lookup( - psmd->mesh_final, psmd->mesh_deformed, newpa->num, newpa->fuv, NULL); + psmd->mesh_final, psmd->mesh_original, newpa->num, newpa->fuv, NULL); } /* update edit key pointers */ @@ -3553,7 +3557,7 @@ static int brush_add(const bContext *C, PEData *data, short number) mesh = psmd->mesh_final; } else { - mesh = psmd->mesh_deformed; + mesh = psmd->mesh_original; } BLI_assert(mesh); @@ -3587,11 +3591,11 @@ static int brush_add(const bContext *C, PEData *data, short number) add_pars[n].num = add_pars[n].num_dmcache; add_pars[n].num_dmcache = DMCACHE_ISCHILD; } - else if (mesh == psmd->mesh_deformed) { + else if (mesh == psmd->mesh_original) { /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */ add_pars[n].num = add_pars[n].num_dmcache; add_pars[n].num_dmcache = psys_particle_dm_face_lookup( - psmd->mesh_final, psmd->mesh_deformed, + psmd->mesh_final, psmd->mesh_original, add_pars[n].num, add_pars[n].fuv, NULL); } else { diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index cb7c90a6c3d..55f518a2a8c 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -680,7 +680,7 @@ static bool remap_hair_emitter( mesh = target_psmd->mesh_final; } else { - mesh = target_psmd->mesh_deformed; + mesh = target_psmd->mesh_original; } target_mesh = target_psmd->mesh_final; if (mesh == NULL) { diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c index b6608ce600f..677fc0a068e 100644 --- a/source/blender/editors/scene/scene_edit.c +++ b/source/blender/editors/scene/scene_edit.c @@ -116,7 +116,7 @@ bool ED_scene_delete(bContext *C, Main *bmain, wmWindow *win, Scene *scene) static ViewLayer *scene_change_get_new_view_layer(const WorkSpace *workspace, const Scene *scene_new) { - ViewLayer *layer_new = BKE_workspace_view_layer_get(workspace, scene_new); + ViewLayer *layer_new = BKE_workspace_view_layer_exists(workspace, scene_new); return layer_new ? layer_new : BKE_view_layer_default_view(scene_new); } @@ -202,10 +202,11 @@ bool ED_scene_view_layer_delete( BLI_assert(BLI_listbase_is_empty(&scene->view_layers) == false); ED_workspace_view_layer_unset(bmain, scene, layer, scene->view_layers.first); - BKE_workspace_view_layer_remove_references(bmain, layer); BKE_view_layer_free(layer); + BKE_workspace_view_layer_remove(bmain, layer); + DEG_id_tag_update(&scene->id, 0); DEG_relations_tag_update(bmain); WM_main_add_notifier(NC_SCENE | ND_LAYER | NA_REMOVED, scene); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 6392af2a5e0..9b7f767798f 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -147,6 +147,14 @@ int ED_operator_screen_mainwinactive(bContext *C) return 1; } +int ED_operator_scene(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + if (scene) + return 1; + return 0; +} + int ED_operator_scene_editable(bContext *C) { Scene *scene = CTX_data_scene(C); @@ -4720,10 +4728,8 @@ void ED_keymap_screen(wmKeyConfig *keyconf) RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1); RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1); - WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", UPARROWKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", DOWNARROWKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_SHIFT, 0); - kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", F10KEY, KM_PRESS, KM_ALT, 0); + kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "use_hide_panels", true); WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index a054949df22..d54996bad59 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -110,7 +110,7 @@ static void workspace_change_update_view_layer( WorkSpace *workspace_new, const WorkSpace *workspace_old, Scene *scene) { - if (!BKE_workspace_view_layer_get(workspace_new, scene)) { + if (!BKE_workspace_view_layer_exists(workspace_new, scene)) { BKE_workspace_view_layer_set(workspace_new, BKE_workspace_view_layer_get(workspace_old, scene), scene); } } @@ -199,7 +199,7 @@ bool ED_workspace_change( screen_change_update(C, win, screen_new); workspace_change_update(workspace_new, workspace_old, C, wm); - BLI_assert(BKE_workspace_view_layer_get(workspace_new, CTX_data_scene(C)) != NULL); + BLI_assert(BKE_workspace_view_layer_exists(workspace_new, CTX_data_scene(C)) != NULL); BLI_assert(CTX_wm_workspace(C) == workspace_new); WM_toolsystem_unlink_all(C, workspace_old); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 0479af3c58f..9ecdc44cd10 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -299,7 +299,7 @@ static int image_paint_poll(bContext *C) return image_paint_poll_ex(C, true); } -static int image_paint_poll_ignore_tool(bContext *C) +static int image_paint_ignore_tool_poll(bContext *C) { return image_paint_poll_ex(C, false); } @@ -1011,11 +1011,6 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int sample_color_poll(bContext *C) -{ - return (image_paint_poll_ignore_tool(C) || image_paint_poll_ignore_tool(C)); -} - void PAINT_OT_sample_color(wmOperatorType *ot) { /* identifiers */ @@ -1027,7 +1022,7 @@ void PAINT_OT_sample_color(wmOperatorType *ot) ot->exec = sample_color_exec; ot->invoke = sample_color_invoke; ot->modal = sample_color_modal; - ot->poll = sample_color_poll; + ot->poll = image_paint_ignore_tool_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index a1435d5916a..76449b61d4d 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -81,6 +81,7 @@ #include "BKE_texture.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "UI_interface.h" @@ -3083,7 +3084,7 @@ static void proj_paint_state_non_cddm_init(ProjPaintState *ps) } static void proj_paint_state_viewport_init( - ProjPaintState *ps, const char symmetry_flag) + ProjPaintState *ps, const Depsgraph *depsgraph, const char symmetry_flag) { float mat[3][3]; float viewmat[4][4]; @@ -3144,17 +3145,17 @@ static void proj_paint_state_viewport_init( invert_m4_m4(viewinv, viewmat); } else if (ps->source == PROJ_SRC_IMAGE_CAM) { - Object *cam_ob = ps->scene->camera; + Object *cam_ob_eval = DEG_get_evaluated_object(depsgraph, ps->scene->camera); CameraParams params; /* viewmat & viewinv */ - copy_m4_m4(viewinv, cam_ob->obmat); + copy_m4_m4(viewinv, cam_ob_eval->obmat); normalize_m4(viewinv); invert_m4_m4(viewmat, viewinv); /* window matrix, clipping and ortho */ BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, cam_ob); + BKE_camera_params_from_object(¶ms, cam_ob_eval); BKE_camera_params_compute_viewplane(¶ms, ps->winx, ps->winy, 1.0f, 1.0f); BKE_camera_params_compute_matrix(¶ms); @@ -3858,7 +3859,7 @@ static void project_paint_begin( proj_paint_state_cavity_init(ps); } - proj_paint_state_viewport_init(ps, symmetry_flag); + proj_paint_state_viewport_init(ps, CTX_data_depsgraph(C), symmetry_flag); /* calculate vert screen coords * run this early so we can calculate the x/y resolution of our bucket rect */ diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index f8888ad9809..b2f3c49cb00 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -50,13 +50,15 @@ #include "BKE_brush.h" #include "BKE_context.h" -#include "BKE_DerivedMesh.h" +#include "BKE_customdata.h" #include "BKE_image.h" #include "BKE_material.h" +#include "BKE_object.h" #include "BKE_paint.h" #include "BKE_report.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "RNA_access.h" #include "RNA_define.h" @@ -274,26 +276,26 @@ static void imapaint_tri_weights(float matrix[4][4], GLint view[4], } /* compute uv coordinates of mouse in face */ -static void imapaint_pick_uv(Depsgraph *depsgraph, Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2]) +static void imapaint_pick_uv(Mesh *me_eval, Scene *scene, Object *ob_eval, unsigned int faceindex, const int xy[2], float uv[2]) { - DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH); - const int tottri = dm->getNumLoopTri(dm); + const int tottri = me_eval->runtime.looptris.len; int i, findex; float p[2], w[3], absw, minabsw; float matrix[4][4], proj[4][4]; GLint view[4]; const eImagePaintMode mode = scene->toolsettings->imapaint.mode; - const MLoopTri *lt = dm->getLoopTriArray(dm); - const MPoly *mpoly = dm->getPolyArray(dm); - const MLoop *mloop = dm->getLoopArray(dm); - const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); + const MLoopTri *lt = me_eval->runtime.looptris.array; + const MVert *mvert = me_eval->mvert; + const MPoly *mpoly = me_eval->mpoly; + const MLoop *mloop = me_eval->mloop; + const int *index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX); /* get the needed opengl matrices */ glGetIntegerv(GL_VIEWPORT, view); gpuGetModelViewMatrix(matrix); gpuGetProjectionMatrix(proj); view[0] = view[1] = 0; - mul_m4_m4m4(matrix, matrix, ob->obmat); + mul_m4_m4m4(matrix, matrix, ob_eval->obmat); mul_m4_m4m4(matrix, proj, matrix); minabsw = 1e10; @@ -310,25 +312,25 @@ static void imapaint_pick_uv(Depsgraph *depsgraph, Scene *scene, Object *ob, uns const MLoopUV *tri_uv[3]; float tri_co[3][3]; - dm->getVertCo(dm, mloop[lt->tri[0]].v, tri_co[0]); - dm->getVertCo(dm, mloop[lt->tri[1]].v, tri_co[1]); - dm->getVertCo(dm, mloop[lt->tri[2]].v, tri_co[2]); + for (int j = 3; j--; ) { + copy_v3_v3(tri_co[j], mvert[mloop[lt->tri[j]].v].co); + } if (mode == IMAGEPAINT_MODE_MATERIAL) { const Material *ma; const TexPaintSlot *slot; - ma = dm->mat[mp->mat_nr]; + ma = give_current_material(ob_eval, mp->mat_nr); slot = &ma->texpaintslot[ma->paint_active_slot]; if (!(slot && slot->uvname && - (mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, slot->uvname)))) + (mloopuv = CustomData_get_layer_named(&me_eval->ldata, CD_MLOOPUV, slot->uvname)))) { - mloopuv = CustomData_get_layer(&dm->loopData, CD_MLOOPUV); + mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV); } } else { - mloopuv = CustomData_get_layer(&dm->loopData, CD_MLOOPUV); + mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV); } tri_uv[0] = &mloopuv[lt->tri[0]]; @@ -347,8 +349,6 @@ static void imapaint_pick_uv(Depsgraph *depsgraph, Scene *scene, Object *ob, uns } } } - - dm->release(dm); } /* returns 0 if not found, otherwise 1 */ @@ -452,20 +452,21 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr /* first try getting a colour directly from the mesh faces if possible */ ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = OBACT(view_layer); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); bool sample_success = false; ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL); if (ob) { Mesh *me = (Mesh *)ob->data; - DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH); + Mesh *me_eval = BKE_object_get_evaluated_mesh(depsgraph, ob); /* Or shall we just do ob_eval->mesh_evaluated ? */ ViewContext vc; const int mval[2] = {x, y}; unsigned int faceindex; unsigned int totpoly = me->totpoly; - if (dm->getLoopDataArray(dm, CD_MLOOPUV)) { + if (CustomData_has_layer(&me_eval->ldata, CD_MLOOPUV)) { ED_view3d_viewcontext_init(C, &vc); view3d_operator_needs_opengl(C); @@ -474,7 +475,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr Image *image; if (use_material) - image = imapaint_face_image(ob, me, faceindex); + image = imapaint_face_image(ob_eval, me_eval, faceindex); else image = imapaint->canvas; @@ -483,7 +484,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr if (ibuf && ibuf->rect) { float uv[2]; float u, v; - imapaint_pick_uv(depsgraph, scene, ob, faceindex, mval, uv); + imapaint_pick_uv(me_eval, scene, ob_eval, faceindex, mval, uv); sample_success = true; u = fmodf(uv[0], 1.0f); @@ -525,7 +526,6 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr } } } - dm->release(dm); } if (!sample_success) { diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 2a0be4eaf0d..cb826d86a21 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -379,6 +379,52 @@ static void action_channel_region_listener( } } +static void saction_channel_region_message_subscribe( + const struct bContext *UNUSED(C), + struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene), + struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, + struct wmMsgBus *mbus) +{ + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, sa->spacedata.first, &ptr); + + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }; + + /* All dopesheet filter settings, etc. affect the drawing of this editor, + * also same applies for all animation-related datatypes that may appear here, + * so just whitelist the entire structs for updates + */ + { + wmMsgParams_RNA msg_key_params = {{{0}}}; + StructRNA *type_array[] = { + &RNA_DopeSheet, /* dopesheet filters */ + + &RNA_ActionGroup, /* channel groups */ + + &RNA_FCurve, /* F-Curve */ + &RNA_Keyframe, + &RNA_FCurveSample, + + &RNA_GreasePencil, /* Grease Pencil */ + &RNA_GPencilLayer, + &RNA_GPencilFrame, + }; + + for (int i = 0; i < ARRAY_SIZE(type_array); i++) { + msg_key_params.ptr.type = type_array[i]; + WM_msg_subscribe_rna_params( + mbus, + &msg_key_params, + &msg_sub_value_region_tag_redraw, + __func__); + } + } +} + static void action_main_region_listener( bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene)) @@ -435,8 +481,8 @@ static void action_main_region_listener( } static void saction_main_region_message_subscribe( - const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), struct Scene *scene, + const struct bContext *C, + struct WorkSpace *workspace, struct Scene *scene, struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, struct wmMsgBus *mbus) { @@ -472,6 +518,9 @@ static void saction_main_region_message_subscribe( WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__); } } + + /* Now run the general "channels region" one - since channels and main should be in sync */ + saction_channel_region_message_subscribe(C, workspace, scene, screen, sa, ar, mbus); } /* editor level listener */ @@ -835,6 +884,7 @@ void ED_spacetype_action(void) art->init = action_channel_region_init; art->draw = action_channel_region_draw; art->listener = action_channel_region_listener; + art->message_subscribe = saction_channel_region_message_subscribe; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 8d3647def9e..6ecb454096d 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -525,6 +525,42 @@ static void graph_region_message_subscribe( WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__); } } + + /* All dopesheet filter settings, etc. affect the drawing of this editor, + * also same applies for all animation-related datatypes that may appear here, + * so just whitelist the entire structs for updates + */ + { + wmMsgParams_RNA msg_key_params = {{{0}}}; + StructRNA *type_array[] = { + &RNA_DopeSheet, /* dopesheet filters */ + + &RNA_ActionGroup, /* channel groups */ + &RNA_FCurve, /* F-Curve */ + &RNA_Keyframe, + &RNA_FCurveSample, + + &RNA_FModifier, /* F-Modifiers (XXX: Why can't we just do all subclasses too?) */ + &RNA_FModifierCycles, + &RNA_FModifierEnvelope, + &RNA_FModifierEnvelopeControlPoint, + &RNA_FModifierFunctionGenerator, + &RNA_FModifierGenerator, + &RNA_FModifierLimits, + &RNA_FModifierNoise, + &RNA_FModifierPython, + &RNA_FModifierStepped, + }; + + for (int i = 0; i < ARRAY_SIZE(type_array); i++) { + msg_key_params.ptr.type = type_array[i]; + WM_msg_subscribe_rna_params( + mbus, + &msg_key_params, + &msg_sub_value_region_tag_redraw, + __func__); + } + } } /* editor level listener */ @@ -810,6 +846,7 @@ void ED_spacetype_ipo(void) art->prefsizex = 200 + V2D_SCROLL_WIDTH; /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES; art->listener = graph_region_listener; + art->message_subscribe = graph_region_message_subscribe; art->init = graph_channel_region_init; art->draw = graph_channel_region_draw; diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 1943cb2c00b..c303a78594d 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -171,12 +171,12 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce simage->spacetype = SPACE_IMAGE; simage->zoom = 1.0f; simage->lock = true; - simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA; + simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS; simage->iuser.ok = true; simage->iuser.fie_ima = 2; simage->iuser.frames = 100; - simage->iuser.flag = IMA_SHOW_STEREO; + simage->iuser.flag = IMA_SHOW_STEREO | IMA_ANIM_ALWAYS; scopes_new(&simage->scopes); simage->sample_line_hist.height = 100; diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index dfcf5fd5d8d..d2bfcfa76df 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -410,6 +410,7 @@ static void stats_string(ViewLayer *view_layer) uintptr_t mem_in_use, mmap_in_use; char memstr[MAX_INFO_MEM_LEN]; char gpumemstr[MAX_INFO_MEM_LEN] = ""; + char formatted_mem[15]; char *s; size_t ofs = 0; @@ -445,20 +446,25 @@ static void stats_string(ViewLayer *view_layer) /* get memory statistics */ - ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem:%.2fM"), - (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0); - if (mmap_in_use) - BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0); + BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, true); + ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem: %s"), formatted_mem); + + if (mmap_in_use) { + BLI_str_format_byte_unit(formatted_mem, mmap_in_use, true); + BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%s)"), formatted_mem); + } if (GPU_mem_stats_supported()) { int gpu_free_mem, gpu_tot_memory; GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem); - ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem:%.2fM"), (double)((gpu_free_mem)) / 1024.0); + BLI_str_format_byte_unit(formatted_mem, gpu_free_mem, true); + ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem: %s"), formatted_mem); if (gpu_tot_memory) { - BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%.2fM"), (double)((gpu_tot_memory)) / 1024.0); + BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, true); + BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%s"), formatted_mem); } } diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 7245fd9c17f..e56fc12c75b 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -527,6 +527,41 @@ static void nla_channel_region_listener( } } +static void nla_channel_region_message_subscribe( + const struct bContext *UNUSED(C), + struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene), + struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar, + struct wmMsgBus *mbus) +{ + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_SpaceNLA, sa->spacedata.first, &ptr); + + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }; + + /* All dopesheet filter settings, etc. affect the drawing of this editor, + * so just whitelist the entire struct for updates + */ + { + wmMsgParams_RNA msg_key_params = {{{0}}}; + StructRNA *type_array[] = { + &RNA_DopeSheet, + }; + + for (int i = 0; i < ARRAY_SIZE(type_array); i++) { + msg_key_params.ptr.type = type_array[i]; + WM_msg_subscribe_rna_params( + mbus, + &msg_key_params, + &msg_sub_value_region_tag_redraw, + __func__); + } + } +} + /* editor level listener */ static void nla_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene), WorkSpace *UNUSED(workspace)) @@ -628,6 +663,7 @@ void ED_spacetype_nla(void) art->init = nla_channel_region_init; art->draw = nla_channel_region_draw; art->listener = nla_channel_region_listener; + art->message_subscribe = nla_channel_region_message_subscribe; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index ca6ae5955a9..19e2ae9808a 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1021,6 +1021,21 @@ static void node_shader_buts_hair(uiLayout *layout, bContext *UNUSED(C), Pointer uiItemR(layout, ptr, "component", 0, "", ICON_NONE); } +static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *row; + + row = uiLayoutRow(layout, false); + uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + + row = uiLayoutRow(layout, true); + + if (RNA_enum_get(ptr, "mode") == NODE_IES_INTERNAL) + uiItemR(row, ptr, "ies", 0, "", ICON_NONE); + else + uiItemR(row, ptr, "filepath", 0, "", ICON_NONE); +} + static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *row; @@ -1189,6 +1204,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_OUTPUT_LINESTYLE: ntype->draw_buttons = node_buts_output_linestyle; break; + case SH_NODE_TEX_IES: + ntype->draw_buttons = node_shader_buts_ies; + break; case SH_NODE_BEVEL: ntype->draw_buttons = node_shader_buts_bevel; break; diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 883078bc83c..172669ed122 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -402,7 +402,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) BLI_strncpy(view_layer->name, oldname, sizeof(view_layer->name)); /* Rename, preserving animation and compositing data. */ - BKE_view_layer_rename(scene, view_layer, newname); + BKE_view_layer_rename(bmain, scene, view_layer, newname); WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); break; } diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 73494b890ed..7ca1bc9cc9b 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -191,7 +191,6 @@ typedef enum { void outliner_free_tree(ListBase *tree); void outliner_cleanup_tree(struct SpaceOops *soops); void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree); -void outliner_remove_treestore_element(struct SpaceOops *soops, TreeStoreElem *tselem); void outliner_build_tree( struct Main *mainvar, diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index f42addb30bf..d865896e524 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -153,6 +153,9 @@ static void outliner_storage_cleanup(SpaceOops *soops) } } } + else if (soops->treehash) { + BKE_outliner_treehash_clear_used(soops->treehash); + } } } @@ -813,8 +816,11 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor } case ID_GR: { - Collection *collection = (Collection *)id; - outliner_add_collection_recursive(soops, collection, te); + /* Don't expand for instances, creates too many elements. */ + if (!(te->parent && te->parent->idcode == ID_OB)) { + Collection *collection = (Collection *)id; + outliner_add_collection_recursive(soops, collection, te); + } } default: break; @@ -1182,15 +1188,6 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i return te; } -/** - * \note Really only removes \a tselem, not it's TreeElement instance or any children. - */ -void outliner_remove_treestore_element(SpaceOops *soops, TreeStoreElem *tselem) -{ - BKE_outliner_treehash_remove_element(soops->treehash, tselem); - BLI_mempool_free(soops->treestore, tselem); -} - /* ======================================================= */ /* Sequencer mode tree building */ diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c index 896f6c016d0..6b7035dd326 100644 --- a/source/blender/editors/space_outliner/outliner_utils.c +++ b/source/blender/editors/space_outliner/outliner_utils.c @@ -142,13 +142,11 @@ TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, const ID *id) if (tselem->id == id) { return te; } - /* only deeper on scene collection or object */ - if (ELEM(te->idcode, ID_OB, ID_SCE, ID_GR)) { - TreeElement *tes = outliner_find_id(soops, &te->subtree, id); - if (tes) { - return tes; - } - } + } + + TreeElement *tes = outliner_find_id(soops, &te->subtree, id); + if (tes) { + return tes; } } return NULL; diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 8e04a2e17b8..b87d6c0b85e 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -610,9 +610,13 @@ static void bbs_mesh_solid_faces(Scene *UNUSED(scene), Object *ob) } void draw_object_backbufsel( - Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) + Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, + short select_mode) { ToolSettings *ts = scene->toolsettings; + if (select_mode == -1) { + select_mode = ts->selectmode; + } gpuMultMatrix(ob->obmat); @@ -631,8 +635,8 @@ void draw_object_backbufsel( DM_update_materials(dm, ob); - bbs_mesh_solid_EM(em, scene, v3d, ob, dm, (ts->selectmode & SCE_SELECT_FACE) != 0); - if (ts->selectmode & SCE_SELECT_FACE) + bbs_mesh_solid_EM(em, scene, v3d, ob, dm, (select_mode & SCE_SELECT_FACE) != 0); + if (select_mode & SCE_SELECT_FACE) bm_solidoffs = 1 + em->bm->totface; else { bm_solidoffs = 1; @@ -641,7 +645,7 @@ void draw_object_backbufsel( ED_view3d_polygon_offset(rv3d, 1.0); /* we draw edges if edge select mode */ - if (ts->selectmode & SCE_SELECT_EDGE) { + if (select_mode & SCE_SELECT_EDGE) { bbs_mesh_wire(em, dm, bm_solidoffs); bm_wireoffs = bm_solidoffs + em->bm->totedge; } @@ -651,7 +655,7 @@ void draw_object_backbufsel( } /* we draw verts if vert select mode. */ - if (ts->selectmode & SCE_SELECT_VERTEX) { + if (select_mode & SCE_SELECT_VERTEX) { bbs_mesh_verts(em, dm, bm_wireoffs); bm_vertoffs = bm_wireoffs + em->bm->totvert; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 99f7abba065..b44e2da3583 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -302,6 +302,7 @@ static void view3d_camera_border( { CameraParams params; rctf rect_view, rect_camera; + Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); /* get viewport viewplane */ BKE_camera_params_init(¶ms); @@ -316,7 +317,7 @@ static void view3d_camera_border( /* fallback for non camera objects */ params.clipsta = v3d->near; params.clipend = v3d->far; - BKE_camera_params_from_object(¶ms, v3d->camera); + BKE_camera_params_from_object(¶ms, camera_eval); if (no_shift) { params.shiftx = 0.0f; params.shifty = 0.0f; @@ -1172,7 +1173,7 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) if (U.uiflag & USER_SHOW_ROTVIEWICON) offset = U.widget_unit + (U.rvisize * 2) + rect->xmin; - BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info)); + BLF_draw_default(offset, rect->ymin + 0.5f * U.widget_unit, 0.0f, info, sizeof(info)); } /* ******************** view loop ***************** */ @@ -1417,13 +1418,16 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( if (rv3d->persp == RV3D_CAMOB && v3d->camera) { CameraParams params; Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); + const Object *camera_eval = DEG_get_evaluated_object( + depsgraph, + camera); BKE_camera_params_init(¶ms); /* fallback for non camera objects */ params.clipsta = v3d->near; params.clipend = v3d->far; - BKE_camera_params_from_object(¶ms, camera); - BKE_camera_multiview_params(&scene->r, ¶ms, camera, viewname); + BKE_camera_params_from_object(¶ms, camera_eval); + BKE_camera_multiview_params(&scene->r, ¶ms, camera_eval, viewname); BKE_camera_params_compute_viewplane(¶ms, sizex, sizey, scene->r.xasp, scene->r.yasp); BKE_camera_params_compute_matrix(¶ms); @@ -1597,11 +1601,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( { CameraParams params; - Object *view_camera = BKE_camera_multiview_render(scene, v3d.camera, viewname); + const Object *view_camera_eval = DEG_get_evaluated_object( + depsgraph, + BKE_camera_multiview_render(scene, v3d.camera, viewname)); BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, view_camera); - BKE_camera_multiview_params(&scene->r, ¶ms, view_camera, viewname); + BKE_camera_params_from_object(¶ms, view_camera_eval); + BKE_camera_multiview_params(&scene->r, ¶ms, view_camera_eval, viewname); BKE_camera_params_compute_viewplane(¶ms, width, height, scene->r.xasp, scene->r.yasp); BKE_camera_params_compute_matrix(¶ms); diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index 5b0f50b7a68..8505de4c7e0 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -163,7 +163,8 @@ bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const static void backdrawview3d( struct Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d, - Object *obact, Object *obedit) + Object *obact, Object *obedit, + short select_mode) { RegionView3D *rv3d = ar->regiondata; Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); @@ -263,7 +264,7 @@ static void backdrawview3d( G.f |= G_BACKBUFSEL; if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLED) != 0)) { - draw_object_backbufsel(depsgraph, scene_eval, v3d, rv3d, obact_eval); + draw_object_backbufsel(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode); } if (rv3d->gpuoffscreen) @@ -301,13 +302,18 @@ static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); } -void ED_view3d_backbuf_validate(ViewContext *vc) +void ED_view3d_backbuf_validate_with_select_mode(ViewContext *vc, short select_mode) { if (vc->v3d->flag & V3D_INVALID_BACKBUF) { - backdrawview3d(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit); + backdrawview3d(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit, select_mode); } } +void ED_view3d_backbuf_validate(ViewContext *vc) +{ + ED_view3d_backbuf_validate_with_select_mode(vc, -1); +} + /** * allow for small values [0.5 - 2.5], * and large values, FLT_MAX by clamping by the area size diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 29a61fdf969..3f59a5db9b3 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1110,7 +1110,7 @@ static void view3d_ndof_pan_zoom( static void view3d_ndof_orbit( const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar, /* optional, can be NULL*/ - ViewOpsData *vod) + ViewOpsData *vod, const bool apply_dyn_ofs) { View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; @@ -1173,7 +1173,7 @@ static void view3d_ndof_orbit( mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat); } - if (vod) { + if (apply_dyn_ofs) { viewrotate_apply_dyn_ofs(vod, rv3d->viewquat); } } @@ -1342,7 +1342,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event) } if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod); + view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true); } } @@ -1424,7 +1424,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev } if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod); + view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true); } } else { /* free/explore (like fly mode) */ @@ -1442,7 +1442,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev ED_view3d_distance_set(rv3d, 0.0f); if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL); + view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL, false); } ED_view3d_distance_set(rv3d, dist_backup); @@ -2654,7 +2654,7 @@ static void view3d_from_minmax( } if (ok_dist) { - new_dist = ED_view3d_radius_to_dist(v3d, ar, persp, true, (size / 2) * VIEW3D_MARGIN); + new_dist = ED_view3d_radius_to_dist(v3d, ar, CTX_data_depsgraph(C), persp, true, (size / 2) * VIEW3D_MARGIN); if (rv3d->is_persp) { /* don't zoom closer than the near clipping plane */ new_dist = max_ff(new_dist, v3d->near * 1.5f); @@ -2765,6 +2765,10 @@ static int view3d_all_exec(bContext *C, wmOperator *op) view3d_from_minmax(C, v3d, ar, min, max, true, smooth_viewtx); } + if (center) { + DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE); + } + return OPERATOR_FINISHED; } @@ -3678,7 +3682,8 @@ static void axis_set_view( dist = rv3d->dist; /* so we animate _from_ the camera location */ - ED_view3d_from_object(v3d->camera, rv3d->ofs, NULL, &rv3d->dist, NULL); + Object *camera_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), v3d->camera); + ED_view3d_from_object(camera_eval, rv3d->ofs, NULL, &rv3d->dist, NULL); ED_view3d_smooth_view( C, v3d, ar, smooth_viewtx, @@ -4599,12 +4604,11 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2]) cursor_curr->rotation[0] *= -1.0f; { - struct Main *bmain = CTX_data_main(C); const float mval_fl[2] = {UNPACK2(mval)}; float ray_no[3]; struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - bmain, scene, CTX_data_depsgraph(C), 0, ar, v3d); + scene, CTX_data_depsgraph(C), 0, ar, v3d); float obmat[4][4]; Object *ob_dummy = NULL; diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 0ee9adfc396..e0f3c412c56 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -225,18 +225,18 @@ void VIEW3D_OT_layers(wmOperatorType *ot) /** \name Toggle Bone selection Overlay Operator * \{ */ -static int toggle_show_see_through(bContext *C, wmOperator *UNUSED(op)) +static int toggle_show_xray(bContext *C, wmOperator *UNUSED(op)) { View3D *v3d = CTX_wm_view3d(C); - v3d->shading.flag ^= V3D_SHADING_SEE_THROUGH; + v3d->shading.flag ^= V3D_SHADING_XRAY; ED_view3d_shade_update(CTX_data_main(C), v3d, CTX_wm_area(C)); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); return OPERATOR_FINISHED; } -static int toggle_show_see_through_poll(bContext *C) +static int toggle_show_xray_poll(bContext *C) { - bool result = (ED_operator_view3d_active(C) && !ED_operator_posemode(C)); + bool result = (ED_operator_view3d_active(C) && !ED_operator_posemode(C) && !ED_operator_editmesh(C)); if (result) { // Additional test for SOLID or TEXTURE mode View3D *v3d = CTX_wm_view3d(C); @@ -245,16 +245,16 @@ static int toggle_show_see_through_poll(bContext *C) return result; } -void VIEW3D_OT_toggle_see_through_draw_option(wmOperatorType *ot) +void VIEW3D_OT_toggle_xray_draw_option(wmOperatorType *ot) { /* identifiers */ - ot->name = "Toggle Show See Though"; - ot->description = "Toggle show see through"; - ot->idname = "VIEW3D_OT_toggle_see_through_draw_option"; + ot->name = "Toggle Show X-Ray"; + ot->description = "Toggle show X-Ray"; + ot->idname = "VIEW3D_OT_toggle_xray_draw_option"; /* api callbacks */ - ot->exec = toggle_show_see_through; - ot->poll = toggle_show_see_through_poll; + ot->exec = toggle_show_xray; + ot->poll = toggle_show_xray_poll; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 794ca0dcad9..da8afa7a390 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -65,7 +65,7 @@ enum { /* view3d_header.c */ void VIEW3D_OT_layers(struct wmOperatorType *ot); -void VIEW3D_OT_toggle_see_through_draw_option(struct wmOperatorType *ot); +void VIEW3D_OT_toggle_xray_draw_option(struct wmOperatorType *ot); /* view3d_ops.c */ void view3d_operatortypes(void); @@ -133,7 +133,9 @@ void VIEW3D_OT_walk(struct wmOperatorType *ot); void VIEW3D_OT_ruler(struct wmOperatorType *ot); /* drawobject.c */ -void draw_object_backbufsel(struct Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob); +void draw_object_backbufsel( + struct Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, + short select_mode); int view3d_effective_drawtype(const struct View3D *v3d); diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index 35127c7c8c6..145f57174fd 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -35,6 +35,7 @@ #include "BLI_utildefines.h" #include "BLI_rect.h" +#include "BKE_action.h" #include "BKE_armature.h" #include "BKE_curve.h" #include "BKE_DerivedMesh.h" @@ -43,6 +44,7 @@ #include "BKE_context.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "bmesh.h" @@ -449,19 +451,21 @@ void pose_foreachScreenBone( void (*func)(void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]), void *userData, const eV3DProjTest clip_flag) { - bArmature *arm = vc->obact->data; + const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); + const bArmature *arm_eval = ob_eval->data; bPose *pose = vc->obact->pose; bPoseChannel *pchan; ED_view3d_check_mats_rv3d(vc->rv3d); for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - if (PBONE_VISIBLE(arm, pchan->bone)) { + if (PBONE_VISIBLE(arm_eval, pchan->bone)) { + bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name); float screen_co_a[2], screen_co_b[2]; int points_proj_tot = 0; /* project head location to screenspace */ - if (ED_view3d_project_float_object(vc->ar, pchan->pose_head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_object(vc->ar, pchan_eval->pose_head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) { points_proj_tot++; } else { @@ -470,7 +474,7 @@ void pose_foreachScreenBone( } /* project tail location to screenspace */ - if (ED_view3d_project_float_object(vc->ar, pchan->pose_tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_object(vc->ar, pchan_eval->pose_tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) { points_proj_tot++; } else { diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c index 87e550ba638..d3fe17123a0 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_camera.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c @@ -132,7 +132,7 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmManipulatorGroup *mg struct CameraWidgetGroup *camgroup = mgroup->customdata; Object *ob = CTX_data_active_object(C); const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - Camera *ca = ob->data; + Camera *ca = ob_eval->data; PointerRNA camera_ptr; float dir[3]; @@ -252,6 +252,7 @@ static void WIDGETGROUP_camera_message_subscribe( extern PropertyRNA rna_Camera_shift_x; extern PropertyRNA rna_Camera_shift_y; extern PropertyRNA rna_Camera_type; + extern PropertyRNA rna_Camera_lens; const PropertyRNA *props[] = { &rna_Camera_dof_distance, &rna_Camera_draw_size, @@ -261,6 +262,7 @@ static void WIDGETGROUP_camera_message_subscribe( &rna_Camera_shift_x, &rna_Camera_shift_y, &rna_Camera_type, + &rna_Camera_lens, }; PointerRNA idptr; diff --git a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c index 93b6b69a105..e659c67396d 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c @@ -45,6 +45,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "DEG_depsgraph_query.h" + #include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ @@ -80,16 +82,18 @@ static void WIDGETGROUP_lamp_spot_setup(const bContext *UNUSED(C), wmManipulator static void WIDGETGROUP_lamp_spot_refresh(const bContext *C, wmManipulatorGroup *mgroup) { + const Depsgraph *depsgraph = CTX_data_depsgraph(C); wmManipulatorWrapper *wwrapper = mgroup->customdata; wmManipulator *mpr = wwrapper->manipulator; Object *ob = CTX_data_active_object(C); + const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); Lamp *la = ob->data; float dir[3]; - negate_v3_v3(dir, ob->obmat[2]); + negate_v3_v3(dir, ob_eval->obmat[2]); WM_manipulator_set_matrix_rotation_from_z_axis(mpr, dir); - WM_manipulator_set_matrix_location(mpr, ob->obmat[3]); + WM_manipulator_set_matrix_location(mpr, ob_eval->obmat[3]); /* need to set property here for undo. TODO would prefer to do this in _init */ PointerRNA lamp_ptr; @@ -129,7 +133,7 @@ static void manipulator_area_lamp_prop_matrix_get( const Lamp *la = mpr_prop->custom_func.user_data; matrix[0][0] = la->area_size; - matrix[1][1] = (la->area_shape == LA_AREA_RECT) ? la->area_sizey : la->area_size; + matrix[1][1] = ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE) ? la->area_sizey : la->area_size; } static void manipulator_area_lamp_prop_matrix_set( @@ -140,7 +144,7 @@ static void manipulator_area_lamp_prop_matrix_set( BLI_assert(mpr_prop->type->array_length == 16); Lamp *la = mpr_prop->custom_func.user_data; - if (la->area_shape == LA_AREA_RECT) { + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { la->area_size = len_v3(matrix[0]); la->area_sizey = len_v3(matrix[1]); } @@ -179,15 +183,19 @@ static void WIDGETGROUP_lamp_area_setup(const bContext *UNUSED(C), wmManipulator static void WIDGETGROUP_lamp_area_refresh(const bContext *C, wmManipulatorGroup *mgroup) { wmManipulatorWrapper *wwrapper = mgroup->customdata; + const Depsgraph *depsgraph = CTX_data_depsgraph(C); Object *ob = CTX_data_active_object(C); - Lamp *la = ob->data; + const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + Lamp *la = ob_eval->data; wmManipulator *mpr = wwrapper->manipulator; - copy_m4_m4(mpr->matrix_basis, ob->obmat); + copy_m4_m4(mpr->matrix_basis, ob_eval->obmat); - RNA_enum_set(mpr->ptr, "transform", - ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE | - ((la->area_shape == LA_AREA_SQUARE) ? ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM : 0)); + int flag = ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE; + if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_DISK)) { + flag |= ED_MANIPULATOR_CAGE2D_XFORM_FLAG_SCALE_UNIFORM; + } + RNA_enum_set(mpr->ptr, "transform", flag); /* need to set property here for undo. TODO would prefer to do this in _init */ WM_manipulator_target_property_def_func( @@ -264,10 +272,12 @@ static void WIDGETGROUP_lamp_target_setup(const bContext *UNUSED(C), wmManipulat static void WIDGETGROUP_lamp_target_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup) { wmManipulatorWrapper *wwrapper = mgroup->customdata; + const Depsgraph *depsgraph = CTX_data_depsgraph(C); Object *ob = CTX_data_active_object(C); + const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); wmManipulator *mpr = wwrapper->manipulator; - copy_m4_m4(mpr->matrix_basis, ob->obmat); + copy_m4_m4(mpr->matrix_basis, ob_eval->obmat); unit_m4(mpr->matrix_offset); mpr->matrix_offset[3][2] = -2.4f / mpr->scale_basis; WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true); diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c index 8c3b28ffdd8..9cde5ffc5e3 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c @@ -278,7 +278,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) } else if (state == RULER_STATE_DRAG) { ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), CTX_data_depsgraph(C), 0, + CTX_data_scene(C), CTX_data_depsgraph(C), 0, ruler_info->ar, CTX_wm_view3d(C)); } else { diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index dd168c26f07..4d362ae5425 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -112,7 +112,7 @@ static void VIEW3D_OT_copybuffer(wmOperatorType *ot) /* api callbacks */ ot->exec = view3d_copybuffer_exec; - ot->poll = ED_operator_view3d_active; + ot->poll = ED_operator_scene; } static int view3d_pastebuffer_exec(bContext *C, wmOperator *op) @@ -149,7 +149,7 @@ static void VIEW3D_OT_pastebuffer(wmOperatorType *ot) /* api callbacks */ ot->exec = view3d_pastebuffer_exec; - ot->poll = ED_operator_view3d_active; + ot->poll = ED_operator_scene_editable; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -222,7 +222,7 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_snap_cursor_to_active); WM_operatortype_append(VIEW3D_OT_toggle_render); - WM_operatortype_append(VIEW3D_OT_toggle_see_through_draw_option); + WM_operatortype_append(VIEW3D_OT_toggle_xray_draw_option); WM_operatortype_append(VIEW3D_OT_ruler_add); @@ -409,7 +409,7 @@ void view3d_keymap(wmKeyConfig *keyconf) RNA_string_set(kmi->ptr, "value_2", "TEXTURED"); WM_keymap_add_item(keymap, "VIEW3D_OT_toggle_render", ZKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "VIEW3D_OT_toggle_see_through_draw_option", ZKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "VIEW3D_OT_toggle_xray_draw_option", ZKEY, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", ZKEY, KM_PRESS, 0, 0); RNA_string_set(kmi->ptr, "data_path", "space_data.use_occlude_geometry"); diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index eb86800f4a9..d0fb82eaaf4 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -282,6 +282,11 @@ float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3]) return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize; } +float ED_view3d_pixel_size_no_ui_scale(const RegionView3D *rv3d, const float co[3]) +{ + return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize; +} + /** * Calculate a depth value from \a co, use with #ED_view3d_win_to_delta */ diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index 5b616f29c60..c0af3c7caaa 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -282,7 +282,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) } else if (state == RULER_STATE_DRAG) { ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), CTX_data_depsgraph(C), 0, + CTX_data_scene(C), CTX_data_depsgraph(C), 0, ruler_info->ar, CTX_wm_view3d(C)); } else { diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 711bdac9dc0..be5653a3021 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -2122,25 +2122,24 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b continue; } /* Loop over contiguous bone hits for 'base'. */ - bool bone_selected = false; + bool changed = false; for (; col != col_end; col += 4) { /* should never fail */ if (bone != NULL) { if (select) { if ((bone->flag & BONE_UNSELECTABLE) == 0) { bone->flag |= BONE_SELECTED; - bone_selected = true; } } else { bArmature *arm = base->object->data; if ((bone->flag & BONE_UNSELECTABLE) == 0) { bone->flag &= ~BONE_SELECTED; - bone_selected = true; if (arm->act_bone == bone) arm->act_bone = NULL; } } + changed = true; } else if (!bone_only) { ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); @@ -2154,7 +2153,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b if ((base->object->pose != NULL) && bone_only) { const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16; - bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);; + bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone); bone = pchan ? pchan->bone : NULL; } else { @@ -2163,7 +2162,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b } } - if (bone_selected) { + if (changed) { if (base->object && (base->object->type == OB_ARMATURE)) { bArmature *arm = base->object->data; @@ -2174,6 +2173,8 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b DEG_id_tag_update(&vc->obact->id, OB_RECALC_DATA); } + /* copy on write tag is needed (for the armature), or else no refresh happens */ + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); } } } @@ -2750,6 +2751,9 @@ static void pose_circle_select(ViewContext *vc, const bool select, const int mva /* mask modifier ('armature' mode), etc. */ DEG_id_tag_update(&vc->obact->id, OB_RECALC_DATA); } + + /* copy on write tag is needed (for the armature), or else no refresh happens */ + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); } } diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index e18370d04a9..90b1b043de6 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -1067,6 +1067,7 @@ float ED_view3d_radius_to_dist_ortho(const float lens, const float radius) */ float ED_view3d_radius_to_dist( const View3D *v3d, const ARegion *ar, + const struct Depsgraph *depsgraph, const char persp, const bool use_aspect, const float radius) { @@ -1087,7 +1088,8 @@ float ED_view3d_radius_to_dist( BKE_camera_params_init(¶ms); params.clipsta = v3d->near; params.clipend = v3d->far; - BKE_camera_params_from_object(¶ms, v3d->camera); + Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); + BKE_camera_params_from_object(¶ms, camera_eval); lens = params.lens; sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y); @@ -1277,7 +1279,7 @@ bool ED_view3d_lock(RegionView3D *rv3d) * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. * \param dist The view distance from ofs, normally from RegionView3D.dist. */ -void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist) +void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float *dist) { float nmat[3][3]; @@ -1322,13 +1324,14 @@ void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], c /** * Set the RegionView3D members from an objects transformation and optionally lens. + * \param depsgraph The depsgraph to get the evaluated object for the lens calculation. * \param ob The object to set the view to. * \param ofs The view offset to be set, normally from RegionView3D.ofs. * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat. * \param dist The view distance from ofs to be set, normally from RegionView3D.dist. * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens. */ -void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens) +void ED_view3d_from_object(const Object *ob, float ofs[3], float quat[4], float *dist, float *lens) { ED_view3d_from_m4(ob->obmat, ofs, quat, dist); @@ -1343,6 +1346,7 @@ void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, /** * Set the object transformation from RegionView3D members. + * \param depsgraph The depsgraph to get the evaluated object parent for the transformation calculation. * \param ob The object which has the transformation assigned. * \param ofs The view offset, normally from RegionView3D.ofs. * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 2fe95f596c8..0a490a8b494 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -48,6 +48,7 @@ #include "BKE_scene.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "UI_resources.h" @@ -62,8 +63,6 @@ #include "DRW_engine.h" -#include "DEG_depsgraph_query.h" - #include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ @@ -513,25 +512,26 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); /* can be NULL */ Object *camera_ob = v3d ? v3d->camera : scene->camera; + Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob); float r_co[3]; /* the new location to apply */ float r_scale; /* only for ortho cameras */ - if (camera_ob == NULL) { + if (camera_ob_eval == NULL) { BKE_report(op->reports, RPT_ERROR, "No active camera"); return OPERATOR_CANCELLED; } /* this function does all the important stuff */ - if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, view_layer, camera_ob, r_co, &r_scale)) { + if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, view_layer, camera_ob_eval, r_co, &r_scale)) { ObjectTfmProtectedChannels obtfm; float obmat_new[4][4]; - if ((camera_ob->type == OB_CAMERA) && (((Camera *)camera_ob->data)->type == CAM_ORTHO)) { + if ((camera_ob_eval->type == OB_CAMERA) && (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) { ((Camera *)camera_ob->data)->ortho_scale = r_scale; } - copy_m4_m4(obmat_new, camera_ob->obmat); + copy_m4_m4(obmat_new, camera_ob_eval->obmat); copy_v3_v3(obmat_new[3], r_co); /* only touch location */ diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 6bbc0b7d985..a7c97ba4d4a 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -602,7 +602,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->rv3d->rflag |= RV3D_NAVIGATING; walk->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), walk->scene, CTX_data_depsgraph(C), 0, + walk->scene, CTX_data_depsgraph(C), 0, walk->ar, walk->v3d); walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 569cd4efafc..b713f18da4c 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2137,6 +2137,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->state = TRANS_STARTING; + if ((prop = RNA_struct_find_property(op->ptr, "cursor_transform")) && RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + options |= CTX_CURSOR; + } + } + if ((prop = RNA_struct_find_property(op->ptr, "texture_space")) && RNA_property_is_set(op->ptr, prop)) { if (RNA_property_boolean_get(op->ptr, prop)) { options |= CTX_TEXTURE; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 136512516e8..3718f1be9a8 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -557,6 +557,8 @@ typedef struct TransInfo { #define T_TEXTURE (1 << 3) /* transforming the camera while in camera view */ #define T_CAMERA (1 << 4) + /* transforming the 3D cursor. */ +#define T_CURSOR (1 << 5) // trans on points, having no rotation/scale #define T_POINTS (1 << 6) /** @@ -601,7 +603,9 @@ typedef struct TransInfo { /** #TransInfo.center has been set, don't change it. */ #define T_OVERRIDE_CENTER (1 << 25) -#define T_CLNOR_REBUILD (1 << 26) +#define T_MODAL_CURSOR_SET (1 << 26) + +#define T_CLNOR_REBUILD (1 << 27) /* TransInfo->modifiers */ #define MOD_CONSTRAINT_SELECT 0x01 diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 73a722d897d..c8b09eef04b 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -345,6 +345,43 @@ static void createTransTexspace(TransInfo *t) copy_v3_v3(td->ext->isize, td->ext->size); } +static void createTransCursor3D(TransInfo *t) +{ + TransData *td; + + Scene *scene = t->scene; + View3D *v3d = ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) ? t->view : NULL; + View3DCursor *cursor = ED_view3d_cursor3d_get(scene, v3d); + + if ((cursor == &scene->cursor) && ID_IS_LINKED(scene)) { + BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform"); + return; + } + + { + BLI_assert(t->data_container_len == 1); + TransDataContainer *tc = t->data_container; + tc->data_len = 1; + td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace"); + td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace"); + } + + td->flag = TD_SELECTED; + copy_v3_v3(td->center, cursor->location); + td->ob = NULL; + + unit_m3(td->mtx); + quat_to_mat3(td->axismtx, cursor->rotation); + normalize_m3(td->axismtx); + pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); + + td->loc = cursor->location; + copy_v3_v3(td->iloc, cursor->location); + + td->ext->quat = cursor->rotation; + copy_qt_qt(td->ext->iquat, cursor->rotation); +} + /* ********************* edge (for crease) ***** */ static void createTransEdge(TransInfo *t) @@ -5583,39 +5620,41 @@ static bool constraints_list_needinv(TransInfo *t, ListBase *list) /* transcribe given object into TransData for Transforming */ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) { + Depsgraph *depsgraph = t->depsgraph; Scene *scene = t->scene; + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); bool constinv; bool skip_invert = false; if (t->mode != TFM_DUMMY && ob->rigidbody_object) { float rot[3][3], scale[3]; - float ctime = BKE_scene_frame_get(scene); + float ctime = DEG_get_ctime(depsgraph); /* only use rigid body transform if simulation is running, avoids problems with initial setup of rigid bodies */ + // XXX: This needs fixing for COW. May need rigidbody_world from scene if (BKE_rigidbody_check_sim_running(scene->rigidbody_world, ctime)) { - /* save original object transform */ - copy_v3_v3(td->ext->oloc, ob->loc); + copy_v3_v3(td->ext->oloc, ob_eval->loc); if (ob->rotmode > 0) { - copy_v3_v3(td->ext->orot, ob->rot); + copy_v3_v3(td->ext->orot, ob_eval->rot); } else if (ob->rotmode == ROT_MODE_AXISANGLE) { - td->ext->orotAngle = ob->rotAngle; - copy_v3_v3(td->ext->orotAxis, ob->rotAxis); + td->ext->orotAngle = ob_eval->rotAngle; + copy_v3_v3(td->ext->orotAxis, ob_eval->rotAxis); } else { - copy_qt_qt(td->ext->oquat, ob->quat); + copy_qt_qt(td->ext->oquat, ob_eval->quat); } /* update object's loc/rot to get current rigid body transform */ - mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat); - sub_v3_v3(ob->loc, ob->dloc); + mat4_to_loc_rot_size(ob->loc, rot, scale, ob_eval->obmat); + sub_v3_v3(ob->loc, ob_eval->dloc); BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */ } } /* axismtx has the real orientation */ - copy_m3_m4(td->axismtx, ob->obmat); + copy_m3_m4(td->axismtx, ob_eval->obmat); normalize_m3(td->axismtx); td->con = ob->constraints.first; @@ -5628,6 +5667,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) constinv = constraints_list_needinv(t, &ob->constraints); /* disable constraints inversion for dummy pass */ + // XXX: Should this use ob or ob_eval?! It's not clear! if (t->mode == TFM_DUMMY) skip_invert = true; @@ -5642,7 +5682,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) td->ob = ob; td->loc = ob->loc; - copy_v3_v3(td->iloc, td->loc); + copy_v3_v3(td->iloc, ob_eval->loc); if (ob->rotmode > 0) { td->ext->rot = ob->rot; @@ -5650,8 +5690,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) td->ext->rotAngle = NULL; td->ext->quat = NULL; - copy_v3_v3(td->ext->irot, ob->rot); - copy_v3_v3(td->ext->drot, ob->drot); + copy_v3_v3(td->ext->irot, ob_eval->rot); + copy_v3_v3(td->ext->drot, ob_eval->drot); } else if (ob->rotmode == ROT_MODE_AXISANGLE) { td->ext->rot = NULL; @@ -5659,10 +5699,10 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) td->ext->rotAngle = &ob->rotAngle; td->ext->quat = NULL; - td->ext->irotAngle = ob->rotAngle; - copy_v3_v3(td->ext->irotAxis, ob->rotAxis); - // td->ext->drotAngle = ob->drotAngle; // XXX, not implemented - // copy_v3_v3(td->ext->drotAxis, ob->drotAxis); // XXX, not implemented + td->ext->irotAngle = ob_eval->rotAngle; + copy_v3_v3(td->ext->irotAxis, ob_eval->rotAxis); + // td->ext->drotAngle = ob_eval->drotAngle; // XXX, not implemented + // copy_v3_v3(td->ext->drotAxis, ob_eval->drotAxis); // XXX, not implemented } else { td->ext->rot = NULL; @@ -5670,18 +5710,18 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) td->ext->rotAngle = NULL; td->ext->quat = ob->quat; - copy_qt_qt(td->ext->iquat, ob->quat); - copy_qt_qt(td->ext->dquat, ob->dquat); + copy_qt_qt(td->ext->iquat, ob_eval->quat); + copy_qt_qt(td->ext->dquat, ob_eval->dquat); } - td->ext->rotOrder = ob->rotmode; + td->ext->rotOrder = ob_eval->rotmode; td->ext->size = ob->size; - copy_v3_v3(td->ext->isize, ob->size); - copy_v3_v3(td->ext->dscale, ob->dscale); + copy_v3_v3(td->ext->isize, ob_eval->size); + copy_v3_v3(td->ext->dscale, ob_eval->dscale); - copy_v3_v3(td->center, ob->obmat[3]); + copy_v3_v3(td->center, ob_eval->obmat[3]); - copy_m4_m4(td->ext->obmat, ob->obmat); + copy_m4_m4(td->ext->obmat, ob_eval->obmat); /* is there a need to set the global<->data space conversion matrices? */ if (ob->parent || constinv) { @@ -5691,8 +5731,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) * NOTE: some Constraints, and also Tracking should never get this * done, as it doesn't work well. */ - BKE_object_to_mat3(ob, obmtx); - copy_m3_m4(totmat, ob->obmat); + BKE_object_to_mat3(ob_eval, obmtx); + copy_m3_m4(totmat, ob_eval->obmat); invert_m3_m3(obinv, totmat); mul_m3_m3m3(td->smtx, obmtx, obinv); invert_m3_m3(td->mtx, td->smtx); @@ -6693,6 +6733,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t) { /* do nothing */ } + else if (t->flag & T_CURSOR) { + /* do nothing */ + } else { /* Objects */ int i; @@ -8325,7 +8368,14 @@ void createTransData(bContext *C, TransInfo *t) t->data_len_all = -1; /* if tests must match recalcData for correct updates */ - if (t->options & CTX_TEXTURE) { + if (t->options & CTX_CURSOR) { + t->flag |= T_CURSOR; + t->obedit_type = -1; + + createTransCursor3D(t); + countAndCleanTransDataContainer(t); + } + else if (t->options & CTX_TEXTURE) { t->flag |= T_TEXTURE; t->obedit_type = -1; diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 818ac86cf0c..576bfddd28c 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1007,6 +1007,11 @@ static void recalcData_objects(TransInfo *t) } } +static void recalcData_cursor(TransInfo *t) +{ + DEG_id_tag_update(&t->scene->id, DEG_TAG_COPY_ON_WRITE); +} + /* helper for recalcData() - for sequencer transforms */ static void recalcData_sequencer(TransInfo *t) { @@ -1056,7 +1061,10 @@ static void recalcData_gpencil_strokes(TransInfo *t) void recalcData(TransInfo *t) { /* if tests must match createTransData for correct updates */ - if (t->options & CTX_TEXTURE) { + if (t->options & CTX_CURSOR) { + recalcData_cursor(t); + } + else if (t->options & CTX_TEXTURE) { recalcData_objects(t); } else if (t->options & CTX_EDGE) { @@ -1323,9 +1331,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve prop_id = "use_even_offset"; } - if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id)) && - RNA_property_is_set(op->ptr, prop)) - { + if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) { SET_FLAG_FROM_TEST(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM); } } @@ -1629,6 +1635,10 @@ void postTrans(bContext *C, TransInfo *t) if (t->draw_handle_cursor) WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor); + if (t->flag & T_MODAL_CURSOR_SET) { + WM_cursor_modal_restore(CTX_wm_window(C)); + } + /* Free all custom-data */ freeTransCustomDataContainer(t, NULL, &t->custom); FOREACH_TRANS_DATA_CONTAINER (t, tc) { diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 2004bba4f09..270ef08be50 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -351,7 +351,8 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) case HLP_NONE: /* INPUT_VECTOR, INPUT_CUSTOM_RATIO, INPUT_CUSTOM_RATIO_FLIP */ if (t->flag & T_MODAL) { - WM_cursor_set(win, BC_NSEW_SCROLLCURSOR); + t->flag |= T_MODAL_CURSOR_SET; + WM_cursor_modal_set(win, BC_NSEW_SCROLLCURSOR); } break; case HLP_SPRING: @@ -360,7 +361,8 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) case HLP_HARROW: case HLP_VARROW: if (t->flag & T_MODAL) { - WM_cursor_set(win, CURSOR_NONE); + t->flag |= T_MODAL_CURSOR_SET; + WM_cursor_modal_set(win, CURSOR_NONE); } break; default: diff --git a/source/blender/editors/transform/transform_manipulator_3d.c b/source/blender/editors/transform/transform_manipulator_3d.c index 891d9cf67f1..b94ccf42325 100644 --- a/source/blender/editors/transform/transform_manipulator_3d.c +++ b/source/blender/editors/transform/transform_manipulator_3d.c @@ -596,8 +596,8 @@ int ED_transform_calc_manipulator_stats( RegionView3D *rv3d = ar->regiondata; Base *base; Object *ob = OBACT(view_layer); - const Object *ob_eval = NULL; - const Object *obedit_eval = NULL; + Object *ob_eval = NULL; + Object *obedit_eval = NULL; bGPdata *gpd = CTX_data_gpencil_data(C); const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)); int a, totsel = 0; @@ -629,7 +629,7 @@ int ED_transform_calc_manipulator_stats( case V3D_MANIP_GIMBAL: { float mat[3][3]; - if (gimbal_axis(ob, mat)) { + if (gimbal_axis(ob_eval, mat)) { copy_m4_m3(rv3d->twmat, mat); break; } @@ -947,7 +947,7 @@ int ED_transform_calc_manipulator_stats( int mode = TFM_ROTATION; // mislead counting bones... bah. We don't know the manipulator mode, could be mixed bool ok = false; - if ((pivot_point == V3D_AROUND_ACTIVE) && (pchan = BKE_pose_channel_active(ob))) { + if ((pivot_point == V3D_AROUND_ACTIVE) && (pchan = BKE_pose_channel_active(ob_eval))) { /* doesn't check selection or visibility intentionally */ Bone *bone = pchan->bone; if (bone) { @@ -958,11 +958,11 @@ int ED_transform_calc_manipulator_stats( } } else { - totsel = count_set_pose_transflags(&mode, 0, ob); + totsel = count_set_pose_transflags(&mode, 0, ob_eval); if (totsel) { /* use channels to get stats */ - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + for (pchan = ob_eval->pose->chanbase.first; pchan; pchan = pchan->next) { Bone *bone = pchan->bone; if (bone && (bone->flag & BONE_TRANSFORM)) { calc_tw_center(tbounds, pchan->pose_head); @@ -1018,7 +1018,7 @@ int ED_transform_calc_manipulator_stats( if (!TESTBASELIB(base)) { continue; } - const Object *base_object_eval = DEG_get_evaluated_object(depsgraph, base->object); + Object *base_object_eval = DEG_get_evaluated_object(depsgraph, base->object); if (ob == NULL) { ob = base->object; ob_eval = base_object_eval; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 4fbb50d678e..a1b78403fc4 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -566,6 +566,10 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes"); } + if (flags & P_CURSOR_EDIT) { + RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", ""); + } + if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) { RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space"); prop = RNA_def_boolean(ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel"); @@ -573,7 +577,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) } if (flags & P_CORRECT_UV) { - RNA_def_boolean(ot->srna, "correct_uv", 0, "Correct UVs", "Correct UV coordinates when transforming"); + RNA_def_boolean(ot->srna, "correct_uv", true, "Correct UVs", "Correct UV coordinates when transforming"); } if (flags & P_CENTER) { @@ -612,7 +616,10 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot) WM_operatortype_props_advanced_begin(ot); - Transform_Properties(ot, P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS | P_GPENCIL_EDIT); + Transform_Properties( + ot, + P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | P_OPTIONS | + P_GPENCIL_EDIT | P_CURSOR_EDIT); } static void TRANSFORM_OT_resize(struct wmOperatorType *ot) diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 19df46455d7..3065007ea6b 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -56,6 +56,8 @@ #include "BKE_scene.h" #include "BKE_workspace.h" +#include "DEG_depsgraph_query.h" + #include "BLT_translation.h" #include "ED_armature.h" @@ -1014,12 +1016,14 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3 } } else if (ob && (ob->mode & OB_MODE_POSE)) { - bArmature *arm = ob->data; + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + bArmature *arm = ob_eval->data; bPoseChannel *pchan; float imat[3][3], mat[3][3]; bool ok = false; - if (activeOnly && (pchan = BKE_pose_channel_active(ob))) { + if (activeOnly && (pchan = BKE_pose_channel_active(ob_eval))) { add_v3_v3(normal, pchan->pose_mat[2]); add_v3_v3(plane, pchan->pose_mat[1]); ok = true; @@ -1030,7 +1034,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3 totsel = count_bone_select(arm, &arm->bonebase, true); if (totsel) { /* use channels to get stats */ - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + for (pchan = ob_eval->pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) { add_v3_v3(normal, pchan->pose_mat[2]); add_v3_v3(plane, pchan->pose_mat[1]); @@ -1043,7 +1047,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3 /* use for both active & all */ if (ok) { /* we need the transpose of the inverse for a normal... */ - copy_m3_m4(imat, ob->obmat); + copy_m3_m4(imat, ob_eval->obmat); invert_m3_m3(mat, imat); transpose_m3(mat); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index b858f40a3ff..10de7f3ea36 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -406,11 +406,6 @@ void applyGridAbsolute(TransInfo *t) void applySnapping(TransInfo *t, float *vec) { - if (t->tsnap.project && t->tsnap.mode == SCE_SNAP_MODE_FACE) { - /* Each Trans Data already makes the snap to face */ - return; - } - if (t->tsnap.status & SNAP_FORCED) { t->tsnap.targetSnap(t); @@ -555,7 +550,9 @@ static void initSnappingMode(TransInfo *t) { /* In "Edit Strokes" mode, Snap tool can perform snap to selected or active objects (see T49632) * TODO: perform self snap in gpencil_strokes */ - t->tsnap.modeSelect = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_ALL : SNAP_NOT_SELECTED; + t->tsnap.modeSelect = ( + ((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR)) != 0) ? + SNAP_ALL : SNAP_NOT_SELECTED); } else { /* Grid if snap is not possible */ @@ -585,7 +582,7 @@ static void initSnappingMode(TransInfo *t) if (t->spacetype == SPACE_VIEW3D) { if (t->tsnap.object_context == NULL) { t->tsnap.object_context = ED_transform_snap_object_context_create_view3d( - G.main, t->scene, t->depsgraph, 0, t->ar, t->view); + t->scene, t->depsgraph, 0, t->ar, t->view); ED_transform_snap_object_context_set_editmesh_callbacks( t->tsnap.object_context, diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index db1a6cc4240..29497fe801c 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -113,7 +113,6 @@ typedef struct SnapObjectData_EditMesh { } SnapObjectData_EditMesh; struct SnapObjectContext { - Main *bmain; Scene *scene; Depsgraph *depsgraph; @@ -535,6 +534,10 @@ static bool raycastEditMesh( return retval; } } + else { + /* COW hack: Update pointers */ + treedata->em = em; + } float imat[4][4]; float timat[3][3]; /* transpose inverse matrix for normals */ @@ -2265,13 +2268,12 @@ static short snapObjectsRay( * \{ */ SnapObjectContext *ED_transform_snap_object_context_create( - Main *bmain, Scene *scene, Depsgraph *depsgraph, int flag) + Scene *scene, Depsgraph *depsgraph, int flag) { SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__); sctx->flag = flag; - sctx->bmain = bmain; sctx->scene = scene; sctx->depsgraph = depsgraph; @@ -2282,11 +2284,11 @@ SnapObjectContext *ED_transform_snap_object_context_create( } SnapObjectContext *ED_transform_snap_object_context_create_view3d( - Main *bmain, Scene *scene, Depsgraph *depsgraph, int flag, + Scene *scene, Depsgraph *depsgraph, int flag, /* extra args for view3d */ const ARegion *ar, const View3D *v3d) { - SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, depsgraph, flag); + SnapObjectContext *sctx = ED_transform_snap_object_context_create(scene, depsgraph, flag); sctx->use_v3d = true; sctx->v3d_data.ar = ar; @@ -2511,6 +2513,10 @@ static short transform_snap_context_project_view3d_mixed_impl( /* Compute the new clip_pane but do not add it yet. */ float new_clipplane[4]; plane_from_point_normal_v3(new_clipplane, loc, no); + if (dot_v3v3(snapdata.clip_plane[0], new_clipplane) > 0.0f) { + /* The plane is facing the wrong direction. */ + negate_v4(new_clipplane); + } /* Try to snap only to the polygon. */ elem = snap_mesh_polygon( diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index f07c32370fd..fceb1532077 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -567,35 +567,45 @@ void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float as } } -bool ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2], float r_max[2]) +bool ED_uvedit_minmax_multi( + Scene *scene, Image *ima, Object **objects_edit, uint objects_len, + float r_min[2], float r_max[2]) { - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; bool changed = false; + INIT_MINMAX2(r_min, r_max); - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects_edit[ob_index]; - INIT_MINMAX2(r_min, r_max); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) - continue; - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - minmax_v2v2_v2(r_min, r_max, luv->uv); - changed = true; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) + continue; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + minmax_v2v2_v2(r_min, r_max, luv->uv); + changed = true; + } } } } - return changed; } +bool ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2], float r_max[2]) +{ + return ED_uvedit_minmax_multi(scene, ima, &obedit, 1, r_min, r_max); +} + /* Be careful when using this, it bypasses all synchronization options */ void ED_uvedit_select_all(BMesh *bm) { @@ -614,27 +624,32 @@ void ED_uvedit_select_all(BMesh *bm) } } -static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[2]) +static bool ED_uvedit_median_multi(Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float co[2]) { - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; unsigned int sel = 0; + zero_v2(co); - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects_edit[ob_index]; - zero_v2(co); - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) - continue; - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { - add_v2_v2(co, luv->uv); - sel++; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) + continue; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + add_v2_v2(co, luv->uv); + sel++; + } } } } @@ -644,19 +659,24 @@ static bool ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[ return (sel != 0); } -bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], char mode) +static bool UNUSED_FUNCTION(ED_uvedit_median)(Scene *scene, Image *ima, Object *obedit, float co[2]) +{ + return ED_uvedit_median_multi(scene, ima, &obedit, 1, co); +} + +bool ED_uvedit_center_multi(Scene *scene, Image *ima, Object **objects_edit, uint objects_len, float cent[2], char mode) { bool changed = false; if (mode == V3D_AROUND_CENTER_BOUNDS) { /* bounding box */ float min[2], max[2]; - if (ED_uvedit_minmax(scene, ima, obedit, min, max)) { + if (ED_uvedit_minmax_multi(scene, ima, objects_edit, objects_len, min, max)) { mid_v2_v2v2(cent, min, max); changed = true; } } else { - if (ED_uvedit_median(scene, ima, obedit, cent)) { + if (ED_uvedit_median_multi(scene, ima, objects_edit, objects_len, cent)) { changed = true; } } @@ -664,6 +684,11 @@ bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], c return changed; } +bool ED_uvedit_center(Scene *scene, Image *ima, Object *obedit, float cent[2], char mode) +{ + return ED_uvedit_center_multi(scene, ima, &obedit, 1, cent, mode); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -3357,17 +3382,16 @@ static void uv_snap_cursor_to_pixels(SpaceImage *sima) uv_snap_to_pixel(sima->cursor, width, height); } -static bool uv_snap_cursor_to_selection(Scene *scene, Image *ima, Object *obedit, SpaceImage *sima) +static bool uv_snap_cursor_to_selection( + Scene *scene, Image *ima, Object **objects_edit, uint objects_len, SpaceImage *sima) { - return ED_uvedit_center(scene, ima, obedit, sima->cursor, sima->around); + return ED_uvedit_center_multi(scene, ima, objects_edit, objects_len, sima->cursor, sima->around); } static int uv_snap_cursor_exec(bContext *C, wmOperator *op) { SpaceImage *sima = CTX_wm_space_image(C); - Scene *scene = CTX_data_scene(C); - Object *obedit = CTX_data_edit_object(C); - Image *ima = CTX_data_edit_image(C); + bool changed = false; switch (RNA_enum_get(op->ptr, "target")) { @@ -3376,8 +3400,18 @@ static int uv_snap_cursor_exec(bContext *C, wmOperator *op) changed = true; break; case 1: - changed = uv_snap_cursor_to_selection(scene, ima, obedit, sima); + { + Scene *scene = CTX_data_scene(C); + Image *ima = CTX_data_edit_image(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, &objects_len); + changed = uv_snap_cursor_to_selection(scene, ima, objects, objects_len, sima); + MEM_freeN(objects); break; + } } if (!changed) diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 4306fe17e96..a6bfb09141c 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -396,6 +396,11 @@ void math_abs(float val1, out float outval) outval = abs(val1); } +void math_atan2(float val1, float val2, out float outval) +{ + outval = atan(val1, val2); +} + void squeeze(float val, float width, float center, out float outval) { outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width))); diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index acf054a94d5..4d59a7c9669 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -397,6 +397,10 @@ typedef enum ID_Type { ID_IS_STATIC_OVERRIDE((_id)) && \ (((ID *)(_id))->override_static->flag & STATICOVERRIDE_AUTO)) +/* No copy-on-write for these types. */ +#define ID_TYPE_IS_COW(_id_type) \ + (!ELEM(_id_type, ID_WM, ID_SCR, ID_SCRN, ID_IM, ID_MC, ID_LI)) + #ifdef GS # undef GS #endif diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h index 6294afe00e7..3a4b07cc791 100644 --- a/source/blender/makesdna/DNA_lamp_types.h +++ b/source/blender/makesdna/DNA_lamp_types.h @@ -148,6 +148,8 @@ typedef struct Lamp { #define LA_AREA_RECT 1 #define LA_AREA_CUBE 2 #define LA_AREA_BOX 3 +#define LA_AREA_DISK 4 +#define LA_AREA_ELLIPSE 5 #endif /* __DNA_LAMP_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 989e0768fc1..1d7d1b34f6b 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -740,7 +740,7 @@ typedef struct ParticleSystemModifierData { struct ParticleSystem *psys; struct Mesh *mesh_final; /* Final Mesh - its topology may differ from orig mesh. */ - struct Mesh *mesh_deformed; /* Deformed-only Mesh - its topology is same as orig mesh one. */ + struct Mesh *mesh_original; /* Original mesh that particles are attached to. */ int totdmvert, totdmedge, totdmface; short flag, pad; } ParticleSystemModifierData; @@ -1615,6 +1615,7 @@ typedef struct SDefVert { typedef struct SurfaceDeformModifierData { ModifierData modifier; + struct Depsgraph *depsgraph; struct Object *target; /* bind target object */ SDefVert *verts; /* vertex bind data */ float falloff; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index b5a3752072b..af1045ee059 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -891,6 +891,12 @@ typedef struct NodeShaderUVMap { char uv_map[64]; } NodeShaderUVMap; +typedef struct NodeShaderTexIES { + int mode; + + char filepath[1024]; /* 1024 = FILE_MAX */ +} NodeShaderTexIES; + typedef struct NodeSunBeams { float source[2]; @@ -904,6 +910,9 @@ typedef struct NodeSunBeams { /* script node flag */ #define NODE_SCRIPT_AUTO_UPDATE 1 +/* ies node mode */ +#define NODE_IES_INTERNAL 0 +#define NODE_IES_EXTERNAL 1 /* frame node flags */ #define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */ @@ -1058,6 +1067,7 @@ enum { NODE_MATH_GREATER = 16, NODE_MATH_MOD = 17, NODE_MATH_ABS = 18, + NODE_MATH_ATAN2 = 19, }; /* mix rgb node flags */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 2c39576d0c9..0559df7950d 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -2064,43 +2064,6 @@ typedef enum eGPencil_Placement_Flags { #define PE_TYPE_SOFTBODY 1 #define PE_TYPE_CLOTH 2 -/* ToolSettings.skgen_options */ -#define SKGEN_FILTER_INTERNAL (1 << 0) -#define SKGEN_FILTER_EXTERNAL (1 << 1) -#define SKGEN_SYMMETRY (1 << 2) -#define SKGEN_CUT_LENGTH (1 << 3) -#define SKGEN_CUT_ANGLE (1 << 4) -#define SKGEN_CUT_CORRELATION (1 << 5) -#define SKGEN_HARMONIC (1 << 6) -#define SKGEN_STICK_TO_EMBEDDING (1 << 7) -#define SKGEN_ADAPTIVE_DISTANCE (1 << 8) -#define SKGEN_FILTER_SMART (1 << 9) -#define SKGEN_DISP_LENGTH (1 << 10) -#define SKGEN_DISP_WEIGHT (1 << 11) -#define SKGEN_DISP_ORIG (1 << 12) -#define SKGEN_DISP_EMBED (1 << 13) -#define SKGEN_DISP_INDEX (1 << 14) - -#define SKGEN_SUB_LENGTH 0 -#define SKGEN_SUB_ANGLE 1 -#define SKGEN_SUB_CORRELATION 2 -#define SKGEN_SUB_TOTAL 3 - -/* ToolSettings.skgen_postpro */ -#define SKGEN_SMOOTH 0 -#define SKGEN_AVERAGE 1 -#define SKGEN_SHARPEN 2 - -/* ToolSettings.bone_sketching */ -#define BONE_SKETCHING 1 -#define BONE_SKETCHING_QUICK 2 -#define BONE_SKETCHING_ADJUST 4 - -/* ToolSettings.skgen_retarget_roll */ -#define SK_RETARGET_ROLL_NONE 0 -#define SK_RETARGET_ROLL_VIEW 1 -#define SK_RETARGET_ROLL_JOINT 2 - /* PhysicsSettings.flag */ #define PHYS_GLOBAL_GRAVITY 1 diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 326d42d9cb3..9817d44c96b 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -406,6 +406,7 @@ typedef struct bTheme { ThemeSpace tconsole; ThemeSpace tclip; ThemeSpace ttopbar; + ThemeSpace tstatusbar; /* 20 sets of bone colors for this theme */ ThemeWireColor tarm[20]; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index cb6031b0a3e..dd3e0c25992 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -338,7 +338,7 @@ enum { /* View3DShading->flag */ enum { V3D_SHADING_OBJECT_OUTLINE = (1 << 0), - V3D_SHADING_SEE_THROUGH = (1 << 1), + V3D_SHADING_XRAY = (1 << 1), V3D_SHADING_SHADOW = (1 << 2), }; diff --git a/source/blender/makesdna/DNA_workspace_types.h b/source/blender/makesdna/DNA_workspace_types.h index 83b6867afd3..b29e1f808c0 100644 --- a/source/blender/makesdna/DNA_workspace_types.h +++ b/source/blender/makesdna/DNA_workspace_types.h @@ -126,7 +126,7 @@ typedef struct WorkSpace { /* Store for each hook (so for each window) which layout has * been activated the last time this workspace was visible. */ ListBase hook_layout_relations DNA_PRIVATE_WORKSPACE_READ_WRITE; /* WorkSpaceDataRelation */ - ListBase scene_viewlayer_relations DNA_PRIVATE_WORKSPACE_READ_WRITE; /* WorkSpaceDataRelation */ + ListBase scene_layer_relations; /* WorkSpaceSceneRelation */ /* Feature tagging (use for addons) */ ListBase owner_ids DNA_PRIVATE_WORKSPACE_READ_WRITE; /* wmOwnerID */ @@ -180,13 +180,17 @@ typedef struct WorkSpaceDataRelation { void *parent; /* The value for this parent-data/workspace relation */ void *value; - - /** Use when we reference non-ID data, this allows use to look it up when linking in a workspace. */ - char value_name[64]; /* MAX_NAME. */ } WorkSpaceDataRelation; #endif /* DNA_PRIVATE_WORKSPACE_READ_WRITE */ +typedef struct WorkSpaceSceneRelation { + struct WorkSpaceSceneRelation *next, *prev; + + struct Scene *scene; + char view_layer[64]; /* MAX_NAME */ +} WorkSpaceSceneRelation; + /** * Little wrapper to store data that is going to be per window, but comming from the workspace. * It allows us to keep workspace and window data completely separate. diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 8e0264e208d..7431f48367c 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -527,6 +527,7 @@ extern StructRNA RNA_ShaderNodeCombineRGB; extern StructRNA RNA_ShaderNodeExtendedMaterial; extern StructRNA RNA_ShaderNodeGeometry; extern StructRNA RNA_ShaderNodeHueSaturation; +extern StructRNA RNA_ShaderNodeIESLight; extern StructRNA RNA_ShaderNodeInvert; extern StructRNA RNA_ShaderNodeLampData; extern StructRNA RNA_ShaderNodeMapping; diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 1c55925809a..80d1897f604 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -3482,7 +3482,7 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const /* we want the included C files to have warnings enabled but for the generated code * ignore unused-parameter warnings which are hard to prevent */ -#ifdef __GNUC__ +#if defined( __GNUC__) || defined(__clang__) fprintf(f, "#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n\n"); #endif diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 952d27fa18d..1ea452bf389 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -500,9 +500,9 @@ static Material *rna_IDMaterials_pop_id(ID *id, Main *bmain, ReportList *reports return ma; } -static void rna_IDMaterials_clear_id(ID *id, int remove_material_slot) +static void rna_IDMaterials_clear_id(ID *id, Main *bmain, int remove_material_slot) { - BKE_material_clear_id(G.main, id, remove_material_slot); + BKE_material_clear_id(bmain, id, remove_material_slot); DEG_id_tag_update(id, OB_RECALC_DATA); WM_main_add_notifier(NC_OBJECT | ND_DRAW, id); @@ -945,6 +945,7 @@ static void rna_def_ID_materials(BlenderRNA *brna) RNA_def_function_return(func, parm); func = RNA_def_function(srna, "clear", "rna_IDMaterials_clear_id"); + RNA_def_function_flag(func, FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Remove all materials from the data-block"); RNA_def_boolean(func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned"); } diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index a6a834465ff..5a0dec28324 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -2064,10 +2064,15 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR else prop->update(bmain, scene, ptr); } -#if 0 - if (prop->noteflag) + +#if 1 + /* TODO(campbell): Should eventually be replaced entirely by message bus (below) + * for now keep since COW, bugs are hard to track when we have other missing updates. */ + if (prop->noteflag) { WM_main_add_notifier(prop->noteflag, ptr->id.data); -#else + } +#endif + /* if C is NULL, we're updating from animation. * avoid slow-down from f-curves by not publishing (for now). */ if (C != NULL) { @@ -2075,9 +2080,15 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR /* we could add NULL check, for now don't */ WM_msg_publish_rna(mbus, ptr, prop); } -#endif + if (ptr->id.data != NULL) { + const short id_type = GS(((ID *)ptr->id.data)->name); + if (ID_TYPE_IS_COW(id_type)) { + DEG_id_tag_update(ptr->id.data, DEG_TAG_COPY_ON_WRITE); + } + } + /* End message bus. */ } - + if (!is_rna || (prop->flag & PROP_IDPROPERTY)) { /* WARNING! This is so property drivers update the display! * not especially nice */ diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 0819a5e828e..30c643388af 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -168,8 +168,10 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po { ID *id = ptr->id.data; - /* special updates for cases where rigs try to hook into armature drawing stuff - * e.g. Mask Modifier - 'Armature' option + /* 1) special updates for cases where rigs try to hook into armature drawing stuff + * e.g. Mask Modifier - 'Armature' option + * 2) tag armature for copy-on-write, so that selection status (set by addons) + * will update properly, like standard tools do already */ if (id) { if (GS(id->name) == ID_AR) { @@ -178,6 +180,8 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po if (arm->flag & ARM_HAS_VIZ_DEPS) { DEG_id_tag_update(id, OB_RECALC_DATA); } + + DEG_id_tag_update(id, DEG_TAG_COPY_ON_WRITE); } else if (GS(id->name) == ID_OB) { Object *ob = (Object *)id; @@ -186,6 +190,8 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po if (arm->flag & ARM_HAS_VIZ_DEPS) { DEG_id_tag_update(id, OB_RECALC_DATA); } + + DEG_id_tag_update(&arm->id, DEG_TAG_COPY_ON_WRITE); } } diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index 5bb24f0270d..d123cdb9773 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -394,6 +394,8 @@ static void rna_def_area_lamp(BlenderRNA *brna) static const EnumPropertyItem prop_areashape_items[] = { {LA_AREA_SQUARE, "SQUARE", 0, "Square", ""}, {LA_AREA_RECT, "RECTANGLE", 0, "Rectangle", ""}, + {LA_AREA_DISK, "DISK", 0, "Disk", ""}, + {LA_AREA_ELLIPSE, "ELLIPSE", 0, "Ellipse", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_lightprobe.c b/source/blender/makesrna/intern/rna_lightprobe.c index d4b94bfb3be..f3091ae5ee1 100644 --- a/source/blender/makesrna/intern/rna_lightprobe.c +++ b/source/blender/makesrna/intern/rna_lightprobe.c @@ -187,17 +187,17 @@ static void rna_def_lightprobe(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Intensity", "Modify the intensity of the lighting captured by this probe"); RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc"); - prop = RNA_def_property(srna, "visibility_group", PROP_POINTER, PROP_NONE); + prop = RNA_def_property(srna, "visibility_collection", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Collection"); RNA_def_property_pointer_sdna(prop, NULL, "visibility_grp"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Visibility Collection", "Restrict objects visible for this probe"); RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc"); - prop = RNA_def_property(srna, "invert_visibility_group", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "invert_visibility_collection", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LIGHTPROBE_FLAG_INVERT_GROUP); RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Invert Group", "Invert visibility group"); + RNA_def_property_ui_text(prop, "Invert Collection", "Invert visibility collection"); RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc"); /* Data preview */ diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 7dc76120097..a40606018e7 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -372,9 +372,9 @@ void RNA_def_material(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Clip Threshold", "A pixel is rendered only if its alpha value is above this threshold"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); - prop = RNA_def_property(srna, "transparent_hide_backside", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MA_BL_HIDE_BACKSIDE); - RNA_def_property_ui_text(prop, "Hide Backside", "Limit transparency to a single layer " + prop = RNA_def_property(srna, "show_transparent_backside", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "blend_flag", MA_BL_HIDE_BACKSIDE); + RNA_def_property_ui_text(prop, "Show Backside", "Limit transparency to a single layer " "(avoids transparency sorting problems)"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); @@ -519,7 +519,8 @@ static void rna_def_tex_slot(BlenderRNA *brna) RNA_def_property_ui_text(prop, "UV Map", "Name of UV map"); RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Material_update"); - prop = RNA_def_property(srna, "valid", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "is_valid", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "valid", 1); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Valid", "Slot has a valid image and UV map"); } diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 79a1ce73071..d2fb9d19acc 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -143,6 +143,7 @@ const EnumPropertyItem rna_enum_node_math_items[] = { {NODE_MATH_GREATER, "GREATER_THAN", 0, "Greater Than", ""}, {NODE_MATH_MOD, "MODULO", 0, "Modulo", ""}, {NODE_MATH_ABS, "ABSOLUTE", 0, "Absolute", ""}, + {NODE_MATH_ATAN2, "ARCTAN2", 0, "Arctan2", ""}, {0, NULL, 0, NULL, NULL} }; @@ -730,7 +731,7 @@ static bNode *rna_NodeTree_node_new(bNodeTree *ntree, bContext *C, ReportList *r return node; } -static void rna_NodeTree_node_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *node_ptr) +static void rna_NodeTree_node_remove(bNodeTree *ntree, Main *bmain, ReportList *reports, PointerRNA *node_ptr) { bNode *node = node_ptr->data; @@ -746,11 +747,11 @@ static void rna_NodeTree_node_remove(bNodeTree *ntree, ReportList *reports, Poin nodeFreeNode(ntree, node); RNA_POINTER_INVALIDATE(node_ptr); - ntreeUpdateTree(G.main, ntree); /* update group node socket links */ + ntreeUpdateTree(bmain, ntree); /* update group node socket links */ WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_NodeTree_node_clear(bNodeTree *ntree, ReportList *reports) +static void rna_NodeTree_node_clear(bNodeTree *ntree, Main *bmain, ReportList *reports) { bNode *node = ntree->nodes.first; @@ -768,7 +769,7 @@ static void rna_NodeTree_node_clear(bNodeTree *ntree, ReportList *reports) node = next_node; } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } @@ -791,7 +792,7 @@ static void rna_NodeTree_active_node_set(PointerRNA *ptr, const PointerRNA value nodeClearActive(ntree); } -static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports, +static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, Main *bmain, ReportList *reports, bNodeSocket *fromsock, bNodeSocket *tosock, int verify_limits) { @@ -833,15 +834,15 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports, if (tonode) nodeUpdate(ntree, tonode); - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); - ED_node_tag_update_nodetree(G.main, ntree, ret->tonode); + ED_node_tag_update_nodetree(bmain, ntree, ret->tonode); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } return ret; } -static void rna_NodeTree_link_remove(bNodeTree *ntree, ReportList *reports, PointerRNA *link_ptr) +static void rna_NodeTree_link_remove(bNodeTree *ntree, Main *bmain, ReportList *reports, PointerRNA *link_ptr) { bNodeLink *link = link_ptr->data; @@ -856,11 +857,11 @@ static void rna_NodeTree_link_remove(bNodeTree *ntree, ReportList *reports, Poin nodeRemLink(ntree, link); RNA_POINTER_INVALIDATE(link_ptr); - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_NodeTree_link_clear(bNodeTree *ntree, ReportList *reports) +static void rna_NodeTree_link_clear(bNodeTree *ntree, Main *bmain, ReportList *reports) { bNodeLink *link = ntree->links.first; @@ -874,7 +875,7 @@ static void rna_NodeTree_link_clear(bNodeTree *ntree, ReportList *reports) link = next_link; } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } @@ -937,7 +938,7 @@ static void rna_NodeTree_active_output_set(PointerRNA *ptr, int value) } } -static bNodeSocket *rna_NodeTree_inputs_new(bNodeTree *ntree, ReportList *reports, const char *type, const char *name) +static bNodeSocket *rna_NodeTree_inputs_new(bNodeTree *ntree, Main *bmain, ReportList *reports, const char *type, const char *name) { bNodeSocket *sock; @@ -946,13 +947,13 @@ static bNodeSocket *rna_NodeTree_inputs_new(bNodeTree *ntree, ReportList *report sock = ntreeAddSocketInterface(ntree, SOCK_IN, type, name); - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); return sock; } -static bNodeSocket *rna_NodeTree_outputs_new(bNodeTree *ntree, ReportList *reports, const char *type, const char *name) +static bNodeSocket *rna_NodeTree_outputs_new(bNodeTree *ntree, Main *bmain, ReportList *reports, const char *type, const char *name) { bNodeSocket *sock; @@ -961,13 +962,13 @@ static bNodeSocket *rna_NodeTree_outputs_new(bNodeTree *ntree, ReportList *repor sock = ntreeAddSocketInterface(ntree, SOCK_OUT, type, name); - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); return sock; } -static void rna_NodeTree_socket_remove(bNodeTree *ntree, ReportList *reports, bNodeSocket *sock) +static void rna_NodeTree_socket_remove(bNodeTree *ntree, Main *bmain, ReportList *reports, bNodeSocket *sock) { if (!rna_NodeTree_check(ntree, reports)) return; @@ -978,12 +979,12 @@ static void rna_NodeTree_socket_remove(bNodeTree *ntree, ReportList *reports, bN else { ntreeRemoveSocketInterface(ntree, sock); - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } } -static void rna_NodeTree_inputs_clear(bNodeTree *ntree, ReportList *reports) +static void rna_NodeTree_inputs_clear(bNodeTree *ntree, Main *bmain, ReportList *reports) { bNodeSocket *sock, *nextsock; @@ -995,11 +996,11 @@ static void rna_NodeTree_inputs_clear(bNodeTree *ntree, ReportList *reports) ntreeRemoveSocketInterface(ntree, sock); } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_NodeTree_outputs_clear(bNodeTree *ntree, ReportList *reports) +static void rna_NodeTree_outputs_clear(bNodeTree *ntree, Main *bmain, ReportList *reports) { bNodeSocket *sock, *nextsock; @@ -1011,11 +1012,11 @@ static void rna_NodeTree_outputs_clear(bNodeTree *ntree, ReportList *reports) ntreeRemoveSocketInterface(ntree, sock); } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_NodeTree_inputs_move(bNodeTree *ntree, int from_index, int to_index) +static void rna_NodeTree_inputs_move(bNodeTree *ntree, Main *bmain, int from_index, int to_index) { bNodeSocket *sock; @@ -1042,11 +1043,11 @@ static void rna_NodeTree_inputs_move(bNodeTree *ntree, int from_index, int to_in ntree->update |= NTREE_UPDATE_GROUP_IN; - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_NodeTree_outputs_move(bNodeTree *ntree, int from_index, int to_index) +static void rna_NodeTree_outputs_move(bNodeTree *ntree, Main *bmain, int from_index, int to_index) { bNodeSocket *sock; @@ -1073,16 +1074,18 @@ static void rna_NodeTree_outputs_move(bNodeTree *ntree, int from_index, int to_i ntree->update |= NTREE_UPDATE_GROUP_OUT; - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } static void rna_NodeTree_interface_update(bNodeTree *ntree, bContext *C) { + Main *bmain = CTX_data_main(C); + ntree->update |= NTREE_UPDATE_GROUP; - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); - ED_node_tag_update_nodetree(CTX_data_main(C), ntree, NULL); + ED_node_tag_update_nodetree(bmain, ntree, NULL); } @@ -1612,7 +1615,7 @@ static void rna_Node_name_set(PointerRNA *ptr, const char *value) BKE_animdata_fix_paths_rename_all(NULL, "nodes", oldname, node->name); } -static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier) +static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, Main *bmain, ReportList *reports, const char *type, const char *name, const char *identifier) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock; @@ -1623,14 +1626,14 @@ static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, ReportList *reports BKE_report(reports, RPT_ERROR, "Unable to create socket"); } else { - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } return sock; } -static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier) +static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, Main *bmain, ReportList *reports, const char *type, const char *name, const char *identifier) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock; @@ -1641,14 +1644,14 @@ static bNodeSocket *rna_Node_outputs_new(ID *id, bNode *node, ReportList *report BKE_report(reports, RPT_ERROR, "Unable to create socket"); } else { - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } return sock; } -static void rna_Node_socket_remove(ID *id, bNode *node, ReportList *reports, bNodeSocket *sock) +static void rna_Node_socket_remove(ID *id, bNode *node, Main *bmain, ReportList *reports, bNodeSocket *sock) { bNodeTree *ntree = (bNodeTree *)id; @@ -1658,12 +1661,12 @@ static void rna_Node_socket_remove(ID *id, bNode *node, ReportList *reports, bNo else { nodeRemoveSocket(ntree, node, sock); - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } } -static void rna_Node_inputs_clear(ID *id, bNode *node) +static void rna_Node_inputs_clear(ID *id, bNode *node, Main *bmain) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock, *nextsock; @@ -1673,11 +1676,11 @@ static void rna_Node_inputs_clear(ID *id, bNode *node) nodeRemoveSocket(ntree, node, sock); } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_Node_outputs_clear(ID *id, bNode *node) +static void rna_Node_outputs_clear(ID *id, bNode *node, Main *bmain) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock, *nextsock; @@ -1687,11 +1690,11 @@ static void rna_Node_outputs_clear(ID *id, bNode *node) nodeRemoveSocket(ntree, node, sock); } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_Node_inputs_move(ID *id, bNode *node, int from_index, int to_index) +static void rna_Node_inputs_move(ID *id, bNode *node, Main *bmain, int from_index, int to_index) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock; @@ -1717,11 +1720,11 @@ static void rna_Node_inputs_move(ID *id, bNode *node, int from_index, int to_ind } } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } -static void rna_Node_outputs_move(ID *id, bNode *node, int from_index, int to_index) +static void rna_Node_outputs_move(ID *id, bNode *node, Main *bmain, int from_index, int to_index) { bNodeTree *ntree = (bNodeTree *)id; bNodeSocket *sock; @@ -1747,7 +1750,7 @@ static void rna_Node_outputs_move(ID *id, bNode *node, int from_index, int to_in } } - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); WM_main_add_notifier(NC_NODE | NA_EDITED, ntree); } @@ -2220,7 +2223,7 @@ static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), Po return; ntree->update |= NTREE_UPDATE_GROUP; - ntreeUpdateTree(G.main, ntree); + ntreeUpdateTree(bmain, ntree); ED_node_tag_update_nodetree(bmain, ntree, NULL); } @@ -2949,6 +2952,30 @@ static bNodeSocket *rna_NodeOutputFile_slots_new(ID *id, bNode *node, bContext * return sock; } +static void rna_ShaderNodeTexIES_mode_set(PointerRNA *ptr, int value) +{ + bNode *node = (bNode *)ptr->data; + NodeShaderTexIES *nss = node->storage; + + if (nss->mode != value) { + nss->mode = value; + nss->filepath[0] = '\0'; + + /* replace text datablock by filepath */ + if (node->id) { + Text *text = (Text *)node->id; + + if (value == NODE_IES_EXTERNAL && text->name) { + BLI_strncpy(nss->filepath, text->name, sizeof(nss->filepath)); + BLI_path_rel(nss->filepath, G.main->name); + } + + id_us_min(node->id); + node->id = NULL; + } + } +} + static void rna_ShaderNodeScript_mode_set(PointerRNA *ptr, int value) { bNode *node = (bNode *)ptr->data; @@ -3291,6 +3318,12 @@ static const EnumPropertyItem node_script_mode_items[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem node_ies_mode_items[] = { + {NODE_IES_INTERNAL, "INTERNAL", 0, "Internal", "Use internal text datablock"}, + {NODE_IES_EXTERNAL, "EXTERNAL", 0, "External", "Use external .ies file"}, + {0, NULL, 0, NULL, NULL} +}; + static const EnumPropertyItem node_principled_distribution_items[] = { {SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""}, {SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", ""}, @@ -4402,6 +4435,32 @@ static void def_sh_subsurface(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeSubsurface_update"); } +static void def_sh_tex_ies(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "ies", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "id"); + RNA_def_property_struct_type(prop, "Text"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); + RNA_def_property_ui_text(prop, "IES Text", "Internal IES file"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + RNA_def_struct_sdna_from(srna, "NodeShaderTexIES", "storage"); + + prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); + RNA_def_property_ui_text(prop, "File Path", "IES light path"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_funcs(prop, NULL, "rna_ShaderNodeTexIES_mode_set", NULL); + RNA_def_property_enum_items(prop, node_ies_mode_items); + RNA_def_property_ui_text(prop, "Source", "Whether the IES file is loaded from disk or from a Text datablock"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + RNA_def_struct_sdna_from(srna, "bNode", NULL); +} + static void def_sh_script(StructRNA *srna) { PropertyRNA *prop; @@ -4897,17 +4956,17 @@ static void rna_def_cmp_output_file_slots_api(BlenderRNA *brna, PropertyRNA *cpr func = RNA_def_function(srna, "remove", "rna_Node_socket_remove"); RNA_def_function_ui_description(func, "Remove a file slot from this node"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "The socket to remove"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); func = RNA_def_function(srna, "clear", "rna_Node_inputs_clear"); RNA_def_function_ui_description(func, "Remove all file slots from this node"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); func = RNA_def_function(srna, "move", "rna_Node_inputs_move"); RNA_def_function_ui_description(func, "Move a file slot to another position"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); parm = RNA_def_int(func, "from_index", -1, 0, INT_MAX, "From Index", "Index of the socket to move", 0, 10000); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_int(func, "to_index", -1, 0, INT_MAX, "To Index", "Target index for the socket", 0, 10000); @@ -7640,7 +7699,7 @@ static void rna_def_node_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int i func = RNA_def_function(srna, "new", newfunc); RNA_def_function_ui_description(func, "Add a socket to this node"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_string(func, "type", NULL, MAX_NAME, "Type", "Data type"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); @@ -7652,17 +7711,17 @@ static void rna_def_node_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int i func = RNA_def_function(srna, "remove", "rna_Node_socket_remove"); RNA_def_function_ui_description(func, "Remove a socket from this node"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "socket", "NodeSocket", "", "The socket to remove"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); func = RNA_def_function(srna, "clear", clearfunc); RNA_def_function_ui_description(func, "Remove all sockets from this node"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); func = RNA_def_function(srna, "move", movefunc); RNA_def_function_ui_description(func, "Move a socket to another position"); - RNA_def_function_flag(func, FUNC_USE_SELF_ID); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); parm = RNA_def_int(func, "from_index", -1, 0, INT_MAX, "From Index", "Index of the socket to move", 0, 10000); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_int(func, "to_index", -1, 0, INT_MAX, "To Index", "Target index for the socket", 0, 10000); @@ -8033,14 +8092,14 @@ static void rna_def_nodetree_nodes_api(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "remove", "rna_NodeTree_node_remove"); RNA_def_function_ui_description(func, "Remove a node from this node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "node", "Node", "", "The node to remove"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); func = RNA_def_function(srna, "clear", "rna_NodeTree_node_clear"); RNA_def_function_ui_description(func, "Remove all nodes from this node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Node"); @@ -8063,7 +8122,7 @@ static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "new", "rna_NodeTree_link_new"); RNA_def_function_ui_description(func, "Add a node link to this node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "input", "NodeSocket", "", "The input socket"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); parm = RNA_def_pointer(func, "output", "NodeSocket", "", "The output socket"); @@ -8075,14 +8134,14 @@ static void rna_def_nodetree_link_api(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "remove", "rna_NodeTree_link_remove"); RNA_def_function_ui_description(func, "remove a node link from the node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "link", "NodeLink", "", "The node link to remove"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); func = RNA_def_function(srna, "clear", "rna_NodeTree_link_clear"); RNA_def_function_ui_description(func, "remove all node links from the node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); } static void rna_def_node_tree_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, int in_out) @@ -8103,7 +8162,7 @@ static void rna_def_node_tree_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, func = RNA_def_function(srna, "new", newfunc); RNA_def_function_ui_description(func, "Add a socket to this node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_string(func, "type", NULL, MAX_NAME, "Type", "Data type"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); @@ -8114,16 +8173,17 @@ static void rna_def_node_tree_sockets_api(BlenderRNA *brna, PropertyRNA *cprop, func = RNA_def_function(srna, "remove", "rna_NodeTree_socket_remove"); RNA_def_function_ui_description(func, "Remove a socket from this node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "socket", "NodeSocketInterface", "", "The socket to remove"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); func = RNA_def_function(srna, "clear", clearfunc); RNA_def_function_ui_description(func, "Remove all sockets from this node tree"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); func = RNA_def_function(srna, "move", movefunc); RNA_def_function_ui_description(func, "Move a socket to another position"); + RNA_def_function_flag(func, FUNC_USE_MAIN); parm = RNA_def_int(func, "from_index", -1, 0, INT_MAX, "From Index", "Index of the socket to move", 0, 10000); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_int(func, "to_index", -1, 0, INT_MAX, "To Index", "Target index for the socket", 0, 10000); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 04507d1ed7e..a01192dad68 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -89,6 +89,8 @@ static const EnumPropertyItem space_items[] = { #include "DNA_scene_types.h" #include "DNA_view3d_types.h" +#include "DEG_depsgraph_query.h" + #include "MEM_guardedalloc.h" static void rna_Object_select_set(Object *ob, bContext *C, ReportList *reports, int action) @@ -173,13 +175,14 @@ static void rna_Object_mat_convert_space(Object *ob, ReportList *reports, bPoseC } static void rna_Object_calc_matrix_camera( - Object *ob, float mat_ret[16], int width, int height, float scalex, float scaley) + Object *ob, Depsgraph *depsgraph, float mat_ret[16], int width, int height, float scalex, float scaley) { + const Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); CameraParams params; /* setup parameters */ BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, ob); + BKE_camera_params_from_object(¶ms, ob_eval); /* compute matrix, viewplane, .. */ BKE_camera_params_compute_viewplane(¶ms, width, height, scalex, scaley); @@ -189,9 +192,9 @@ static void rna_Object_calc_matrix_camera( } static void rna_Object_camera_fit_coords( - Object *ob, Scene *scene, int num_cos, float *cos, float co_ret[3], float *scale_ret) + Object *ob, Depsgraph *depsgraph, int num_cos, float *cos, float co_ret[3], float *scale_ret) { - BKE_camera_view_frame_fit_to_coords(scene, (const float (*)[3])cos, num_cos / 3, ob, co_ret, scale_ret); + BKE_camera_view_frame_fit_to_coords(depsgraph, (const float (*)[3])cos, num_cos / 3, ob, co_ret, scale_ret); } /* copied from Mesh_getFromObject and adapted to RNA interface */ @@ -518,6 +521,9 @@ void RNA_api_object(StructRNA *srna) func = RNA_def_function(srna, "calc_matrix_camera", "rna_Object_calc_matrix_camera"); RNA_def_function_ui_description(func, "Generate the camera projection matrix of this object " "(mostly useful for Camera and Lamp types)"); + parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "", + "Depsgraph to get evaluated data from"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_property(func, "result", PROP_FLOAT, PROP_MATRIX); RNA_def_property_multi_array(parm, 2, rna_matrix_dimsize_4x4); RNA_def_property_ui_text(parm, "", "The camera projection matrix"); @@ -530,7 +536,8 @@ void RNA_api_object(StructRNA *srna) func = RNA_def_function(srna, "camera_fit_coords", "rna_Object_camera_fit_coords"); RNA_def_function_ui_description(func, "Compute the coordinate (and scale for ortho cameras) " "given object should be to 'see' all given coordinates"); - parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene to get render size information from, if available"); + parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "", + "Depsgraph to get evaluated data from"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_float_array(func, "coordinates", 1, NULL, -FLT_MAX, FLT_MAX, "", "Coordinates to fit in", -FLT_MAX, FLT_MAX); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 27f9932ebde..4599ec0f9c5 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -175,11 +175,10 @@ const EnumPropertyItem rna_enum_snap_element_items[] = { }; const EnumPropertyItem rna_enum_snap_node_element_items[] = { - {SCE_SNAP_MODE_GRID , "GRID" , ICON_SNAP_GRID, "Grid", "Snap to grid"}, - {SCE_SNAP_MODE_NODE_X, "NODE_X" , ICON_SNAP_EDGE, "Node X", "Snap to left/right node border"}, - {SCE_SNAP_MODE_NODE_Y, "NODE_Y" , ICON_SNAP_EDGE, "Node Y", "Snap to top/bottom node border"}, - {SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y, - "NODE_XY", ICON_SNAP_EDGE, "Node X / Y", "Snap to any node border"}, + {SCE_SNAP_MODE_GRID, "GRID", ICON_SNAP_GRID, "Grid", "Snap to grid"}, + {SCE_SNAP_MODE_NODE_X, "NODE_X", ICON_SNAP_EDGE, "Node X", "Snap to left/right node border"}, + {SCE_SNAP_MODE_NODE_Y, "NODE_Y", ICON_SNAP_EDGE, "Node Y", "Snap to top/bottom node border"}, + {SCE_SNAP_MODE_NODE_X | SCE_SNAP_MODE_NODE_Y, "NODE_XY", ICON_SNAP_EDGE, "Node X / Y", "Snap to any node border"}, {0, NULL, 0, NULL, NULL} }; @@ -1486,7 +1485,7 @@ void rna_ViewLayer_name_set(PointerRNA *ptr, const char *value) { Scene *scene = (Scene *)ptr->id.data; ViewLayer *view_layer = (ViewLayer *)ptr->data; - BKE_view_layer_rename(scene, view_layer, value); + BKE_view_layer_rename(G.main, scene, view_layer, value); } static void rna_SceneRenderView_name_set(PointerRNA *ptr, const char *value) @@ -5866,7 +5865,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_range(prop, 1, INT_MAX); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "taa_reprojection", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_taa_reprojection", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_TAA_REPROJECTION); RNA_def_property_boolean_default(prop, 1); RNA_def_property_ui_text(prop, "Viewport Denoising", "Denoise image using temporal reprojection " @@ -5874,7 +5873,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Screen Space Subsurface Scattering */ - prop = RNA_def_property(srna, "sss_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_sss", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSS_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Subsurface Scattering", "Enable screen space subsurface scattering"); @@ -5892,7 +5891,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "sss_separate_albedo", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_sss_separate_albedo", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSS_SEPARATE_ALBEDO); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Separate Albedo", "Avoid albedo being blured by the subsurface scattering " @@ -5900,19 +5899,19 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Screen Space Reflection */ - prop = RNA_def_property(srna, "ssr_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_ssr", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSR_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Screen Space Reflections", "Enable screen space reflection"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "ssr_refraction", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_ssr_refraction", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSR_REFRACTION); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Screen Space Refractions", "Enable screen space Refractions"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "ssr_halfres", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_ssr_halfres", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSR_HALF_RESOLUTION); RNA_def_property_boolean_default(prop, 1); RNA_def_property_ui_text(prop, "Half Res Trace", "Raytrace at a lower resolution"); @@ -5950,7 +5949,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Volumetrics */ - prop = RNA_def_property(srna, "volumetric_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_volumetric", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_VOLUMETRIC_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Volumetrics", "Enable scattering and absorbance of volumetric material"); @@ -5988,7 +5987,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Exponential Sampling", "Distribute more samples closer to the camera"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "volumetric_lights", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_volumetric_lights", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_VOLUMETRIC_LIGHTS); RNA_def_property_boolean_default(prop, 1); RNA_def_property_ui_text(prop, "Volumetric Lighting", "Enable scene lamps interactions with volumetrics"); @@ -6000,7 +5999,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Clamp", "Maximum light contribution, reducing noise"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "volumetric_shadows", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_volumetric_shadows", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_VOLUMETRIC_SHADOWS); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Volumetric Shadows", "Generate shadows from volumetric material (Very expensive)"); @@ -6012,26 +6011,26 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Volumetric Shadow Samples", "Number of samples to compute volumetric shadowing"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "volumetric_colored_transmittance", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_volumetric_colored_transmittance", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_VOLUMETRIC_COLORED); RNA_def_property_boolean_default(prop, 1); RNA_def_property_ui_text(prop, "Colored Transmittance", "Enable wavelength dependent volumetric transmittance"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Ambient Occlusion */ - prop = RNA_def_property(srna, "gtao_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_gtao", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_GTAO_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Ambient Occlusion", "Enable ambient occlusion to simulate medium scale indirect shadowing"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "gtao_use_bent_normals", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_gtao_bent_normals", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_GTAO_BENT_NORMALS); RNA_def_property_boolean_default(prop, 1); RNA_def_property_ui_text(prop, "Bent Normals", "Compute main non occluded direction to sample the environment"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "gtao_bounce", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_gtao_bounce", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_GTAO_BOUNCE); RNA_def_property_boolean_default(prop, 1); RNA_def_property_ui_text(prop, "Bounces Approximation", "An approximation to simulate light bounces " @@ -6059,7 +6058,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Depth of Field */ - prop = RNA_def_property(srna, "dof_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_DOF_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Depth of Field", "Enable depth of field using the values from the active camera"); @@ -6080,7 +6079,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Bloom */ - prop = RNA_def_property(srna, "bloom_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_bloom", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_BLOOM_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Bloom", "High brighness pixels generate a glowing effect"); @@ -6127,7 +6126,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); /* Motion blur */ - prop = RNA_def_property(srna, "motion_blur_enable", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_motion_blur", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_MOTION_BLUR_ENABLED); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "Motion Blur", "Enable motion blur effect (only in camera view)"); @@ -6164,7 +6163,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Directional Shadows Resolution", "Size of sun lamps shadow maps"); RNA_def_property_flag(prop, PROP_OVERRIDABLE_STATIC); - prop = RNA_def_property(srna, "shadow_high_bitdepth", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "use_shadow_high_bitdepth", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SHADOW_HIGH_BITDEPTH); RNA_def_property_boolean_default(prop, 0); RNA_def_property_ui_text(prop, "High Bitdepth", "Use 32bit shadows"); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index a3e403154f9..a307aff6e96 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -144,7 +144,8 @@ static void rna_Scene_update_tagged(Scene *scene, Main *bmain) #endif } -static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int preview, const char *view, char *name) +static void rna_SceneRender_get_frame_path( + RenderData *rd, Main *bmain, int frame, int preview, const char *view, char *name) { const char *suffix = BKE_scene_multiview_view_suffix_get(rd, view); @@ -157,7 +158,7 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int previe } else { BKE_image_path_from_imformat( - name, rd->pic, G.main->name, (frame == INT_MIN) ? rd->cfra : frame, + name, rd->pic, bmain->name, (frame == INT_MIN) ? rd->cfra : frame, &rd->im_format, (rd->scemode & R_EXTENSION) != 0, true, suffix); } } @@ -172,7 +173,7 @@ static void rna_Scene_ray_cast( Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); SnapObjectContext *sctx = ED_transform_snap_object_context_create( - G.main, scene, depsgraph, 0); + scene, depsgraph, 0); bool ret = ED_transform_snap_object_project_ray_ex( sctx, @@ -390,6 +391,7 @@ void RNA_api_scene_render(StructRNA *srna) PropertyRNA *parm; func = RNA_def_function(srna, "frame_path", "rna_SceneRender_get_frame_path"); + RNA_def_function_flag(func, FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Return the absolute path to the filename to be written for a given frame"); RNA_def_int(func, "frame", INT_MIN, INT_MIN, INT_MAX, "", "Frame number to use, if unset the current frame will be used", MINAFRAME, MAXFRAME); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index e555c2ae52a..65edc619ced 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -655,12 +655,7 @@ static int rna_3DViewShading_type_get(PointerRNA *ptr) RenderEngineType *type = RE_engines_find(scene->r.engine); View3D *v3d = (View3D *)ptr->data; - if (BKE_scene_uses_blender_eevee(scene)) { - if (v3d->drawtype == OB_MATERIAL) { - return OB_RENDER; - } - } - else if (v3d->drawtype == OB_RENDER) { + if (!BKE_scene_uses_blender_eevee(scene) && v3d->drawtype == OB_RENDER) { if (!(type && type->render_to_view)) { return OB_MATERIAL; } @@ -693,6 +688,7 @@ static const EnumPropertyItem *rna_3DViewShading_type_itemf( RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_TEXTURE); if (BKE_scene_uses_blender_eevee(scene)) { + RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_MATERIAL); RNA_enum_items_add_value(&item, &totitem, rna_enum_shading_type_items, OB_RENDER); } else { @@ -711,7 +707,7 @@ static const EnumPropertyItem *rna_3DViewShading_type_itemf( static int rna_View3DShading_studio_light_orientation_get(PointerRNA *ptr) { View3D *v3d = (View3D *)ptr->data; - StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light); + StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light, 0); return sl->flag & (STUDIOLIGHT_ORIENTATION_WORLD | STUDIOLIGHT_ORIENTATION_CAMERA); } static void rna_View3DShading_studio_light_orientation_set(PointerRNA *UNUSED(ptr), int UNUSED(value)) @@ -721,7 +717,9 @@ static void rna_View3DShading_studio_light_orientation_set(PointerRNA *UNUSED(pt static int rna_View3DShading_studio_light_get(PointerRNA *ptr) { View3D *v3d = (View3D *)ptr->data; - StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light); + const int flag = v3d->drawtype == OB_MATERIAL? STUDIOLIGHT_ORIENTATION_WORLD: 0; + StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light, flag); + BLI_strncpy(v3d->shading.studio_light, sl->name, FILE_MAXFILE); return sl->index; } @@ -733,19 +731,40 @@ static void rna_View3DShading_studio_light_set(PointerRNA *ptr, int value) } static const EnumPropertyItem *rna_View3DShading_studio_light_itemf( - bContext *UNUSED(C), PointerRNA *UNUSED(ptr), + bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { + View3D *v3d = (View3D *)ptr->data; EnumPropertyItem *item = NULL; EnumPropertyItem *lastitem; int totitem = 0; + bool show_studiolight; LISTBASE_FOREACH(StudioLight *, sl, BKE_studiolight_listbase()) { - if (totitem < NUM_STUDIOLIGHT_ITEMS) { - RNA_enum_items_add_value(&item, &totitem, rna_enum_studio_light_items, totitem); + show_studiolight = false; + int icon_id = sl->irradiance_icon_id; + + if ((sl->flag & STUDIOLIGHT_EXTERNAL_FILE) == 0) { + /* always show internal lights */ + show_studiolight = true; + } else { + switch (v3d->drawtype) { + case OB_SOLID: + case OB_TEXTURE: + show_studiolight = true; + break; + case OB_MATERIAL: + show_studiolight = (sl->flag & STUDIOLIGHT_ORIENTATION_WORLD) > 0; + icon_id = sl->radiance_icon_id; + break; + } + } + + if (show_studiolight && totitem < NUM_STUDIOLIGHT_ITEMS) { + RNA_enum_items_add_value(&item, &totitem, rna_enum_studio_light_items, sl->index); lastitem = &item[totitem - 1]; lastitem->value = sl->index; - lastitem->icon = sl->icon_id; + lastitem->icon = icon_id; lastitem->name = sl->name; } } @@ -2038,10 +2057,10 @@ static void rna_def_space_image_uv(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Texture Paint UVs", "Draw overlay of texture paint uv layer"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); - prop = RNA_def_property(srna, "show_normalized_coords", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_COORDFLOATS); - RNA_def_property_ui_text(prop, "Normalized Coordinates", - "Display UV coordinates from 0.0 to 1.0 rather than in pixels"); + prop = RNA_def_property(srna, "show_pixel_coords", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SI_COORDFLOATS); + RNA_def_property_ui_text(prop, "Pixel Coordinates", + "Display UV coordinates in pixels rather than from 0.0 to 1.0"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); prop = RNA_def_property(srna, "show_faces", PROP_BOOLEAN, PROP_NONE); @@ -2305,10 +2324,10 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Shadow", "Show Shadow"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "show_see_through", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_SEE_THROUGH); + prop = RNA_def_property(srna, "show_xray", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "shading.flag", V3D_SHADING_XRAY); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "See Through", "Show whole scene transparent"); + RNA_def_property_ui_text(prop, "X-Ray", "Show whole scene transparent"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "object_outline_color", PROP_FLOAT, PROP_COLOR); @@ -2475,7 +2494,7 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "transparent_bones", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "show_transparent_bones", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "overlay.arm_flag", V3D_OVERLAY_ARM_TRANSP_BONES); RNA_def_property_ui_text(prop, "Transparent Bones", "Display bones as transparent"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index 9e868cf17e9..173eaf56f0c 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -914,6 +914,16 @@ static void rna_UILayout_emboss_set(PointerRNA *ptr, int value) uiLayoutSetEmboss(ptr->data, value); } +static int rna_UILayout_property_split_get(PointerRNA *ptr) +{ + return uiLayoutGetPropSep(ptr->data); +} + +static void rna_UILayout_property_split_set(PointerRNA *ptr, int value) +{ + uiLayoutSetPropSep(ptr->data, value); +} + #else /* RNA_RUNTIME */ static void rna_def_ui_layout(BlenderRNA *brna) @@ -978,6 +988,9 @@ static void rna_def_ui_layout(BlenderRNA *brna) prop = RNA_def_property(srna, "emboss", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, emboss_items); RNA_def_property_enum_funcs(prop, "rna_UILayout_emboss_get", "rna_UILayout_emboss_set", NULL); + + prop = RNA_def_property(srna, "use_property_split", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_UILayout_property_split_get", "rna_UILayout_property_split_set"); } static void rna_def_panel(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 741a1a87eb1..fef4cc3ed8e 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2962,6 +2962,20 @@ static void rna_def_userdef_theme_space_topbar(BlenderRNA *brna) rna_def_userdef_theme_spaces_main(srna); } +static void rna_def_userdef_theme_space_statusbar(BlenderRNA *brna) +{ + StructRNA *srna; + + /* space_statusbar */ + + srna = RNA_def_struct(brna, "ThemeStatusBar", NULL); + RNA_def_struct_sdna(srna, "ThemeSpace"); + RNA_def_struct_clear_flag(srna, STRUCT_UNDO); + RNA_def_struct_ui_text(srna, "Theme Status Bar", "Theme settings for the Status Bar"); + + rna_def_userdef_theme_spaces_main(srna); +} + static void rna_def_userdef_themes(BlenderRNA *brna) { StructRNA *srna; @@ -2987,6 +3001,7 @@ static void rna_def_userdef_themes(BlenderRNA *brna) {17, "CONSOLE", ICON_CONSOLE, "Python Console", ""}, {20, "CLIP_EDITOR", ICON_CLIP, "Movie Clip Editor", ""}, {21, "TOPBAR", ICON_NONE, "Top Bar", ""}, + {22, "STATUSBAR", ICON_NONE, "Status Bar", ""}, {0, NULL, 0, NULL, NULL} }; @@ -3114,6 +3129,12 @@ static void rna_def_userdef_themes(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "ttopbar"); RNA_def_property_struct_type(prop, "ThemeTopBar"); RNA_def_property_ui_text(prop, "Top Bar", ""); + + prop = RNA_def_property(srna, "statusbar", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "tstatusbar"); + RNA_def_property_struct_type(prop, "ThemeStatusBar"); + RNA_def_property_ui_text(prop, "Status Bar", ""); } static void rna_def_userdef_addon(BlenderRNA *brna) @@ -3204,6 +3225,7 @@ static void rna_def_userdef_dothemes(BlenderRNA *brna) rna_def_userdef_theme_space_console(brna); rna_def_userdef_theme_space_clip(brna); rna_def_userdef_theme_space_topbar(brna); + rna_def_userdef_theme_space_statusbar(brna); rna_def_userdef_theme_colorset(brna); rna_def_userdef_themes(brna); } diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 4a67b8318bb..e74d9087427 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -390,7 +390,7 @@ static Mesh *arrayModifier_doArray( vgroup_start_cap_remap = BKE_object_defgroup_index_map_create( amd->start_cap, ctx->object, &vgroup_start_cap_remap_len); - start_cap_mesh = BKE_modifier_get_evaluated_mesh_from_object(amd->start_cap, ctx->flag); + start_cap_mesh = BKE_modifier_get_evaluated_mesh_from_object(ctx, amd->start_cap); if (start_cap_mesh) { start_cap_nverts = start_cap_mesh->totvert; start_cap_nedges = start_cap_mesh->totedge; @@ -402,7 +402,7 @@ static Mesh *arrayModifier_doArray( vgroup_end_cap_remap = BKE_object_defgroup_index_map_create( amd->end_cap, ctx->object, &vgroup_end_cap_remap_len); - end_cap_mesh = BKE_modifier_get_evaluated_mesh_from_object(amd->end_cap, ctx->flag); + end_cap_mesh = BKE_modifier_get_evaluated_mesh_from_object(ctx, amd->end_cap); if (end_cap_mesh) { end_cap_nverts = end_cap_mesh->totvert; end_cap_nedges = end_cap_mesh->totedge; diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index ebe5aacd888..73d1388d88f 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -56,6 +56,8 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DEG_depsgraph_query.h" + #include "MEM_guardedalloc.h" #include "bmesh.h" @@ -173,18 +175,19 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes if (!bmd->object) return mesh; - mesh_other = BKE_modifier_get_evaluated_mesh_from_object(bmd->object, ctx->flag); - + mesh_other = BKE_modifier_get_evaluated_mesh_from_object(ctx, bmd->object); if (mesh_other) { Mesh *result; + Object *object_eval = DEG_get_evaluated_object(ctx->depsgraph, ctx->object); + Object *other_eval = DEG_get_evaluated_object(ctx->depsgraph, bmd->object); /* when one of objects is empty (has got no faces) we could speed up * calculation a bit returning one of objects' derived meshes (or empty one) * Returning mesh is depended on modifiers operation (sergey) */ - result = get_quick_mesh(ctx->object, mesh, bmd->object, mesh_other, bmd->operation); + result = get_quick_mesh(object_eval, mesh, other_eval, mesh_other, bmd->operation); if (result == NULL) { - const bool is_flip = (is_negative_m4(ctx->object->obmat) != is_negative_m4(bmd->object->obmat)); + const bool is_flip = (is_negative_m4(object_eval->obmat) != is_negative_m4(other_eval->obmat)); BMesh *bm; const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh, mesh_other); @@ -231,8 +234,8 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes float imat[4][4]; float omat[4][4]; - invert_m4_m4(imat, ctx->object->obmat); - mul_m4_m4m4(omat, imat, bmd->object->obmat); + invert_m4_m4(imat, object_eval->obmat); + mul_m4_m4m4(omat, imat, other_eval->obmat); BMVert *eve; i = 0; @@ -254,10 +257,11 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes negate_m3(nmat); } - const short ob_src_totcol = bmd->object->totcol; + const short ob_src_totcol = other_eval->totcol; short *material_remap = BLI_array_alloca(material_remap, ob_src_totcol ? ob_src_totcol : 1); - BKE_material_remap_object_calc(ctx->object, bmd->object, material_remap); + /* Using original (not evaluated) object here since we are writing to it. */ + BKE_material_remap_object_calc(ctx->object, other_eval, material_remap); BMFace *efa; i = 0; diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index 94adb3d9ebc..48653856178 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -275,7 +275,7 @@ static void meshdeform_vert_task( } static void meshdeformModifier_do( - ModifierData *md, Object *ob, Mesh *mesh, + ModifierData *md, Depsgraph *depsgraph, Object *ob, Mesh *mesh, float (*vertexCos)[3], int numVerts) { MeshDeformModifierData *mmd = (MeshDeformModifierData *) md; @@ -307,7 +307,11 @@ static void meshdeformModifier_do( free_cagemesh = true; } else { - cagemesh = BKE_modifier_get_evaluated_mesh_from_object(ob, md->mode & eModifierMode_Render ? MOD_APPLY_RENDER : 0); + ModifierEvalContext ctx = { + .depsgraph = depsgraph, + .flag = md->mode & eModifierMode_Render ? MOD_APPLY_RENDER : 0, + }; + cagemesh = BKE_modifier_get_evaluated_mesh_from_object(&ctx, ob); } /* if we don't have one computed, use derivedmesh from data @@ -421,7 +425,7 @@ static void deformVerts( modifier_vgroup_cache(md, vertexCos); /* if next modifier needs original vertices */ - meshdeformModifier_do(md, ctx->object, mesh_src, vertexCos, numVerts); + meshdeformModifier_do(md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, numVerts); if (mesh_src && mesh_src != mesh) { BKE_id_free(NULL, mesh_src); @@ -437,7 +441,7 @@ static void deformVertsEM( { Mesh *mesh_src = get_mesh(ctx->object, NULL, mesh, NULL, false, false); - meshdeformModifier_do(md, ctx->object, mesh_src, vertexCos, numVerts); + meshdeformModifier_do(md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, numVerts); if (mesh_src && mesh_src != mesh) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index c2493e6d8f3..72bdcc779ea 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -42,6 +42,7 @@ #include "BKE_cdderivedmesh.h" +#include "BKE_editmesh.h" #include "BKE_mesh.h" #include "BKE_library.h" #include "BKE_modifier.h" @@ -55,7 +56,7 @@ static void initData(ModifierData *md) ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md; psmd->psys = NULL; psmd->mesh_final = NULL; - psmd->mesh_deformed = NULL; + psmd->mesh_original = NULL; psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0; } static void freeData(ModifierData *md) @@ -65,9 +66,9 @@ static void freeData(ModifierData *md) if (psmd->mesh_final) { BKE_id_free(NULL, psmd->mesh_final); psmd->mesh_final = NULL; - if (psmd->mesh_deformed) { - BKE_id_free(NULL, psmd->mesh_deformed); - psmd->mesh_deformed = NULL; + if (psmd->mesh_original) { + BKE_id_free(NULL, psmd->mesh_original); + psmd->mesh_original = NULL; } } psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0; @@ -88,7 +89,7 @@ static void copyData(const ModifierData *md, ModifierData *target) modifier_copyData_generic(md, target); tpsmd->mesh_final = NULL; - tpsmd->mesh_deformed = NULL; + tpsmd->mesh_original = NULL; tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0; } @@ -129,9 +130,9 @@ static void deformVerts( if (psmd->mesh_final) { BKE_id_free(NULL, psmd->mesh_final); psmd->mesh_final = NULL; - if (psmd->mesh_deformed) { - BKE_id_free(NULL, psmd->mesh_deformed); - psmd->mesh_deformed = NULL; + if (psmd->mesh_original) { + BKE_id_free(NULL, psmd->mesh_original); + psmd->mesh_original = NULL; } } else if (psmd->flag & eParticleSystemFlag_file_loaded) { @@ -156,20 +157,40 @@ static void deformVerts( BKE_mesh_tessface_ensure(psmd->mesh_final); if (!psmd->mesh_final->runtime.deformed_only) { - /* XXX Think we can assume here that if current DM is not only-deformed, ob->deformedOnly has been set. - * This is awfully weak though. :| */ - if (ctx->object->derivedDeform) { - DM_to_mesh(ctx->object->derivedDeform, psmd->mesh_deformed, ctx->object, CD_MASK_EVERYTHING, false); + /* Get the original mesh from the object, this is what the particles + * are attached to so in case of non-deform modifiers we need to remap + * them to the final mesh (typically subdivision surfaces). */ + Mesh *mesh_original = NULL; + + if (ctx->object->type == OB_MESH) { + BMEditMesh *edit_btmesh = BKE_editmesh_from_object(ctx->object); + + if (edit_btmesh) { + /* In edit mode get directly from the edit mesh. */ + psmd->mesh_original = BKE_bmesh_to_mesh_nomain(edit_btmesh->bm, &(struct BMeshToMeshParams){0}); + } + else { + /* Otherwise get regular mesh. */ + mesh_original = ctx->object->data; + } } - else { /* Can happen in some cases, e.g. when rendering from Edit mode... */ - BKE_id_copy_ex(NULL, &mesh_src->id, (ID **)&psmd->mesh_deformed, + else { + mesh_original = mesh_src; + } + + if (mesh_original) { + /* Make a persistent copy of the mesh. We don't actually need + * all this data, just some topology for remapping. Could be + * optimized once. */ + BKE_id_copy_ex(NULL, &mesh_original->id, (ID **)&psmd->mesh_original, LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_DEG_TAG | LIB_ID_COPY_NO_PREVIEW, false); } - BKE_mesh_tessface_ensure(psmd->mesh_deformed); + + BKE_mesh_tessface_ensure(psmd->mesh_original); } if (mesh_src != psmd->mesh_final && mesh_src != mesh) { diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index ab0b31812b2..f03ae73e2bb 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -1041,7 +1041,7 @@ static bool surfacedeformBind( return data.success == 1; } -static Mesh *surfacedeform_get_mesh(SurfaceDeformModifierData *smd, bool *r_needsfree) +static Mesh *surfacedeform_get_mesh(Depsgraph *depsgraph, SurfaceDeformModifierData *smd, bool *r_needsfree) { Mesh *mesh; @@ -1052,8 +1052,11 @@ static Mesh *surfacedeform_get_mesh(SurfaceDeformModifierData *smd, bool *r_need *r_needsfree = true; } else { - mesh = BKE_modifier_get_evaluated_mesh_from_object( - smd->target, smd->modifier.mode & eModifierMode_Render ? MOD_APPLY_RENDER : 0); + ModifierEvalContext ctx = { + .depsgraph = depsgraph, + .flag = smd->modifier.mode & eModifierMode_Render ? MOD_APPLY_RENDER : 0, + }; + mesh = BKE_modifier_get_evaluated_mesh_from_object(&ctx, smd->target); *r_needsfree = false; } @@ -1124,6 +1127,7 @@ static void deformVert( static void surfacedeformModifier_do( ModifierData *md, + const ModifierEvalContext *ctx, float (*vertexCos)[3], unsigned int numverts, Object *ob) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; @@ -1137,7 +1141,7 @@ static void surfacedeformModifier_do( return; } - target = surfacedeform_get_mesh(smd, &free_target); + target = surfacedeform_get_mesh(ctx->depsgraph, smd, &free_target); if (!target) { modifier_setError(md, "No valid target mesh"); return; @@ -1204,7 +1208,7 @@ static void deformVerts( Mesh *UNUSED(mesh), float (*vertexCos)[3], int numVerts) { - surfacedeformModifier_do(md, vertexCos, numVerts, ctx->object); + surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object); } static void deformVertsEM( @@ -1213,7 +1217,7 @@ static void deformVertsEM( Mesh *UNUSED(mesh), float (*vertexCos)[3], int numVerts) { - surfacedeformModifier_do(md, vertexCos, numVerts, ctx->object); + surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object); } static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams)) diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 207c692071c..b491496caa4 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -55,7 +55,9 @@ #include "MEM_guardedalloc.h" +#include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" static void initData(ModifierData *md) { @@ -111,7 +113,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte } typedef struct Projector { - Object *ob; /* object this projector is derived from */ + Object *ob_eval; /* object this projector is derived from */ float projmat[4][4]; /* projection matrix */ float normal[3]; /* projector normal in world space */ void *uci; /* optional uv-project info (panorama projection) */ @@ -119,6 +121,7 @@ typedef struct Projector { static Mesh *uvprojectModifier_do( UVProjectModifierData *umd, + Depsgraph *depsgraph, Object *ob, Mesh *mesh) { float (*coords)[3], (*co)[3]; @@ -137,7 +140,7 @@ static Mesh *uvprojectModifier_do( for (i = 0; i < umd->num_projectors; ++i) if (umd->projectors[i]) - projectors[num_projectors++].ob = umd->projectors[i]; + projectors[num_projectors++].ob_eval = DEG_get_evaluated_object(depsgraph, umd->projectors[i]); if (num_projectors == 0) return mesh; @@ -154,15 +157,14 @@ static Mesh *uvprojectModifier_do( float offsetmat[4][4]; Camera *cam = NULL; /* calculate projection matrix */ - invert_m4_m4(projectors[i].projmat, projectors[i].ob->obmat); + invert_m4_m4(projectors[i].projmat, projectors[i].ob_eval->obmat); projectors[i].uci = NULL; - if (projectors[i].ob->type == OB_CAMERA) { - - cam = (Camera *)projectors[i].ob->data; + if (projectors[i].ob_eval->type == OB_CAMERA) { + cam = (Camera *)projectors[i].ob_eval->data; if (cam->type == CAM_PANO) { - projectors[i].uci = BLI_uvproject_camera_info(projectors[i].ob, NULL, aspx, aspy); + projectors[i].uci = BLI_uvproject_camera_info(projectors[i].ob_eval, NULL, aspx, aspy); BLI_uvproject_camera_info_scale(projectors[i].uci, scax, scay); free_uci = 1; } @@ -171,7 +173,7 @@ static Mesh *uvprojectModifier_do( /* setup parameters */ BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, projectors[i].ob); + BKE_camera_params_from_object(¶ms, projectors[i].ob_eval); /* compute matrix, viewplane, .. */ BKE_camera_params_compute_viewplane(¶ms, 1, 1, aspx, aspy); @@ -200,7 +202,7 @@ static Mesh *uvprojectModifier_do( projectors[i].normal[0] = 0; projectors[i].normal[1] = 0; projectors[i].normal[2] = 1; - mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal); + mul_mat3_m4_v3(projectors[i].ob_eval->obmat, projectors[i].normal); } numPolys = mesh->totpoly; @@ -312,7 +314,7 @@ static Mesh *applyModifier( Mesh *result; UVProjectModifierData *umd = (UVProjectModifierData *) md; - result = uvprojectModifier_do(umd, ctx->object, mesh); + result = uvprojectModifier_do(umd, ctx->depsgraph, ctx->object, mesh); return result; } diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 64133222c1e..9e77e0d3794 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -506,7 +506,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes const bool use_trgt_faces = (wmd->proximity_flags & MOD_WVG_PROXIMITY_GEOM_FACES) != 0; if (use_trgt_verts || use_trgt_edges || use_trgt_faces) { - Mesh *target_mesh = BKE_modifier_get_evaluated_mesh_from_object(obr, ctx->flag); + Mesh *target_mesh = BKE_modifier_get_evaluated_mesh_from_object(ctx, obr); /* We must check that we do have a valid target_mesh! */ if (target_mesh != NULL) { diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 5acd0a9fcea..67c86180188 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -173,6 +173,7 @@ set(SRC shader/nodes/node_shader_fresnel.c shader/nodes/node_shader_geometry.c shader/nodes/node_shader_holdout.c + shader/nodes/node_shader_ies_light.c shader/nodes/node_shader_layer_weight.c shader/nodes/node_shader_light_falloff.c shader/nodes/node_shader_light_path.c diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 3d6a8647628..158d20a5c19 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -136,6 +136,7 @@ void register_node_type_sh_tex_musgrave(void); void register_node_type_sh_tex_noise(void); void register_node_type_sh_tex_checker(void); void register_node_type_sh_bump(void); +void register_node_type_sh_tex_ies(void); #endif diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index efb8eb66737..437093a9cb3 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -126,6 +126,7 @@ DefNode( ShaderNode, SH_NODE_COMBXYZ, 0, "CO DefNode( ShaderNode, SH_NODE_BEVEL, def_sh_bevel, "BEVEL", Bevel, "Bevel", "" ) DefNode( ShaderNode, SH_NODE_DISPLACEMENT, def_sh_displacement, "DISPLACEMENT", Displacement, "Displacement", "" ) DefNode( ShaderNode, SH_NODE_VECTOR_DISPLACEMENT,def_sh_vector_displacement,"VECTOR_DISPLACEMENT",VectorDisplacement,"Vector Displacement","" ) +DefNode( ShaderNode, SH_NODE_TEX_IES, def_sh_tex_ies, "TEX_IES", TexIES, "IES Texture", "" ) DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" ) DefNode( CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" ) diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index be23c535cba..a1beadbdc03 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -306,6 +306,7 @@ static void node_composit_init_image(bNodeTree *ntree, bNode *node) iuser->sfra = 1; iuser->fie_ima = 2; iuser->ok = 1; + iuser->flag |= IMA_ANIM_ALWAYS; /* setup initial outputs */ cmp_node_image_verify_outputs(ntree, node, false); diff --git a/source/blender/nodes/shader/nodes/node_shader_ies_light.c b/source/blender/nodes/shader/nodes/node_shader_ies_light.c new file mode 100644 index 00000000000..8084f445e34 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_ies_light.c @@ -0,0 +1,61 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * The Original Code is Copyright (C) 2018 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +/* **************** IES Light ******************** */ + +static bNodeSocketTemplate sh_node_tex_ies_in[] = { + { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f, PROP_NONE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_tex_ies_out[] = { + { SOCK_FLOAT, 0, N_("Fac")}, + { -1, 0, "" } +}; + +static void node_shader_init_tex_ies(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeShaderTexIES *tex = MEM_callocN(sizeof(NodeShaderTexIES), "NodeShaderIESLight"); + node->storage = tex; +} + +/* node type definition */ +void register_node_type_sh_tex_ies(void) +{ + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_TEX_IES, "IES Texture", NODE_CLASS_TEXTURE, 0); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_tex_ies_in, sh_node_tex_ies_out); + node_type_init(&ntype, node_shader_init_tex_ies); + node_type_storage(&ntype, "NodeShaderTexIES", node_free_standard_storage, node_copy_standard_storage); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c index 6cd58d2fb85..f36310f4d00 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_math.c @@ -221,6 +221,11 @@ static void node_shader_exec_math(void *UNUSED(data), int UNUSED(thread), bNode r = fabsf(a); break; } + case NODE_MATH_ATAN2: + { + r = atan2(a, b); + break; + } } if (node->custom2 & SHD_MATH_CLAMP) { CLAMP(r, 0.0f, 1.0f); @@ -235,6 +240,7 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED( "math_divide", "math_sine", "math_cosine", "math_tangent", "math_asin", "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max", "math_round", "math_less_than", "math_greater_than", "math_modulo", "math_abs", + "math_atan2" }; switch (node->custom1) { @@ -249,6 +255,7 @@ static int gpu_shader_math(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED( case NODE_MATH_LESS: case NODE_MATH_GREATER: case NODE_MATH_MOD: + case NODE_MATH_ATAN2: GPU_stack_link(mat, node, names[node->custom1], in, out); break; case NODE_MATH_SIN: diff --git a/source/blender/nodes/texture/nodes/node_texture_image.c b/source/blender/nodes/texture/nodes/node_texture_image.c index 69c8f4b7262..fd1e818b63b 100644 --- a/source/blender/nodes/texture/nodes/node_texture_image.c +++ b/source/blender/nodes/texture/nodes/node_texture_image.c @@ -95,6 +95,7 @@ static void init(bNodeTree *UNUSED(ntree), bNode *node) iuser->sfra = 1; iuser->fie_ima = 2; iuser->ok = 1; + iuser->flag |= IMA_ANIM_ALWAYS; } void register_node_type_tex_image(void) diff --git a/source/blender/nodes/texture/nodes/node_texture_math.c b/source/blender/nodes/texture/nodes/node_texture_math.c index 19bc16fb82d..d8dc2a62625 100644 --- a/source/blender/nodes/texture/nodes/node_texture_math.c +++ b/source/blender/nodes/texture/nodes/node_texture_math.c @@ -189,6 +189,12 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor break; } + case NODE_MATH_ATAN2: + { + *out = atan2(in0, in1); + break; + } + default: { BLI_assert(0); diff --git a/source/blender/python/intern/stubs.c b/source/blender/python/intern/stubs.c index cc186be60ea..3b3a4d6d2fe 100644 --- a/source/blender/python/intern/stubs.c +++ b/source/blender/python/intern/stubs.c @@ -32,7 +32,7 @@ #include "BPY_extern.h" -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__clang__) # pragma GCC diagnostic error "-Wmissing-prototypes" # pragma GCC diagnostic ignored "-Wunused-parameter" #endif diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 4f3f8ece1f0..c800370a85d 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1958,14 +1958,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand /* remove modal handler, operator itself should have been canceled and freed */ if (retval & (OPERATOR_CANCELLED | OPERATOR_FINISHED)) { - /* set cursor back to the default for the region */ - wmWindow *win = CTX_wm_window(C); - WM_cursor_grab_disable(win, NULL); - /* Causes crash when joining areas: T55166, seems this is not even needed. */ -#if 0 - ED_region_cursor_set(win, area, region); -#endif - + WM_cursor_grab_disable(CTX_wm_window(C), NULL); BLI_remlink(handlers, handler); wm_event_free_handler(handler); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 9d26c7e92d5..f2387846fd2 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -1215,9 +1215,11 @@ static wmKeyMapItem *wm_keymap_item_find_props( /* look into multiple handler lists to find the item */ if (win) { - found = wm_keymap_item_find_handlers(C, &win->modalhandlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); + found = wm_keymap_item_find_handlers( + C, &win->modalhandlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); if (found == NULL) { - found = wm_keymap_item_find_handlers(C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); + found = wm_keymap_item_find_handlers( + C, &win->handlers, opname, opcontext, properties, is_strict, is_hotkey, r_keymap); } } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 1fe0799d6c1..7cf1fe3bdfa 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2248,7 +2248,7 @@ static int wm_call_panel_exec(bContext *C, wmOperator *op) const int space_type = RNA_enum_get(op->ptr, "space_type"); const int region_type = RNA_enum_get(op->ptr, "region_type"); - return UI_popover_panel_invoke(C, space_type, region_type, idname, op->reports); + return UI_popover_panel_invoke(C, space_type, region_type, idname, true, op->reports); } static void WM_OT_call_panel(wmOperatorType *ot) diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c index f5a8746f807..5634a1a3ee7 100644 --- a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c +++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c @@ -509,7 +509,7 @@ void wm_manipulator_calculate_scale(wmManipulator *mpr, const bContext *C) } /* Exclude matrix_offset from scale. */ - scale *= ED_view3d_pixel_size(rv3d, matrix_world[3]) / U.pixelsize; + scale *= ED_view3d_pixel_size_no_ui_scale(rv3d, matrix_world[3]); } else { scale *= 0.02f; |