diff options
author | YimingWu <xp8110@outlook.com> | 2019-05-16 04:48:45 +0300 |
---|---|---|
committer | YimingWu <xp8110@outlook.com> | 2019-05-16 04:48:45 +0300 |
commit | 54804117e89931a1e7bfa67b2aaf4fe237881ab6 (patch) | |
tree | 72f60f4ee18426243c986e973029508ab706569a /source/blender | |
parent | 2753611c4e2482885021416f1b2af46250fd09dd (diff) | |
parent | 2384564149b54374572ea28f91b5f64dc61143e2 (diff) |
Merge branch 'master' into soc-2018-npr
Diffstat (limited to 'source/blender')
462 files changed, 10791 insertions, 8243 deletions
diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc index 8b8ed6c5c4b..08f8eb8bd8f 100644 --- a/source/blender/alembic/intern/abc_transform.cc +++ b/source/blender/alembic/intern/abc_transform.cc @@ -86,7 +86,7 @@ void AbcTransformWriter::do_write() m_xform, m_xform.getSchema().getTimeSampling()); } - m_visibility.set(!(ob_eval->restrictflag & OB_RESTRICT_VIEW)); + m_visibility.set(!(ob_eval->restrictflag & OB_RESTRICT_VIEWPORT)); if (!m_first_frame && !m_is_animated) { return; diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h index 7ff8514f675..e956aeb769a 100644 --- a/source/blender/blenkernel/BKE_appdir.h +++ b/source/blender/blenkernel/BKE_appdir.h @@ -36,6 +36,7 @@ const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, con bool BKE_appdir_app_is_portable_install(void); bool BKE_appdir_app_template_any(void); bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len); +bool BKE_appdir_app_template_has_userpref(const char *app_template); void BKE_appdir_app_templates(struct ListBase *templates); /* Initialize path to program executable */ diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index b5da30e725d..6839e13ffe1 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -84,7 +84,9 @@ bool BKE_pose_minmax( int bone_autoside_name(char name[64], int strip_number, short axis, float head, float tail); struct Bone *BKE_armature_find_bone_name(struct bArmature *arm, const char *name); -struct GHash *BKE_armature_bone_from_name_map(struct bArmature *arm); + +void BKE_armature_bone_hash_make(struct bArmature *arm); +void BKE_armature_bone_hash_free(struct bArmature *arm); bool BKE_armature_bone_flag_test_recursive(const struct Bone *bone, int flag); diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index e01f6a6b751..a36ead4630e 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ * \note Use #STRINGIFY() rather than defining with quotes. */ #define BLENDER_VERSION 280 -#define BLENDER_SUBVERSION 60 +#define BLENDER_SUBVERSION 64 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h index 216bef0d1e3..76c05b0411a 100644 --- a/source/blender/blenkernel/BKE_blendfile.h +++ b/source/blender/blenkernel/BKE_blendfile.h @@ -62,6 +62,8 @@ struct UserDef *BKE_blendfile_userdef_read_from_memory(const void *filebuf, bool BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports); bool BKE_blendfile_userdef_write_app_template(const char *filepath, struct ReportList *reports); +bool BKE_blendfile_userdef_write_all(struct ReportList *reports); + struct WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath, const void *filebuf, int filelength, diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index 47786629aed..0e093bb086b 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -161,6 +161,8 @@ bool BKE_collection_move(struct Main *bmain, bool BKE_collection_find_cycle(struct Collection *new_ancestor, struct Collection *collection); +bool BKE_collection_has_collection(struct Collection *parent, struct Collection *collection); + /* Iteration callbacks. */ typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data); diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 4eaa0fbe057..4356d39be36 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -134,10 +134,6 @@ void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex); void BKE_curve_editNurb_free(struct Curve *cu); struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu); -float *BKE_curve_make_orco(struct Depsgraph *depsgraph, - struct Scene *scene, - struct Object *ob, - int *r_numVerts); float *BKE_curve_surf_make_orco(struct Object *ob); void BKE_curve_bevelList_free(struct ListBase *bev); @@ -147,7 +143,6 @@ void BKE_curve_bevel_make(struct Depsgraph *depsgraph, struct Object *ob, struct ListBase *disp, const bool for_render, - const bool use_render_resolution, struct LinkNode *ob_cyclic_list); void BKE_curve_forward_diff_bezier( @@ -212,9 +207,9 @@ void BKE_nurb_knot_calc_u(struct Nurb *nu); void BKE_nurb_knot_calc_v(struct Nurb *nu); /* nurb checks if they can be drawn, also clamp order func */ -bool BKE_nurb_check_valid_u(struct Nurb *nu); -bool BKE_nurb_check_valid_v(struct Nurb *nu); -bool BKE_nurb_check_valid_uv(struct Nurb *nu); +bool BKE_nurb_check_valid_u(const struct Nurb *nu); +bool BKE_nurb_check_valid_v(const struct Nurb *nu); +bool BKE_nurb_check_valid_uv(const struct Nurb *nu); bool BKE_nurb_order_clamp_u(struct Nurb *nu); bool BKE_nurb_order_clamp_v(struct Nurb *nu); diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index 9bf5a2f9971..db57df42d02 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -85,8 +85,7 @@ void BKE_displist_make_surf(struct Depsgraph *depsgraph, struct ListBase *dispbase, struct Mesh **r_final, const bool for_render, - const bool for_orco, - const bool use_render_resolution); + const bool for_orco); void BKE_displist_make_curveTypes(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, @@ -99,13 +98,7 @@ void BKE_displist_make_curveTypes_forRender(struct Depsgraph *depsgraph, struct ListBase *dispbase, struct Mesh **r_final, const bool for_orco, - const bool use_render_resolution, struct LinkNode *ob_cyclic_list); -void BKE_displist_make_curveTypes_forOrco(struct Depsgraph *depsgraph, - struct Scene *scene, - struct Object *ob, - struct ListBase *dispbase, - struct LinkNode *ob_cyclic_list); void BKE_displist_make_mball(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); void BKE_displist_make_mball_forRender(struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 2c19c1e2006..387e7f2182b 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -111,6 +111,7 @@ enum { G_FLAG_PICKSEL = (1 << 2), /** Support simulating events (for testing). */ G_FLAG_EVENT_SIMULATE = (1 << 3), + G_FLAG_USERPREF_NO_SAVE_ON_EXIT = (1 << 4), G_FLAG_SCRIPT_AUTOEXEC = (1 << 13), /** When this flag is set ignore the prefs #USER_SCRIPT_AUTOEXEC_DISABLE. */ @@ -121,7 +122,8 @@ enum { /** Don't overwrite these flags when reading a file. */ #define G_FLAG_ALL_RUNTIME \ - (G_FLAG_SCRIPT_AUTOEXEC | G_FLAG_SCRIPT_OVERRIDE_PREF | G_FLAG_EVENT_SIMULATE) + (G_FLAG_SCRIPT_AUTOEXEC | G_FLAG_SCRIPT_OVERRIDE_PREF | G_FLAG_EVENT_SIMULATE | \ + G_FLAG_USERPREF_NO_SAVE_ON_EXIT) /** Flags to read from blend file. */ #define G_FLAG_ALL_READFILE 0 diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 28886a5a195..d5304ec5434 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -340,12 +340,15 @@ void BKE_image_buf_fill_checker_color(unsigned char *rect, unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame); float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame); +/* Image modifications */ +bool BKE_image_is_dirty(struct Image *image); +void BKE_image_mark_dirty(struct Image *image, struct ImBuf *ibuf); + /* Guess offset for the first frame in the sequence */ int BKE_image_sequence_guess_offset(struct Image *image); bool BKE_image_has_anim(struct Image *image); bool BKE_image_has_packedfile(struct Image *image); bool BKE_image_is_animated(struct Image *image); -bool BKE_image_is_dirty(struct Image *image); void BKE_image_file_format_set(struct Image *image, int ftype, const struct ImbFormatOptions *options); diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 9d8b9218a79..37c502b3b0c 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -113,7 +113,7 @@ void free_matcopybuf(void); void copy_matcopybuf(struct Main *bmain, struct Material *ma); void paste_matcopybuf(struct Main *bmain, struct Material *ma); -/* Dependency graph evaluation. */ +/* Evaluation. */ struct Depsgraph; diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index ecee00b1b3f..b094dc5f400 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -671,11 +671,9 @@ void BKE_mesh_eval_geometry(struct Depsgraph *depsgraph, struct Mesh *mesh); /* Draw Cache */ enum { BKE_MESH_BATCH_DIRTY_ALL = 0, - BKE_MESH_BATCH_DIRTY_MAYBE_ALL, BKE_MESH_BATCH_DIRTY_SELECT, BKE_MESH_BATCH_DIRTY_SELECT_PAINT, BKE_MESH_BATCH_DIRTY_SHADING, - BKE_MESH_BATCH_DIRTY_SCULPT_COORDS, BKE_MESH_BATCH_DIRTY_UVEDIT_ALL, BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT, }; diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 9425f396bc5..43ee284a201 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -116,8 +116,7 @@ bool BKE_movieclip_put_frame_if_possible(struct MovieClip *clip, struct MovieClipUser *user, struct ImBuf *ibuf); -/* Dependency graph evaluation. */ - +/* Evaluation. */ void BKE_movieclip_eval_update(struct Depsgraph *depsgraph, struct MovieClip *clip); void BKE_movieclip_eval_selection_update(struct Depsgraph *depsgraph, struct MovieClip *clip); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 49b35bfccc1..c373fbfe478 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -100,6 +100,8 @@ bool BKE_object_is_mode_compat(const struct Object *ob, eObjectMode object_mode) bool BKE_object_data_is_in_editmode(const struct ID *id); +void BKE_object_update_select_id(struct Main *bmain); + typedef enum eObjectVisibilityResult { OB_VISIBLE_SELF = 1, OB_VISIBLE_PARTICLES = 2, diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 9b15462de6b..315c0224b11 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -34,13 +34,13 @@ struct CCGKey; struct CustomData; struct DMFlagMat; struct GPUBatch; +struct GPU_PBVH_Buffers; struct MLoop; struct MLoopTri; struct MPoly; struct MVert; struct PBVH; struct PBVHNode; -struct GPU_PBVH_Buffers; typedef struct PBVH PBVH; typedef struct PBVHNode PBVHNode; diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 3b5db883cf3..75ff5eace3c 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -240,14 +240,6 @@ void BKE_scene_cursor_quat_to_rot(struct View3DCursor *cursor, const float quat[4], bool use_compat); -/* Dependency graph evaluation. */ - -/* Evaluate parts of sequences which needs to be done as a part of a dependency graph evaluation. - * This does NOT include actual rendering of the strips, but rather makes them up-to-date for - * animation playback and makes them ready for the sequencer's rendering pipeline to render them. - */ -void BKE_scene_eval_sequencer_sequences(struct Depsgraph *depsgraph, struct Scene *scene); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index f526dd579ce..91e23d35f0e 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -32,7 +32,6 @@ struct Main; struct Sequence; struct bSound; -struct Depsgraph; typedef struct SoundWaveform { int length; @@ -72,17 +71,10 @@ void BKE_sound_cache(struct bSound *sound); void BKE_sound_delete_cache(struct bSound *sound); -void BKE_sound_reset_runtime(struct bSound *sound); void BKE_sound_load(struct Main *main, struct bSound *sound); -void BKE_sound_ensure_loaded(struct Main *bmain, struct bSound *sound); void BKE_sound_free(struct bSound *sound); -/* Is used by sequencer to temporarily load audio to access information about channels and - * duration. */ -void BKE_sound_load_audio(struct Main *main, struct bSound *sound); -void BKE_sound_free_audio(struct bSound *sound); - void BKE_sound_copy_data(struct Main *bmain, struct bSound *sound_dst, const struct bSound *sound_src, @@ -94,9 +86,7 @@ void BKE_sound_make_local(struct Main *bmain, struct bSound *sound, const bool l AUD_Device *BKE_sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume); #endif -void BKE_sound_reset_scene_runtime(struct Scene *scene); void BKE_sound_create_scene(struct Scene *scene); -void BKE_sound_ensure_scene(struct Scene *scene); void BKE_sound_destroy_scene(struct Scene *scene); @@ -144,10 +134,6 @@ void BKE_sound_stop_scene(struct Scene *scene); void BKE_sound_seek_scene(struct Main *bmain, struct Scene *scene); -/* Use this after original scene's frame has been changed. It will take care of doing all the - * updates required for BKE_sound_seek_scene(). */ -void BKE_sound_update_and_seek(struct Main *bmain, struct Depsgraph *depsgraph); - float BKE_sound_sync_scene(struct Scene *scene); int BKE_sound_scene_playing(struct Scene *scene); @@ -164,15 +150,4 @@ float BKE_sound_get_length(struct bSound *sound); char **BKE_sound_get_device_names(void); -typedef void (*SoundJackSyncCallback)(struct Main *bmain, int mode, float time); - -void BKE_sound_jack_sync_callback_set(SoundJackSyncCallback callback); -void BKE_sound_jack_scene_update(struct Scene *scene, int mode, float time); - -/* Dependency graph evaluation. */ - -struct Depsgraph; - -void BKE_sound_evaluate(struct Depsgraph *depsgraph, struct Main *bmain, struct bSound *sound); - #endif /* __BKE_SOUND_H__ */ diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h index 0a4ad4cd994..133cf2d6cf5 100644 --- a/source/blender/blenkernel/BKE_workspace.h +++ b/source/blender/blenkernel/BKE_workspace.h @@ -110,6 +110,8 @@ void BKE_workspace_hook_layout_for_workspace_set(struct WorkSpaceInstanceHook *h bool BKE_workspace_owner_id_check(const struct WorkSpace *workspace, const char *owner_id) ATTR_NONNULL(); +void BKE_workspace_id_tag_all_visible(struct Main *bmain, int tag) ATTR_NONNULL(); + #undef GETTER_ATTRS #undef SETTER_ATTRS diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h index 72817217a0a..3212bad75cb 100644 --- a/source/blender/blenkernel/BKE_writeavi.h +++ b/source/blender/blenkernel/BKE_writeavi.h @@ -53,9 +53,6 @@ typedef struct bMovieHandle { const char *suffix, struct ReportList *reports); void (*end_movie)(void *context_v); - int (*get_next_frame)(void *context_v, - struct RenderData *rd, - struct ReportList *reports); /* optional */ void (*get_movie_path)(char *string, struct RenderData *rd, bool preview, diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 9b321ff4e44..34c50865073 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -978,6 +978,7 @@ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_f } pchan->custom_scale = pchan_from->custom_scale; + pchan->drawflag = pchan_from->drawflag; } /* checks for IK constraint, Spline IK, and also for Follow-Path constraint. diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index cc5cd3b03ae..663eb4027f6 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1893,6 +1893,10 @@ static void animsys_evaluate_fcurves(Depsgraph *depsgraph, if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED))) { continue; } + /* Skip empty curves, as if muted. */ + if (fcu->totvert == 0) { + continue; + } PathResolvedRNA anim_rna; if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { const float curval = calculate_fcurve(&anim_rna, fcu, ctime); @@ -2005,7 +2009,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * /* calculate then execute each curve */ for (fcu = agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu = fcu->next) { /* check if this curve should be skipped */ - if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) { + if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0 && fcu->totvert != 0) { PathResolvedRNA anim_rna; if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { const float curval = calculate_fcurve(&anim_rna, fcu, ctime); @@ -3101,6 +3105,9 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr, if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) { continue; } + if (fcu->totvert == 0) { + continue; + } /* evaluate the F-Curve's value for the time given in the strip * NOTE: we use the modified time here, since strip's F-Curve Modifiers @@ -3327,6 +3334,9 @@ static void nla_eval_domain_action(PointerRNA *ptr, if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) { continue; } + if (fcu->totvert == 0) { + continue; + } NlaEvalChannel *nec = nlaevalchan_verify(ptr, channels, fcu->rna_path); diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 2b4123c74e2..c1ea57c5fcc 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -838,6 +838,26 @@ bool BKE_appdir_app_template_id_search(const char *app_template, char *path, siz return false; } +bool BKE_appdir_app_template_has_userpref(const char *app_template) +{ + /* Test if app template provides a userpref.blend. + * If not, we will share user preferences with the rest of Blender. */ + if (!app_template && app_template[0]) { + return false; + } + + char app_template_path[FILE_MAX]; + if (!BKE_appdir_app_template_id_search( + app_template, app_template_path, sizeof(app_template_path))) { + return false; + } + + char userpref_path[FILE_MAX]; + BLI_path_join( + userpref_path, sizeof(userpref_path), app_template_path, BLENDER_USERPREF_FILE, NULL); + return BLI_exists(userpref_path); +} + void BKE_appdir_app_templates(ListBase *templates) { BLI_listbase_clear(templates); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 60446bf60b6..bd9907acb24 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -125,6 +125,7 @@ void BKE_armature_free(bArmature *arm) { BKE_animdata_free(&arm->id, false); + BKE_armature_bone_hash_free(arm); BKE_armature_bonelist_free(&arm->bonebase); /* free editmode data */ @@ -169,25 +170,20 @@ static void copy_bonechildren(Bone *bone_dst, } } -static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst, GHash **bone_hash) +static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst) { Bone *bone_dst_child; - /* Lazily create the name -> bone hashtable. */ - if ((bone_dst->bbone_prev || bone_dst->bbone_next) && *bone_hash == NULL) { - *bone_hash = BKE_armature_bone_from_name_map(arm_dst); - } - if (bone_dst->bbone_prev) { - bone_dst->bbone_prev = BLI_ghash_lookup(*bone_hash, bone_dst->bbone_prev->name); + bone_dst->bbone_prev = BKE_armature_find_bone_name(arm_dst, bone_dst->bbone_prev->name); } if (bone_dst->bbone_next) { - bone_dst->bbone_next = BLI_ghash_lookup(*bone_hash, bone_dst->bbone_next->name); + bone_dst->bbone_next = BKE_armature_find_bone_name(arm_dst, bone_dst->bbone_next->name); } for (bone_dst_child = bone_dst->childbase.first; bone_dst_child; bone_dst_child = bone_dst_child->next) { - copy_bonechildren_custom_handles(bone_dst_child, arm_dst, bone_hash); + copy_bonechildren_custom_handles(bone_dst_child, arm_dst); } } @@ -212,6 +208,8 @@ void BKE_armature_copy_data(Main *UNUSED(bmain), /* We never handle usercount here for own data. */ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + arm_dst->bonehash = NULL; + BLI_duplicatelist(&arm_dst->bonebase, &arm_src->bonebase); /* Duplicate the childrens' lists */ @@ -224,15 +222,11 @@ void BKE_armature_copy_data(Main *UNUSED(bmain), arm_dst->act_bone = bone_dst_act; - /* Fix custom handle references. */ - GHash *bone_hash = NULL; /* lazily created */ + BKE_armature_bone_hash_make(arm_dst); + /* Fix custom handle references. */ for (bone_dst = arm_dst->bonebase.first; bone_dst; bone_dst = bone_dst->next) { - copy_bonechildren_custom_handles(bone_dst, arm_dst, &bone_hash); - } - - if (bone_hash) { - BLI_ghash_free(bone_hash, NULL, NULL); + copy_bonechildren_custom_handles(bone_dst, arm_dst); } arm_dst->edbo = NULL; @@ -274,6 +268,10 @@ Bone *BKE_armature_find_bone_name(bArmature *arm, const char *name) return NULL; } + if (arm->bonehash) { + return BLI_ghash_lookup(arm->bonehash, name); + } + return get_named_bone_bonechildren(&arm->bonebase, name); } @@ -291,7 +289,7 @@ static void armature_bone_from_name_insert_recursive(GHash *bone_hash, ListBase * \note typically #bPose.chanhash us used via #BKE_pose_channel_find_name * this is for the cases we can't use pose channels. */ -GHash *BKE_armature_bone_from_name_map(bArmature *arm) +static GHash *armature_bone_from_name_map(bArmature *arm) { const int bones_count = BKE_armature_bonelist_count(&arm->bonebase); GHash *bone_hash = BLI_ghash_str_new_ex(__func__, bones_count); @@ -299,6 +297,21 @@ GHash *BKE_armature_bone_from_name_map(bArmature *arm) return bone_hash; } +void BKE_armature_bone_hash_make(bArmature *arm) +{ + if (!arm->bonehash) { + arm->bonehash = armature_bone_from_name_map(arm); + } +} + +void BKE_armature_bone_hash_free(bArmature *arm) +{ + if (arm->bonehash) { + BLI_ghash_free(arm->bonehash, NULL, NULL); + arm->bonehash = NULL; + } +} + bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag) { if (bone->flag & flag) { @@ -2458,11 +2471,9 @@ void BKE_pose_clear_pointers(bPose *pose) void BKE_pose_remap_bone_pointers(bArmature *armature, bPose *pose) { - GHash *bone_hash = BKE_armature_bone_from_name_map(armature); for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - pchan->bone = BLI_ghash_lookup(bone_hash, pchan->name); + pchan->bone = BKE_armature_find_bone_name(armature, pchan->name); } - BLI_ghash_free(bone_hash, NULL, NULL); } /** Find the matching pose channel using the bone name, if not NULL. */ diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index c71c2dc86cf..bf7d81e5d63 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -273,11 +273,12 @@ static void splineik_evaluate_bone( /* first, adjust the point positions on the curve */ float curveLen = tree->points[index] - tree->points[index + 1]; float pointStart = state->curve_position; + float poseScale = len_v3v3(poseHead, poseTail) / pchan->bone->length; float baseScale = 1.0f; if (ikData->yScaleMode == CONSTRAINT_SPLINEIK_YS_ORIGINAL) { /* Carry over the bone Y scale to the curve range. */ - baseScale = len_v3v3(poseHead, poseTail) / pchan->bone->length; + baseScale = poseScale; } float pointEnd = pointStart + curveLen * baseScale * state->curve_scale; @@ -339,8 +340,8 @@ static void splineik_evaluate_bone( sub_v3_v3v3(splineVec, poseTail, poseHead); scaleFac = len_v3(splineVec) / pchan->bone->length; - /* Adjust the scale factor towards the neutral state when rolling off the curve end. */ - scaleFac = interpf(scaleFac, baseScale, tailBlendFac); + /* Extrapolate the full length of the bone as it rolls off the end of the curve. */ + scaleFac = (tailBlendFac < 1e-5f) ? baseScale : scaleFac / tailBlendFac; /* Step 3: compute the shortest rotation needed * to map from the bone rotation to the current axis. @@ -394,24 +395,31 @@ static void splineik_evaluate_bone( } /* step 4: set the scaling factors for the axes */ - { - /* only multiply the y-axis by the scaling factor to get nice volume-preservation */ - mul_v3_fl(poseMat[1], scaleFac); - /* set the scaling factors of the x and z axes from... */ - switch (ikData->xzScaleMode) { - case CONSTRAINT_SPLINEIK_XZS_ORIGINAL: { - /* original scales get used */ - float scale; + /* Always multiply the y-axis by the scaling factor to get the correct length. */ + mul_v3_fl(poseMat[1], scaleFac); + + /* After that, apply x/z scaling modes. */ + if (ikData->xzScaleMode != CONSTRAINT_SPLINEIK_XZS_NONE) { + /* First, apply the original scale if enabled. */ + if (ikData->xzScaleMode == CONSTRAINT_SPLINEIK_XZS_ORIGINAL || + (ikData->flag & CONSTRAINT_SPLINEIK_USE_ORIGINAL_SCALE) != 0) { + float scale; + + /* x-axis scale */ + scale = len_v3(pchan->pose_mat[0]); + mul_v3_fl(poseMat[0], scale); + /* z-axis scale */ + scale = len_v3(pchan->pose_mat[2]); + mul_v3_fl(poseMat[2], scale); + + /* Adjust the scale factor used for volume preservation + * to consider the pre-IK scaling as the initial volume. */ + scaleFac /= poseScale; + } - /* x-axis scale */ - scale = len_v3(pchan->pose_mat[0]); - mul_v3_fl(poseMat[0], scale); - /* z-axis scale */ - scale = len_v3(pchan->pose_mat[2]); - mul_v3_fl(poseMat[2], scale); - break; - } + /* Apply volume preservation. */ + switch (ikData->xzScaleMode) { case CONSTRAINT_SPLINEIK_XZS_INVERSE: { /* old 'volume preservation' method using the inverse scale */ float scale; @@ -483,14 +491,14 @@ static void splineik_evaluate_bone( break; } } + } - /* finally, multiply the x and z scaling by the radius of the curve too, - * to allow automatic scales to get tweaked still - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) { - mul_v3_fl(poseMat[0], radius); - mul_v3_fl(poseMat[2], radius); - } + /* Finally, multiply the x and z scaling by the radius of the curve too, + * to allow automatic scales to get tweaked still. + */ + if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) { + mul_v3_fl(poseMat[0], radius); + mul_v3_fl(poseMat[2], radius); } /* Blend the scaling of the matrix according to the influence. */ diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index d1a3045a829..570c1b9bd4c 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -98,6 +98,25 @@ static bool wm_scene_is_visible(wmWindowManager *wm, Scene *scene) return false; } +static void setup_app_userdef(BlendFileData *bfd) +{ + if (bfd->user) { + /* only here free userdef themes... */ + BKE_blender_userdef_data_set_and_free(bfd->user); + bfd->user = NULL; + + /* Security issue: any blend file could include a USER block. + * + * Currently we load prefs from BLENDER_STARTUP_FILE and later on load BLENDER_USERPREF_FILE, + * to load the preferences defined in the users home dir. + * + * This means we will never accidentally (or maliciously) + * enable scripts auto-execution by loading a '.blend' file. + */ + U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE; + } +} + /** * Context matching, handle no-ui case * @@ -235,26 +254,10 @@ static void setup_app_data(bContext *C, RNA_property_update_cache_free(); bmain = G_MAIN = bfd->main; + bfd->main = NULL; CTX_data_main_set(C, bmain); - if (bfd->user) { - - /* only here free userdef themes... */ - BKE_blender_userdef_data_set_and_free(bfd->user); - bfd->user = NULL; - - /* Security issue: any blend file could include a USER block. - * - * Currently we load prefs from BLENDER_STARTUP_FILE and later on load BLENDER_USERPREF_FILE, - * to load the preferences defined in the users home dir. - * - * This means we will never accidentally (or maliciously) - * enable scripts auto-execution by loading a '.blend' file. - */ - U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE; - } - /* case G_FILE_NO_UI or no screens in file */ if (mode != LOAD_UI) { /* leave entire context further unaltered? */ @@ -356,8 +359,20 @@ static void setup_app_data(bContext *C, /* TODO(sergey): Can this be also move above? */ RE_FreeAllPersistentData(); } +} - MEM_freeN(bfd); +static void setup_app_blend_file_data(bContext *C, + BlendFileData *bfd, + const char *filepath, + const struct BlendFileReadParams *params, + ReportList *reports) +{ + if ((params->skip_flags & BLO_READ_SKIP_USERDEF) == 0) { + setup_app_userdef(bfd); + } + if ((params->skip_flags & BLO_READ_SKIP_DATA) == 0) { + setup_app_data(C, bfd, filepath, params->is_startup, reports); + } } static int handle_subversion_warning(Main *main, ReportList *reports) @@ -400,7 +415,8 @@ int BKE_blendfile_read(bContext *C, retval = BKE_BLENDFILE_READ_FAIL; } else { - setup_app_data(C, bfd, filepath, params->is_startup, reports); + setup_app_blend_file_data(C, bfd, filepath, params, reports); + BLO_blendfiledata_free(bfd); } } else { @@ -422,9 +438,13 @@ bool BKE_blendfile_read_from_memory(bContext *C, bfd = BLO_read_from_memory(filebuf, filelength, params->skip_flags, reports); if (bfd) { if (update_defaults) { - BLO_update_defaults_startup_blend(bfd->main, NULL); + if ((params->skip_flags & BLO_READ_SKIP_DATA) == 0) { + BLO_update_defaults_startup_blend(bfd->main, NULL); + } } - setup_app_data(C, bfd, "<memory2>", params->is_startup, reports); + + setup_app_blend_file_data(C, bfd, "<memory2>", params, reports); + BLO_blendfiledata_free(bfd); } else { BKE_reports_prepend(reports, "Loading failed: "); @@ -453,7 +473,8 @@ bool BKE_blendfile_read_from_memfile(bContext *C, BKE_id_free(bfd->main, bfd->main->screens.first); } - setup_app_data(C, bfd, "<memory1>", params->is_startup, reports); + setup_app_blend_file_data(C, bfd, "<memory1>", params, reports); + BLO_blendfiledata_free(bfd); } else { BKE_reports_prepend(reports, "Loading failed: "); @@ -566,6 +587,63 @@ bool BKE_blendfile_userdef_write_app_template(const char *filepath, ReportList * return ok; } +bool BKE_blendfile_userdef_write_all(ReportList *reports) +{ + char filepath[FILE_MAX]; + const char *cfgdir; + bool ok = true; + const bool use_template_userpref = BKE_appdir_app_template_has_userpref(U.app_template); + + if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) { + bool ok_write; + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); + + printf("Writing userprefs: '%s' ", filepath); + if (use_template_userpref) { + ok_write = BKE_blendfile_userdef_write_app_template(filepath, reports); + } + else { + ok_write = BKE_blendfile_userdef_write(filepath, reports); + } + + if (ok_write) { + printf("ok\n"); + } + else { + printf("fail\n"); + ok = false; + } + } + else { + BKE_report(reports, RPT_ERROR, "Unable to create userpref path"); + } + + if (use_template_userpref) { + if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) { + /* Also save app-template prefs */ + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); + + printf("Writing userprefs app-template: '%s' ", filepath); + if (BKE_blendfile_userdef_write(filepath, reports) != 0) { + printf("ok\n"); + } + else { + printf("fail\n"); + ok = false; + } + } + else { + BKE_report(reports, RPT_ERROR, "Unable to create app-template userpref path"); + ok = false; + } + } + + if (ok) { + U.runtime.is_dirty = false; + } + return ok; +} + WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath, const void *filebuf, int filelength, diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index d33d4e344b5..87f448d8d57 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -434,8 +434,8 @@ static void collection_object_cache_fill(ListBase *lb, Collection *collection, i int object_restrict = base->object->restrictflag; - if (((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) && - ((object_restrict & OB_RESTRICT_VIEW) == 0)) { + if (((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) && + ((object_restrict & OB_RESTRICT_VIEWPORT) == 0)) { base->flag |= BASE_ENABLED_VIEWPORT; } @@ -966,6 +966,11 @@ static bool collection_find_child_recursive(Collection *parent, Collection *coll return false; } +bool BKE_collection_has_collection(Collection *parent, Collection *collection) +{ + return collection_find_child_recursive(parent, collection); +} + static CollectionParent *collection_find_parent(Collection *child, Collection *collection) { return BLI_findptr(&child->parents, collection, offsetof(CollectionParent, collection)); diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 0e29f165992..c680e15763d 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -1882,6 +1882,7 @@ static void sizelike_new_data(void *cdata) bSizeLikeConstraint *data = (bSizeLikeConstraint *)cdata; data->flag = SIZELIKE_X | SIZELIKE_Y | SIZELIKE_Z | SIZELIKE_MULTIPLY; + data->power = 1.0f; } static void sizelike_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) @@ -1929,6 +1930,10 @@ static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta mat4_to_size(size, ct->matrix); mat4_to_size(obsize, cob->matrix); + for (int i = 0; i < 3; i++) { + size[i] = powf(size[i], data->power); + } + if (data->flag & SIZELIKE_OFFSET) { /* Scale is a multiplicative quantity, so adding it makes no sense. * However, the additive mode has to stay for backward compatibility. */ @@ -2037,7 +2042,7 @@ static void samevolume_new_data(void *cdata) { bSameVolumeConstraint *data = (bSameVolumeConstraint *)cdata; - data->flag = SAMEVOL_Y; + data->free_axis = SAMEVOL_Y; data->volume = 1.0f; } @@ -2046,19 +2051,30 @@ static void samevolume_evaluate(bConstraint *con, bConstraintOb *cob, ListBase * bSameVolumeConstraint *data = con->data; float volume = data->volume; - float fac = 1.0f, total_scale; + float fac = 1.0f, total_scale = 1.0f; float obsize[3]; mat4_to_size(obsize, cob->matrix); /* calculate normalizing scale factor for non-essential values */ - total_scale = obsize[0] * obsize[1] * obsize[2]; + switch (data->mode) { + case SAMEVOL_STRICT: + total_scale = obsize[0] * obsize[1] * obsize[2]; + break; + case SAMEVOL_UNIFORM: + total_scale = pow3f(obsize[data->free_axis]); + break; + case SAMEVOL_SINGLE_AXIS: + total_scale = obsize[data->free_axis]; + break; + } + if (total_scale != 0) { fac = sqrtf(volume / total_scale); } /* apply scaling factor to the channels not being kept */ - switch (data->flag) { + switch (data->free_axis) { case SAMEVOL_X: mul_v3_fl(cob->matrix[1], fac); mul_v3_fl(cob->matrix[2], fac); @@ -2406,7 +2422,8 @@ static void armdef_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ copy_v3_v3(input_co, cob->matrix[3]); } - /* Process all targets. */ + /* Process all targets. This can't use ct->matrix, as armdef_get_tarmat is not + * called in solve for efficiency because the constraint needs bone data anyway. */ for (bConstraintTarget *ct = targets->first; ct; ct = ct->next) { if (ct->weight <= 0.0f) { continue; @@ -4224,6 +4241,7 @@ static void splineik_new_data(void *cdata) data->bulge_min = 1.0f; data->yScaleMode = CONSTRAINT_SPLINEIK_YS_FIT_CURVE; + data->flag = CONSTRAINT_SPLINEIK_USE_ORIGINAL_SCALE; } static void splineik_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) @@ -5600,6 +5618,11 @@ void BKE_constraint_targets_for_solving_get(struct Depsgraph *depsgraph, */ cti->get_constraint_targets(con, targets); + /* The Armature constraint doesn't need ct->matrix for evaluate at all. */ + if (ELEM(cti->type, CONSTRAINT_TYPE_ARMATURE)) { + return; + } + /* set matrices * - calculate if possible, otherwise just initialize as identity matrix */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index dc677449a4c..2775cf9691f 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1737,232 +1737,6 @@ static void forward_diff_bezier_cotangent(const float p0[3], } } -/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ - -float *BKE_curve_surf_make_orco(Object *ob) -{ - /* Note: this function is used in convertblender only atm, so - * suppose nonzero curve's render resolution should always be used */ - Curve *cu = ob->data; - Nurb *nu; - int a, b, tot = 0; - int sizeu, sizev; - int resolu, resolv; - float *fp, *coord_array; - - /* first calculate the size of the datablock */ - nu = cu->nurb.first; - while (nu) { - /* as we want to avoid the seam in a cyclic nurbs - * texture wrapping, reserve extra orco data space to save these extra needed - * vertex based UV coordinates for the meridian vertices. - * Vertices on the 0/2pi boundary are not duplicated inside the displist but later in - * the renderface/vert construction. - * - * See also convertblender.c: init_render_surf() - */ - - resolu = cu->resolu_ren ? cu->resolu_ren : nu->resolu; - resolv = cu->resolv_ren ? cu->resolv_ren : nu->resolv; - - sizeu = nu->pntsu * resolu; - sizev = nu->pntsv * resolv; - if (nu->flagu & CU_NURB_CYCLIC) { - sizeu++; - } - if (nu->flagv & CU_NURB_CYCLIC) { - sizev++; - } - if (nu->pntsv > 1) { - tot += sizeu * sizev; - } - - nu = nu->next; - } - /* makeNurbfaces wants zeros */ - fp = coord_array = MEM_calloc_arrayN(tot, 3 * sizeof(float), "make_orco"); - - nu = cu->nurb.first; - while (nu) { - resolu = cu->resolu_ren ? cu->resolu_ren : nu->resolu; - resolv = cu->resolv_ren ? cu->resolv_ren : nu->resolv; - - if (nu->pntsv > 1) { - sizeu = nu->pntsu * resolu; - sizev = nu->pntsv * resolv; - - if (nu->flagu & CU_NURB_CYCLIC) { - sizeu++; - } - if (nu->flagv & CU_NURB_CYCLIC) { - sizev++; - } - - if (cu->flag & CU_UV_ORCO) { - for (b = 0; b < sizeu; b++) { - for (a = 0; a < sizev; a++) { - - if (sizev < 2) { - fp[0] = 0.0f; - } - else { - fp[0] = -1.0f + 2.0f * ((float)a) / (sizev - 1); - } - - if (sizeu < 2) { - fp[1] = 0.0f; - } - else { - fp[1] = -1.0f + 2.0f * ((float)b) / (sizeu - 1); - } - - fp[2] = 0.0; - - fp += 3; - } - } - } - else { - int size = (nu->pntsu * resolu) * (nu->pntsv * resolv) * 3 * sizeof(float); - float *_tdata = MEM_mallocN(size, "temp data"); - float *tdata = _tdata; - - BKE_nurb_makeFaces(nu, tdata, 0, resolu, resolv); - - for (b = 0; b < sizeu; b++) { - int use_b = b; - if (b == sizeu - 1 && (nu->flagu & CU_NURB_CYCLIC)) { - use_b = false; - } - - for (a = 0; a < sizev; a++) { - int use_a = a; - if (a == sizev - 1 && (nu->flagv & CU_NURB_CYCLIC)) { - use_a = false; - } - - tdata = _tdata + 3 * (use_b * (nu->pntsv * resolv) + use_a); - - fp[0] = (tdata[0] - cu->loc[0]) / cu->size[0]; - fp[1] = (tdata[1] - cu->loc[1]) / cu->size[1]; - fp[2] = (tdata[2] - cu->loc[2]) / cu->size[2]; - fp += 3; - } - } - - MEM_freeN(_tdata); - } - } - nu = nu->next; - } - - return coord_array; -} - -/* NOTE: This routine is tied to the order of vertex - * built by displist and as passed to the renderer. - */ -float *BKE_curve_make_orco(Depsgraph *depsgraph, Scene *scene, Object *ob, int *r_numVerts) -{ - Curve *cu = ob->data; - DispList *dl; - int u, v, numVerts; - float *fp, *coord_array; - ListBase disp = {NULL, NULL}; - - BKE_displist_make_curveTypes_forOrco(depsgraph, scene, ob, &disp, NULL); - - numVerts = 0; - for (dl = disp.first; dl; dl = dl->next) { - if (dl->type == DL_INDEX3) { - numVerts += dl->nr; - } - else if (dl->type == DL_SURF) { - /* convertblender.c uses the Surface code for creating renderfaces when cyclic U only - * (closed circle beveling) - */ - if (dl->flag & DL_CYCL_U) { - if (dl->flag & DL_CYCL_V) { - numVerts += (dl->parts + 1) * (dl->nr + 1); - } - else { - numVerts += dl->parts * (dl->nr + 1); - } - } - else if (dl->flag & DL_CYCL_V) { - numVerts += (dl->parts + 1) * dl->nr; - } - else { - numVerts += dl->parts * dl->nr; - } - } - } - - if (r_numVerts) { - *r_numVerts = numVerts; - } - - fp = coord_array = MEM_malloc_arrayN(numVerts, 3 * sizeof(float), "cu_orco"); - for (dl = disp.first; dl; dl = dl->next) { - if (dl->type == DL_INDEX3) { - for (u = 0; u < dl->nr; u++, fp += 3) { - if (cu->flag & CU_UV_ORCO) { - fp[0] = 2.0f * u / (dl->nr - 1) - 1.0f; - fp[1] = 0.0; - fp[2] = 0.0; - } - else { - copy_v3_v3(fp, &dl->verts[u * 3]); - - fp[0] = (fp[0] - cu->loc[0]) / cu->size[0]; - fp[1] = (fp[1] - cu->loc[1]) / cu->size[1]; - fp[2] = (fp[2] - cu->loc[2]) / cu->size[2]; - } - } - } - else if (dl->type == DL_SURF) { - int sizeu = dl->nr, sizev = dl->parts; - - /* exception as handled in convertblender.c too */ - if (dl->flag & DL_CYCL_U) { - sizeu++; - if (dl->flag & DL_CYCL_V) { - sizev++; - } - } - else if (dl->flag & DL_CYCL_V) { - sizev++; - } - - for (u = 0; u < sizev; u++) { - for (v = 0; v < sizeu; v++, fp += 3) { - if (cu->flag & CU_UV_ORCO) { - fp[0] = 2.0f * u / (sizev - 1) - 1.0f; - fp[1] = 2.0f * v / (sizeu - 1) - 1.0f; - fp[2] = 0.0; - } - else { - const float *vert; - int realv = v % dl->nr; - int realu = u % dl->parts; - - vert = dl->verts + 3 * (dl->nr * realu + realv); - copy_v3_v3(fp, vert); - - fp[0] = (fp[0] - cu->loc[0]) / cu->size[0]; - fp[1] = (fp[1] - cu->loc[1]) / cu->size[1]; - fp[2] = (fp[2] - cu->loc[2]) / cu->size[2]; - } - } - } - } - } - - BKE_displist_free(&disp); - - return coord_array; -} - /* ***************** BEVEL ****************** */ void BKE_curve_bevel_make(Depsgraph *depsgraph, @@ -1970,7 +1744,6 @@ void BKE_curve_bevel_make(Depsgraph *depsgraph, Object *ob, ListBase *disp, const bool for_render, - const bool use_render_resolution, LinkNode *ob_cyclic_list) { DispList *dl, *dlnew; @@ -2003,7 +1776,6 @@ void BKE_curve_bevel_make(Depsgraph *depsgraph, &bevdisp, NULL, false, - use_render_resolution, &(LinkNode){ .link = ob, .next = ob_cyclic_list, @@ -4980,7 +4752,7 @@ void BKE_curve_nurbs_keyVertexTilts_apply(ListBase *lb, float *key) } } -bool BKE_nurb_check_valid_u(struct Nurb *nu) +bool BKE_nurb_check_valid_u(const Nurb *nu) { if (nu->pntsu <= 1) { return false; @@ -5007,7 +4779,7 @@ bool BKE_nurb_check_valid_u(struct Nurb *nu) } return true; } -bool BKE_nurb_check_valid_v(struct Nurb *nu) +bool BKE_nurb_check_valid_v(const Nurb *nu) { if (nu->pntsv <= 1) { return false; @@ -5035,7 +4807,7 @@ bool BKE_nurb_check_valid_v(struct Nurb *nu) return true; } -bool BKE_nurb_check_valid_uv(struct Nurb *nu) +bool BKE_nurb_check_valid_uv(const Nurb *nu) { if (!BKE_nurb_check_valid_u(nu)) { return false; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index c228595b6e8..cc1c73b1e68 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -315,8 +315,7 @@ bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, i static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, - const bool for_render, - const bool use_render_resolution) + const bool for_render) { Nurb *nu; DispList *dl; @@ -329,7 +328,7 @@ static void curve_to_displist(Curve *cu, nu = nubase->first; while (nu) { if (nu->hide == 0 || editmode == false) { - if (use_render_resolution && cu->resolu_ren != 0) { + if (for_render && cu->resolu_ren != 0) { resolu = cu->resolu_ren; } else { @@ -801,7 +800,7 @@ void BKE_displist_make_mball_forRender(Depsgraph *depsgraph, static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, - const bool use_render_resolution, + const bool for_render, const bool editmode) { VirtualModifierData virtualModifierData; @@ -809,7 +808,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, ModifierData *pretessellatePoint; int required_mode; - if (use_render_resolution) { + if (for_render) { required_mode = eModifierMode_Render; } else { @@ -848,12 +847,8 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, return pretessellatePoint; } -static void curve_calc_modifiers_pre(Depsgraph *depsgraph, - Scene *scene, - Object *ob, - ListBase *nurb, - const bool for_render, - const bool use_render_resolution) +static void curve_calc_modifiers_pre( + Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *nurb, const bool for_render) { VirtualModifierData virtualModifierData; ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); @@ -871,7 +866,7 @@ static void curve_calc_modifiers_pre(Depsgraph *depsgraph, if (editmode) { app_flag |= MOD_APPLY_USECACHE; } - if (use_render_resolution) { + if (for_render) { app_flag |= MOD_APPLY_RENDER; required_mode = eModifierMode_Render; } @@ -881,7 +876,7 @@ static void curve_calc_modifiers_pre(Depsgraph *depsgraph, const ModifierEvalContext mectx = {depsgraph, ob, app_flag}; - pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode); + pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode); if (editmode) { required_mode |= eModifierMode_Editmode; @@ -979,8 +974,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, ListBase *nurb, ListBase *dispbase, Mesh **r_final, - const bool for_render, - const bool use_render_resolution) + const bool for_render) { VirtualModifierData virtualModifierData; ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); @@ -993,7 +987,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, int useCache = !for_render; ModifierApplyFlag app_flag = 0; - if (use_render_resolution) { + if (for_render) { app_flag |= MOD_APPLY_RENDER; required_mode = eModifierMode_Render; } @@ -1006,7 +1000,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, const ModifierEvalContext mectx_apply = { depsgraph, ob, useCache ? app_flag | MOD_APPLY_USECACHE : app_flag}; - pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode); + pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode); if (editmode) { required_mode |= eModifierMode_Editmode; @@ -1199,144 +1193,13 @@ static void displist_surf_indices(DispList *dl) } } -/* XXX2.8(Sybren): unused function; impossible to test after porting to Mesh */ -#ifdef WITH_DERIVEDMESH_DEPRECATED_FUNCS -static DerivedMesh *create_orco_dm(Depsgraph *depsgraph, Scene *scene, Object *ob) -{ - DerivedMesh *dm; - ListBase disp = {NULL, NULL}; - - /* OrcoDM should be created from underformed disp lists */ - BKE_displist_make_curveTypes_forOrco(depsgraph, scene, ob, &disp); - dm = CDDM_from_curve_displist(ob, &disp); - - BKE_displist_free(&disp); - - return dm; -} - -static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm) -{ - float(*orco)[3], (*layerorco)[3]; - int totvert, a; - Curve *cu = ob->data; - - totvert = dm->getNumVerts(dm); - - orco = MEM_callocN(sizeof(float) * 3 * totvert, "dm orco"); - - if (orcodm->getNumVerts(orcodm) == totvert) { - orcodm->getVertCos(orcodm, orco); - } - else { - dm->getVertCos(dm, orco); - } - - for (a = 0; a < totvert; a++) { - float *co = orco[a]; - co[0] = (co[0] - cu->loc[0]) / cu->size[0]; - co[1] = (co[1] - cu->loc[1]) / cu->size[1]; - co[2] = (co[2] - cu->loc[2]) / cu->size[2]; - } - - if ((layerorco = DM_get_vert_data_layer(dm, CD_ORCO))) { - memcpy(layerorco, orco, sizeof(float) * totvert); - MEM_freeN(orco); - } - else { - DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco); - } -} -#endif - -/* XXX2.8(Sybren): unused function; impossible to test after porting to Mesh */ -#ifdef WITH_DERIVEDMESH_DEPRECATED_FUNCS -static void curve_calc_orcodm(Depsgraph *depsgraph, - Scene *scene, - Object *ob, - DerivedMesh *dm_final, - const bool for_render, - const bool use_render_resolution) -{ - /* this function represents logic of mesh's orcodm calculation - * for displist-based objects - */ - VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); - ModifierData *pretessellatePoint; - Curve *cu = ob->data; - int required_mode; - const bool editmode = (!for_render && (cu->editnurb || cu->editfont)); - DerivedMesh *ndm, *orcodm = NULL; - ModifierApplyFlag app_flag = MOD_APPLY_ORCO; - - if (use_render_resolution) { - app_flag |= MOD_APPLY_RENDER; - required_mode = eModifierMode_Render; - } - else { - required_mode = eModifierMode_Realtime; - } - - const ModifierEvalContext mectx = {depsgraph, ob, app_flag}; - - pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode); - - if (editmode) { - required_mode |= eModifierMode_Editmode; - } - - if (pretessellatePoint) { - md = pretessellatePoint->next; - } - - /* If modifiers are disabled, we wouldn't be here because - * this function is only called if there're enabled constructive - * modifiers applied on the curve. - * - * This means we can create ORCO DM in advance and assume it's - * never NULL. - */ - orcodm = create_orco_dm(depsgraph, scene, ob); - - for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - - md->scene = scene; - - if (!modifier_isEnabled(scene, md, required_mode)) { - continue; - } - if (mti->type != eModifierTypeType_Constructive) { - continue; - } - - ndm = modwrap_applyModifier(md, &mectx, orcodm); - - if (ndm) { - /* if the modifier returned a new dm, release the old one */ - if (orcodm && orcodm != ndm) { - orcodm->release(orcodm); - } - orcodm = ndm; - } - } - - /* add an orco layer if needed */ - add_orco_dm(ob, dm_final, orcodm); - - orcodm->release(orcodm); -} -#endif - void BKE_displist_make_surf(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase, Mesh **r_final, const bool for_render, - const bool for_orco, - const bool use_render_resolution) + const bool for_orco) { ListBase nubase = {NULL, NULL}; Nurb *nu; @@ -1353,14 +1216,14 @@ void BKE_displist_make_surf(Depsgraph *depsgraph, } if (!for_orco) { - curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render, use_render_resolution); + curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render); } for (nu = nubase.first; nu; nu = nu->next) { if ((for_render || nu->hide == 0) && BKE_nurb_check_valid_uv(nu)) { int resolu = nu->resolu, resolv = nu->resolv; - if (use_render_resolution) { + if (for_render) { if (cu->resolu_ren) { resolu = cu->resolu_ren; } @@ -1431,8 +1294,7 @@ void BKE_displist_make_surf(Depsgraph *depsgraph, if (!for_orco) { BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase); - curve_calc_modifiers_post( - depsgraph, scene, ob, &nubase, dispbase, r_final, for_render, use_render_resolution); + curve_calc_modifiers_post(depsgraph, scene, ob, &nubase, dispbase, r_final, for_render); } BKE_nurbList_free(&nubase); @@ -1665,7 +1527,6 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph, ListBase *dispbase, const bool for_render, const bool for_orco, - const bool use_render_resolution, LinkNode *ob_cyclic_list, Mesh **r_final) { @@ -1677,8 +1538,7 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph, } if (ob->type == OB_SURF) { - BKE_displist_make_surf( - depsgraph, scene, ob, dispbase, r_final, for_render, for_orco, use_render_resolution); + BKE_displist_make_surf(depsgraph, scene, ob, dispbase, r_final, for_render, for_orco); } else if (ELEM(ob->type, OB_CURVE, OB_FONT)) { ListBase dlbev; @@ -1705,18 +1565,17 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph, } if (!for_orco) { - curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render, use_render_resolution); + curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render); } - BKE_curve_bevelList_make(ob, &nubase, use_render_resolution); + BKE_curve_bevelList_make(ob, &nubase, for_render); /* If curve has no bevel will return nothing */ - BKE_curve_bevel_make( - depsgraph, scene, ob, &dlbev, for_render, use_render_resolution, ob_cyclic_list); + BKE_curve_bevel_make(depsgraph, scene, ob, &dlbev, for_render, ob_cyclic_list); /* no bevel or extrude, and no width correction? */ if (!dlbev.first && cu->width == 1.0f) { - curve_to_displist(cu, &nubase, dispbase, for_render, use_render_resolution); + curve_to_displist(cu, &nubase, dispbase, for_render); } else { float widfac = cu->width - 1.0f; @@ -1916,8 +1775,7 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph, if (!for_orco) { BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase); - curve_calc_modifiers_post( - depsgraph, scene, ob, &nubase, dispbase, r_final, for_render, use_render_resolution); + curve_calc_modifiers_post(depsgraph, scene, ob, &nubase, dispbase, r_final, for_render); } if (cu->flag & CU_DEFORM_FILL && !ob->runtime.mesh_eval) { @@ -1958,7 +1816,6 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph, dispbase, for_render, for_orco, - false, ob_cyclic_list, &ob->runtime.mesh_eval); @@ -1971,32 +1828,14 @@ void BKE_displist_make_curveTypes_forRender(Depsgraph *depsgraph, ListBase *dispbase, Mesh **r_final, const bool for_orco, - const bool use_render_resolution, LinkNode *ob_cyclic_list) { if (ob->runtime.curve_cache == NULL) { ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve"); } - do_makeDispListCurveTypes(depsgraph, - scene, - ob, - dispbase, - true, - for_orco, - use_render_resolution, - ob_cyclic_list, - r_final); -} - -void BKE_displist_make_curveTypes_forOrco( - Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase, LinkNode *ob_cyclic_list) -{ - if (ob->runtime.curve_cache == NULL) { - ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve"); - } - - do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, 1, 1, 1, ob_cyclic_list, NULL); + do_makeDispListCurveTypes( + depsgraph, scene, ob, dispbase, true, for_orco, ob_cyclic_list, r_final); } void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3]) diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 93b6fd34a8f..b5242d00ee0 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -2066,7 +2066,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object * } if (update_normals) { - // result->dirty |= DM_DIRTY_NORMALS; + result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } } /* make a copy of mesh to use as brush data */ diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 8c95e4c7ff3..e2d0a479792 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1707,6 +1707,11 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) /* not valid channel */ return 0.0f; } + else if (dtar->transChan == DTAR_TRANSCHAN_SCALE_AVG) { + /* Cubic root of the change in volume, equal to the geometric mean + * of scale over all three axes unless the matrix includes shear. */ + return cbrtf(mat4_to_volume_scale(mat)); + } else if (dtar->transChan >= DTAR_TRANSCHAN_SCALEX) { /* Extract scale, and choose the right axis, * inline 'mat4_to_size'. */ diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index f23c58befdf..18c42da0bd4 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -5087,6 +5087,7 @@ bool BKE_image_is_animated(Image *image) return ELEM(image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE); } +/* Image modifications */ bool BKE_image_is_dirty(Image *image) { bool is_dirty = false; @@ -5110,6 +5111,11 @@ bool BKE_image_is_dirty(Image *image) return is_dirty; } +void BKE_image_mark_dirty(Image *UNUSED(image), ImBuf *ibuf) +{ + ibuf->userflags |= IB_BITMAPDIRTY; +} + void BKE_image_file_format_set(Image *image, int ftype, const ImbFormatOptions *options) { BLI_spin_lock(&image_spin); diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index fc349e62809..99e6c99ec0c 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -693,8 +693,8 @@ static short layer_collection_sync(ViewLayer *view_layer, lc->runtime_flag = child_runtime_flag; } - if (((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) && - ((child_layer_restrict & LAYER_COLLECTION_RESTRICT_VIEW) == 0)) { + if (((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) && + ((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0)) { lc->runtime_flag |= LAYER_COLLECTION_VISIBLE; } @@ -723,9 +723,9 @@ static short layer_collection_sync(ViewLayer *view_layer, BLI_addtail(new_object_bases, base); } - if ((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) { + if ((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) { base->flag_from_collection |= BASE_ENABLED_VIEWPORT; - if ((child_layer_restrict & LAYER_COLLECTION_RESTRICT_VIEW) == 0) { + if ((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0) { base->flag_from_collection |= BASE_VISIBLE; if (((child_restrict & COLLECTION_RESTRICT_SELECT) == 0)) { base->flag_from_collection |= BASE_SELECTABLE; @@ -1014,8 +1014,8 @@ bool BKE_layer_collection_isolate(Scene *scene, bool hide_it = extend && (lc->runtime_flag & LAYER_COLLECTION_VISIBLE); if ((!ID_IS_LINKED(lc->collection) && !hide_it)) { - if (lc->collection->flag & COLLECTION_RESTRICT_VIEW) { - lc->collection->flag &= ~COLLECTION_RESTRICT_VIEW; + if (lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) { + lc->collection->flag &= ~COLLECTION_RESTRICT_VIEWPORT; depsgraph_need_update = true; } } @@ -1024,13 +1024,13 @@ bool BKE_layer_collection_isolate(Scene *scene, /* Hide all collections . */ for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter; lc_iter = lc_iter->next) { - layer_collection_flag_set_recursive(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW); + layer_collection_flag_set_recursive(lc_iter, LAYER_COLLECTION_HIDE); } } /* Make all the direct parents visible. */ if (hide_it) { - lc->flag |= LAYER_COLLECTION_RESTRICT_VIEW; + lc->flag |= LAYER_COLLECTION_HIDE; } else { LayerCollection *lc_parent = lc; @@ -1044,13 +1044,13 @@ bool BKE_layer_collection_isolate(Scene *scene, while (lc_parent != lc) { if (!ID_IS_LINKED(lc_parent->collection)) { - if (lc_parent->collection->flag & COLLECTION_RESTRICT_VIEW) { - lc_parent->collection->flag &= ~COLLECTION_RESTRICT_VIEW; + if (lc_parent->collection->flag & COLLECTION_RESTRICT_VIEWPORT) { + lc_parent->collection->flag &= ~COLLECTION_RESTRICT_VIEWPORT; depsgraph_need_update = true; } } - lc_parent->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW; + lc_parent->flag &= ~LAYER_COLLECTION_HIDE; for (LayerCollection *lc_iter = lc_parent->layer_collections.first; lc_iter; lc_iter = lc_iter->next) { @@ -1062,7 +1062,7 @@ bool BKE_layer_collection_isolate(Scene *scene, } /* Make all the children visible, but respect their disable state. */ - layer_collection_flag_unset_recursive(lc, LAYER_COLLECTION_RESTRICT_VIEW); + layer_collection_flag_unset_recursive(lc, LAYER_COLLECTION_HIDE); BKE_layer_collection_activate(view_layer, lc); } @@ -1109,27 +1109,27 @@ bool BKE_layer_collection_set_visible(ViewLayer *view_layer, bool depsgraph_changed = false; if (visible && (!ID_IS_LINKED(lc->collection)) && - ((lc->collection->flag & COLLECTION_RESTRICT_VIEW) != 0)) { - lc->collection->flag &= ~COLLECTION_RESTRICT_VIEW; + ((lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) != 0)) { + lc->collection->flag &= ~COLLECTION_RESTRICT_VIEWPORT; depsgraph_changed = true; } if (hierarchy) { if (visible) { - layer_collection_flag_unset_recursive(lc, LAYER_COLLECTION_RESTRICT_VIEW); + layer_collection_flag_unset_recursive(lc, LAYER_COLLECTION_HIDE); layer_collection_bases_show_recursive(view_layer, lc); } else { - layer_collection_flag_set_recursive(lc, LAYER_COLLECTION_RESTRICT_VIEW); + layer_collection_flag_set_recursive(lc, LAYER_COLLECTION_HIDE); layer_collection_bases_hide_recursive(view_layer, lc); } } else { if (visible) { - lc->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW; + lc->flag &= ~LAYER_COLLECTION_HIDE; } else { - lc->flag |= LAYER_COLLECTION_RESTRICT_VIEW; + lc->flag |= LAYER_COLLECTION_HIDE; } } return depsgraph_changed; @@ -1491,7 +1491,7 @@ void BKE_base_eval_flags(Base *base) /* Apply object restrictions. */ const int object_restrict = base->object->restrictflag; - if (object_restrict & OB_RESTRICT_VIEW) { + if (object_restrict & OB_RESTRICT_VIEWPORT) { base->flag &= ~BASE_ENABLED_VIEWPORT; } if (object_restrict & OB_RESTRICT_RENDER) { diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index ad0c405ab28..3e6f93d1323 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -1860,7 +1860,7 @@ static void library_make_local_copying_check(ID *id, * (except group and objects ones). */ /* Note: Old (2.77) version was simply making (tagging) data-blocks as local, - * without actually making any check whether * they were also indirectly used or not... + * without actually making any check whether they were also indirectly used or not... * * Current version uses regular id_make_local callback, with advanced pre-processing step to detect * all cases of IDs currently indirectly used, but which will be used by local data only once this diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c index 05b2eb82daf..1c3acb6a73a 100644 --- a/source/blender/blenkernel/intern/light.c +++ b/source/blender/blenkernel/intern/light.c @@ -80,6 +80,7 @@ void BKE_light_init(Light *la) la->contact_thickness = 0.2f; la->spec_fac = 1.0f; la->att_dist = 40.0f; + la->sun_angle = DEG2RADF(0.526f); curvemapping_initialize(la->curfalloff); } diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 3f4e504867c..fe8d053c1df 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -1007,7 +1007,7 @@ Mesh *BKE_mesh_new_from_object(Depsgraph *depsgraph, /* get updated display list, and convert to a mesh */ BKE_displist_make_curveTypes_forRender( - depsgraph, sce, tmpobj, &dispbase, &me_eval_final, false, render, NULL); + depsgraph, sce, tmpobj, &dispbase, &me_eval_final, false, NULL); copycu->editfont = NULL; copycu->editnurb = NULL; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 38a8ad2769a..6c2bd5e6127 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -4487,3 +4487,14 @@ void BKE_object_type_set_empty_for_versioning(Object *ob) } ob->mode = OB_MODE_OBJECT; } + +/* Updates select_id of all objects in the given bmain. */ +void BKE_object_update_select_id(struct Main *bmain) +{ + Object *ob = bmain->objects.first; + int select_id = 1; + while (ob) { + ob->runtime.select_id = select_id++; + ob = ob->id.next; + } +}
\ No newline at end of file diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 8080834a53a..0dedbb7e934 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -1082,7 +1082,7 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx) /* Should the dupli's be generated for this object? - Respect restrict flags */ if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER ? (restrictflag & OB_RESTRICT_RENDER) : - (restrictflag & OB_RESTRICT_VIEW)) { + (restrictflag & OB_RESTRICT_VIEWPORT)) { return NULL; } diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 183bc968897..77941e7d607 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -202,9 +202,11 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o case OB_CURVE: case OB_SURF: - case OB_FONT: - BKE_displist_make_curveTypes(depsgraph, scene, ob, false, false, NULL); + case OB_FONT: { + bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + BKE_displist_make_curveTypes(depsgraph, scene, ob, for_render, false, NULL); break; + } case OB_LATTICE: BKE_lattice_modifiers_calc(depsgraph, scene, ob); diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index b594232193d..bd06e2fe7e0 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -1276,9 +1276,6 @@ void BKE_sculpt_update_mesh_elements( } } } - - /* 2.8x - avoid full mesh update! */ - BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_SCULPT_COORDS); } int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 8a70db8704f..3d6b7390057 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -37,7 +37,6 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_sequence_types.h" -#include "DNA_sound_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" @@ -309,7 +308,8 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons flag_subdata); } - BKE_sound_reset_scene_runtime(sce_dst); + /* before scene copy */ + BKE_sound_create_scene(sce_dst); /* Copy sequencer, this is local data! */ if (sce_src->ed) { @@ -399,7 +399,8 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) sce_copy->r.ffcodecdata.properties = IDP_CopyProperty(sce->r.ffcodecdata.properties); } - BKE_sound_reset_scene_runtime(sce_copy); + /* before scene copy */ + BKE_sound_create_scene(sce_copy); /* grease pencil */ sce_copy->gpd = NULL; @@ -779,7 +780,7 @@ void BKE_scene_init(Scene *sce) srv = sce->r.views.last; BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix)); - BKE_sound_reset_scene_runtime(sce); + BKE_sound_create_scene(sce); /* color management */ colorspace_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_SEQUENCER); @@ -1530,13 +1531,6 @@ static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_ } } -static void scene_update_sound(Depsgraph *depsgraph, Main *bmain) -{ - Scene *scene = DEG_get_evaluated_scene(depsgraph); - BKE_sound_ensure_scene(scene); - BKE_sound_update_scene(bmain, scene); -} - /* TODO(sergey): This actually should become view_layer_graph or so. * Same applies to update_for_newframe. */ @@ -1565,9 +1559,10 @@ void BKE_scene_graph_update_tagged(Depsgraph *depsgraph, Main *bmain) * by depgraph or manual, no layer check here, gets correct flushed. */ DEG_evaluate_on_refresh(depsgraph); - /* Update sound system. */ - scene_update_sound(depsgraph, bmain); - /* Notify python about depsgraph update. */ + /* Update sound system animation (TODO, move to depsgraph). */ + BKE_sound_update_scene(bmain, scene); + + /* Notify python about depsgraph update */ if (run_callbacks) { BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_DEPSGRAPH_UPDATE_POST); } @@ -1602,8 +1597,8 @@ void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph, Main *bmain) * by depgraph or manual, no layer check here, gets correct flushed. */ DEG_evaluate_on_framechange(bmain, depsgraph, ctime); - /* Update sound system animation. */ - scene_update_sound(depsgraph, bmain); + /* Update sound system animation (TODO, move to depsgraph). */ + BKE_sound_update_scene(bmain, scene); /* Notify editors and python about recalc. */ BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_FRAME_CHANGE_POST); /* Inform editors about possible changes. */ @@ -2415,23 +2410,3 @@ void BKE_scene_cursor_quat_to_rot(View3DCursor *cursor, const float quat[4], boo } /** \} */ - -/* Dependency graph evaluation. */ - -void BKE_scene_eval_sequencer_sequences(Depsgraph *depsgraph, Scene *scene) -{ - DEG_debug_print_eval(depsgraph, __func__, scene->id.name, scene); - if (scene->ed == NULL) { - return; - } - BKE_sound_ensure_scene(scene); - Sequence *seq; - SEQ_BEGIN (scene->ed, seq) { - if (seq->sound != NULL && seq->scene_sound == NULL) { - seq->scene_sound = BKE_sound_add_scene_sound_defaults(scene, seq); - } - } - SEQ_END; - BKE_sequencer_update_muting(scene->ed); - BKE_sequencer_update_sound_bounds_all(scene); -} diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 9799f7c2943..5c41048be83 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -193,18 +193,6 @@ static void panel_list_copy(ListBase *newlb, const ListBase *lb) Panel *pa = lb->first; for (; newpa; newpa = newpa->next, pa = pa->next) { newpa->activedata = NULL; - - Panel *newpatab = newlb->first; - Panel *patab = lb->first; - while (newpatab) { - if (newpa->paneltab == patab) { - newpa->paneltab = newpatab; - break; - } - newpatab = newpatab->next; - patab = patab->next; - } - panel_list_copy(&newpa->children, &pa->children); } } @@ -859,6 +847,7 @@ void BKE_screen_view3d_shading_init(View3DShading *shading) shading->xray_alpha_wire = 0.5f; shading->cavity_valley_factor = 1.0f; shading->cavity_ridge_factor = 1.0f; + shading->cavity_type = V3D_SHADING_CAVITY_CURVATURE; shading->curvature_ridge_factor = 1.0f; shading->curvature_valley_factor = 1.0f; copy_v3_fl(shading->single_color, 0.8f); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 74541c13c4f..7f738ff4e4f 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -808,7 +808,10 @@ void BKE_sequence_calc_disp(Scene *scene, Sequence *seq) seq->handsize = (float)((seq->enddisp - seq->startdisp) / 25); } - if (seq->type == SEQ_TYPE_META) { + if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { + BKE_sequencer_update_sound_bounds(scene, seq); + } + else if (seq->type == SEQ_TYPE_META) { seq_update_sound_bounds_recursive(scene, seq); } } @@ -3572,9 +3575,9 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, re = RE_NewSceneRender(scene); } - RE_BlenderFrame(re, context->bmain, scene, view_layer, camera, frame, false); + RE_RenderFrame(re, context->bmain, scene, view_layer, camera, frame, false); - /* restore previous state after it was toggled on & off by RE_BlenderFrame */ + /* restore previous state after it was toggled on & off by RE_RenderFrame */ G.is_rendering = is_rendering; } @@ -5488,18 +5491,17 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad Strip *strip; StripElem *se; + AUD_SoundInfo info; + sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */ - /* Load the original sound, so we can access number of channels and length information. - * We free the sound handle on the original bSound datablock before existing this function, it is - * to be allocated on an evaluated version after this. */ - BKE_sound_load_audio(bmain, sound); - AUD_SoundInfo info = AUD_getInfo(sound->playback_handle); if (sound->playback_handle == NULL) { BKE_id_free(bmain, sound); return NULL; } + info = AUD_getInfo(sound->playback_handle); + if (info.specs.channels == AUD_CHANNELS_INVALID) { BKE_id_free(bmain, sound); return NULL; @@ -5524,7 +5526,8 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad BLI_split_dirfile(seq_load->path, strip->dir, se->name, sizeof(strip->dir), sizeof(se->name)); - seq->scene_sound = NULL; + seq->scene_sound = BKE_sound_add_scene_sound( + scene, seq, seq_load->start_frame, seq_load->start_frame + seq->len, 0); BKE_sequence_calc_disp(scene, seq); @@ -5533,11 +5536,6 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad seq_load_apply(bmain, scene, seq, seq_load); - BKE_sound_free_audio(sound); - - /* TODO(sergey): Shall we tag here or in the oeprator? */ - DEG_relations_tag_update(bmain); - return seq; } #else // WITH_AUDASPACE @@ -5749,7 +5747,10 @@ static Sequence *seq_dupli(const Scene *scene_src, } else if (seq->type == SEQ_TYPE_SOUND_RAM) { seqn->strip->stripdata = MEM_dupallocN(seq->strip->stripdata); - seqn->scene_sound = NULL; + if (seq->scene_sound) { + seqn->scene_sound = BKE_sound_add_scene_sound_defaults(scene_dst, seqn); + } + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { id_us_plus((ID *)seqn->sound); } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 9ccb90b5cdc..c97baf8f7dd 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -38,7 +38,6 @@ #include "DNA_screen_types.h" #include "DNA_sound_types.h" #include "DNA_speaker_types.h" -#include "DNA_windowmanager_types.h" #ifdef WITH_AUDASPACE # include <AUD_Sound.h> @@ -56,37 +55,12 @@ #include "BKE_sequencer.h" #include "BKE_scene.h" -#include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" - #ifdef WITH_AUDASPACE /* evil globals ;-) */ static int sound_cfra; static char **audio_device_names = NULL; #endif -BLI_INLINE void sound_verify_evaluated_id(ID *id) -{ - UNUSED_VARS_NDEBUG(id); - /* This is a bit tricky and not quite reliable, but good enough check. - * - * We don't want audio system handles to be allocated on amn original datablocks, and only want - * them to be allocated on a datablocks which are result of dependency graph evaluation. - * - * Datablocks which are covered by a copy-on-write system of dependency graph will have - * LIB_TAG_COPIED_ON_WRITE tag set on them. But if some of datablocks during its evaluation - * decides to re-allocate it's nested one (for example, object evaluation could re-allocate mesh - * when evaluating modifier stack). Such datablocks will have LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT - * tag set on them. - * - * Additionally, we also allow datablocks outside of main database. Those can not be "original" - * and could be used as a temporary evaluated result during operations like baking. - * - * NOTE: We conder ID evaluated if ANY of those flags is set. We do NOT require ALL of them. */ - BLI_assert(id->tag & - (LIB_TAG_COPIED_ON_WRITE | LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT | LIB_TAG_NO_MAIN)); -} - bSound *BKE_sound_new_file(Main *bmain, const char *filepath) { bSound *sound; @@ -103,10 +77,7 @@ bSound *BKE_sound_new_file(Main *bmain, const char *filepath) BLI_strncpy(sound->name, filepath, FILE_MAX); /* sound->type = SOUND_TYPE_FILE; */ /* XXX unused currently */ - sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); - BLI_spin_init(sound->spinlock); - - BKE_sound_reset_runtime(sound); + BKE_sound_load(bmain, sound); return sound; } @@ -154,18 +125,6 @@ void BKE_sound_free(bSound *sound) sound->packedfile = NULL; } - BKE_sound_free_audio(sound); - BKE_sound_free_waveform(sound); - - if (sound->spinlock) { - BLI_spin_end(sound->spinlock); - MEM_freeN(sound->spinlock); - sound->spinlock = NULL; - } -} - -void BKE_sound_free_audio(bSound *sound) -{ #ifdef WITH_AUDASPACE if (sound->handle) { AUD_Sound_free(sound->handle); @@ -177,9 +136,15 @@ void BKE_sound_free_audio(bSound *sound) AUD_Sound_free(sound->cache); sound->cache = NULL; } -#else - UNUSED_VARS(sound); + + BKE_sound_free_waveform(sound); + #endif /* WITH_AUDASPACE */ + if (sound->spinlock) { + BLI_spin_end(sound->spinlock); + MEM_freeN(sound->spinlock); + sound->spinlock = NULL; + } } /** @@ -192,7 +157,7 @@ void BKE_sound_free_audio(bSound *sound) * * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). */ -void BKE_sound_copy_data(Main *UNUSED(bmain), +void BKE_sound_copy_data(Main *bmain, bSound *sound_dst, const bSound *UNUSED(sound_src), const int UNUSED(flag)) @@ -201,8 +166,8 @@ void BKE_sound_copy_data(Main *UNUSED(bmain), sound_dst->cache = NULL; sound_dst->waveform = NULL; sound_dst->playback_handle = NULL; - sound_dst->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); - BLI_spin_init(sound_dst->spinlock); + sound_dst->spinlock = + NULL; /* Think this is OK? Otherwise, easy to create new spinlock here... */ /* Just to be sure, should not have any value actually after reading time. */ sound_dst->ipo = NULL; @@ -212,7 +177,8 @@ void BKE_sound_copy_data(Main *UNUSED(bmain), sound_dst->packedfile = dupPackedFile(sound_dst->packedfile); } - BKE_sound_reset_runtime(sound_dst); + /* Initialize whole runtime (audaspace) stuff. */ + BKE_sound_load(bmain, sound_dst); } void BKE_sound_make_local(Main *bmain, bSound *sound, const bool lib_local) @@ -225,15 +191,31 @@ void BKE_sound_make_local(Main *bmain, bSound *sound, const bool lib_local) static const char *force_device = NULL; # ifdef WITH_JACK -static SoundJackSyncCallback sound_jack_sync_callback = NULL; - static void sound_sync_callback(void *data, int mode, float time) { - if (sound_jack_sync_callback == NULL) { + // Ugly: Blender doesn't like it when the animation is played back during rendering + if (G.is_rendering) { return; } + Main *bmain = (Main *)data; - sound_jack_sync_callback(bmain, mode, time); + Scene *scene; + + scene = bmain->scenes.first; + while (scene) { + if (scene->audio.flag & AUDIO_SYNC) { + if (mode) { + BKE_sound_play_scene(scene); + } + else { + BKE_sound_stop_scene(scene); + } + if (scene->playback_handle) { + AUD_Handle_setPosition(scene->playback_handle, time); + } + } + scene = scene->id.next; + } } # endif @@ -316,7 +298,7 @@ void BKE_sound_init_main(Main *bmain) AUD_setSynchronizerCallback(sound_sync_callback, bmain); } # else - UNUSED_VARS(bmain); + (void)bmain; /* unused */ # endif } @@ -385,8 +367,6 @@ bSound *BKE_sound_new_limiter(Main *bmain, bSound *source, float start, float en void BKE_sound_cache(bSound *sound) { - sound_verify_evaluated_id(&sound->id); - sound->flags |= SOUND_FLAGS_CACHING; if (sound->cache) { AUD_Sound_free(sound->cache); @@ -413,50 +393,44 @@ void BKE_sound_delete_cache(bSound *sound) void BKE_sound_load(Main *bmain, bSound *sound) { - sound_verify_evaluated_id(&sound->id); - BKE_sound_load_audio(bmain, sound); -} - -void BKE_sound_load_audio(Main *bmain, bSound *sound) -{ - - if (sound->cache) { - AUD_Sound_free(sound->cache); - sound->cache = NULL; - } + if (sound) { + if (sound->cache) { + AUD_Sound_free(sound->cache); + sound->cache = NULL; + } - if (sound->handle) { - AUD_Sound_free(sound->handle); - sound->handle = NULL; - sound->playback_handle = NULL; - } + if (sound->handle) { + AUD_Sound_free(sound->handle); + sound->handle = NULL; + sound->playback_handle = NULL; + } - BKE_sound_free_waveform(sound); + BKE_sound_free_waveform(sound); /* XXX unused currently */ # if 0 switch (sound->type) { case SOUND_TYPE_FILE: # endif - { - char fullpath[FILE_MAX]; + { + char fullpath[FILE_MAX]; - /* load sound */ - PackedFile *pf = sound->packedfile; + /* load sound */ + PackedFile *pf = sound->packedfile; - /* don't modify soundact->sound->name, only change a copy */ - BLI_strncpy(fullpath, sound->name, sizeof(fullpath)); - BLI_path_abs(fullpath, ID_BLEND_PATH(bmain, &sound->id)); + /* don't modify soundact->sound->name, only change a copy */ + BLI_strncpy(fullpath, sound->name, sizeof(fullpath)); + BLI_path_abs(fullpath, ID_BLEND_PATH(bmain, &sound->id)); - /* but we need a packed file then */ - if (pf) { - sound->handle = AUD_Sound_bufferFile((unsigned char *)pf->data, pf->size); - } - else { - /* or else load it from disk */ - sound->handle = AUD_Sound_file(fullpath); + /* but we need a packed file then */ + if (pf) { + sound->handle = AUD_Sound_bufferFile((unsigned char *)pf->data, pf->size); + } + else { + /* or else load it from disk */ + sound->handle = AUD_Sound_file(fullpath); + } } - } /* XXX unused currently */ # if 0 break; @@ -473,34 +447,34 @@ void BKE_sound_load_audio(Main *bmain, bSound *sound) break; } # endif - if (sound->flags & SOUND_FLAGS_MONO) { - void *handle = AUD_Sound_rechannel(sound->handle, AUD_CHANNELS_MONO); - AUD_Sound_free(sound->handle); - sound->handle = handle; - } + if (sound->flags & SOUND_FLAGS_MONO) { + void *handle = AUD_Sound_rechannel(sound->handle, AUD_CHANNELS_MONO); + AUD_Sound_free(sound->handle); + sound->handle = handle; + } - if (sound->flags & SOUND_FLAGS_CACHING) { - sound->cache = AUD_Sound_cache(sound->handle); - } + if (sound->flags & SOUND_FLAGS_CACHING) { + sound->cache = AUD_Sound_cache(sound->handle); + } - if (sound->cache) { - sound->playback_handle = sound->cache; - } - else { - sound->playback_handle = sound->handle; + if (sound->cache) { + sound->playback_handle = sound->cache; + } + else { + sound->playback_handle = sound->handle; + } + + BKE_sound_update_sequencer(bmain, sound); } } AUD_Device *BKE_sound_mixdown(Scene *scene, AUD_DeviceSpecs specs, int start, float volume) { - sound_verify_evaluated_id(&scene->id); return AUD_openMixdownDevice(specs, scene->sound_scene, volume, start / FPS); } void BKE_sound_create_scene(Scene *scene) { - sound_verify_evaluated_id(&scene->id); - /* should be done in version patch, but this gets called before */ if (scene->r.frs_sec_base == 0) { scene->r.frs_sec_base = 1; @@ -533,21 +507,16 @@ void BKE_sound_destroy_scene(Scene *scene) void BKE_sound_reset_scene_specs(Scene *scene) { - sound_verify_evaluated_id(&scene->id); + AUD_Specs specs; - if (scene->sound_scene) { - AUD_Specs specs; + specs.channels = AUD_Device_getChannels(sound_device); + specs.rate = AUD_Device_getRate(sound_device); - specs.channels = AUD_Device_getChannels(sound_device); - specs.rate = AUD_Device_getRate(sound_device); - - AUD_Sequence_setSpecs(scene->sound_scene, specs); - } + AUD_Sequence_setSpecs(scene->sound_scene, specs); } void BKE_sound_mute_scene(Scene *scene, int muted) { - sound_verify_evaluated_id(&scene->id); if (scene->sound_scene) { AUD_Sequence_setMuted(scene->sound_scene, muted); } @@ -555,8 +524,6 @@ void BKE_sound_mute_scene(Scene *scene, int muted) void BKE_sound_update_fps(Scene *scene) { - sound_verify_evaluated_id(&scene->id); - if (scene->sound_scene) { AUD_Sequence_setFPS(scene->sound_scene, FPS); } @@ -566,8 +533,6 @@ void BKE_sound_update_fps(Scene *scene) void BKE_sound_update_scene_listener(Scene *scene) { - sound_verify_evaluated_id(&scene->id); - AUD_Sequence_setSpeedOfSound(scene->sound_scene, scene->audio.speed_of_sound); AUD_Sequence_setDopplerFactor(scene->sound_scene, scene->audio.doppler_factor); AUD_Sequence_setDistanceModel(scene->sound_scene, scene->audio.distance_model); @@ -576,7 +541,6 @@ void BKE_sound_update_scene_listener(Scene *scene) void *BKE_sound_scene_add_scene_sound( Scene *scene, Sequence *sequence, int startframe, int endframe, int frameskip) { - sound_verify_evaluated_id(&scene->id); if (sequence->scene && scene != sequence->scene) { const double fps = FPS; return AUD_Sequence_add(scene->sound_scene, @@ -600,7 +564,6 @@ void *BKE_sound_scene_add_scene_sound_defaults(Scene *scene, Sequence *sequence) void *BKE_sound_add_scene_sound( Scene *scene, Sequence *sequence, int startframe, int endframe, int frameskip) { - sound_verify_evaluated_id(&scene->id); /* Happens when sequence's sound datablock was removed. */ if (sequence->sound == NULL) { return NULL; @@ -640,14 +603,12 @@ void BKE_sound_mute_scene_sound(void *handle, char mute) void BKE_sound_move_scene_sound( Scene *scene, void *handle, int startframe, int endframe, int frameskip) { - sound_verify_evaluated_id(&scene->id); const double fps = FPS; AUD_SequenceEntry_move(handle, startframe / fps, endframe / fps, frameskip / fps); } void BKE_sound_move_scene_sound_defaults(Scene *scene, Sequence *sequence) { - sound_verify_evaluated_id(&scene->id); if (sequence->scene_sound) { BKE_sound_move_scene_sound(scene, sequence->scene_sound, @@ -669,7 +630,6 @@ void BKE_sound_set_cfra(int cfra) void BKE_sound_set_scene_volume(Scene *scene, float volume) { - sound_verify_evaluated_id(&scene->id); AUD_Sequence_setAnimationData(scene->sound_scene, AUD_AP_VOLUME, CFRA, @@ -695,8 +655,6 @@ void BKE_sound_set_scene_sound_pan(void *handle, float pan, char animated) void BKE_sound_update_sequencer(Main *main, bSound *sound) { - BLI_assert(!"is not supposed to be used, is weird function."); - Scene *scene; for (scene = main->scenes.first; scene; scene = scene->id.next) { @@ -706,8 +664,6 @@ void BKE_sound_update_sequencer(Main *main, bSound *sound) static void sound_start_play_scene(Scene *scene) { - sound_verify_evaluated_id(&scene->id); - if (scene->playback_handle) { AUD_Handle_stop(scene->playback_handle); } @@ -721,8 +677,6 @@ static void sound_start_play_scene(Scene *scene) void BKE_sound_play_scene(Scene *scene) { - sound_verify_evaluated_id(&scene->id); - AUD_Status status; const float cur_time = (float)((double)CFRA / FPS); @@ -765,8 +719,6 @@ void BKE_sound_stop_scene(Scene *scene) void BKE_sound_seek_scene(Main *bmain, Scene *scene) { - sound_verify_evaluated_id(&scene->id); - AUD_Status status; bScreen *screen; int animation_playing; @@ -798,10 +750,9 @@ void BKE_sound_seek_scene(Main *bmain, Scene *scene) } } - Scene *scene_orig = (Scene *)DEG_get_original_id(&scene->id); - if (scene_orig->audio.flag & AUDIO_SCRUB && !animation_playing) { + if (scene->audio.flag & AUDIO_SCRUB && !animation_playing) { AUD_Handle_setPosition(scene->playback_handle, cur_time); - if (scene_orig->audio.flag & AUDIO_SYNC) { + if (scene->audio.flag & AUDIO_SYNC) { AUD_seekSynchronizer(scene->playback_handle, cur_time); } AUD_Handle_resume(scene->playback_handle); @@ -817,7 +768,7 @@ void BKE_sound_seek_scene(Main *bmain, Scene *scene) } } else { - if (scene_orig->audio.flag & AUDIO_SYNC) { + if (scene->audio.flag & AUDIO_SYNC) { AUD_seekSynchronizer(scene->playback_handle, cur_time); } else { @@ -832,8 +783,6 @@ void BKE_sound_seek_scene(Main *bmain, Scene *scene) float BKE_sound_sync_scene(Scene *scene) { - sound_verify_evaluated_id(&scene->id); - // Ugly: Blender doesn't like it when the animation is played back during rendering if (G.is_rendering) { return NAN_FLT; @@ -852,8 +801,6 @@ float BKE_sound_sync_scene(Scene *scene) int BKE_sound_scene_playing(Scene *scene) { - sound_verify_evaluated_id(&scene->id); - // Ugly: Blender doesn't like it when the animation is played back during rendering if (G.is_rendering) { return -1; @@ -884,9 +831,6 @@ void BKE_sound_free_waveform(bSound *sound) sound->tags &= ~SOUND_TAGS_WAVEFORM_NO_RELOAD; } -/* TODO(sergey): Consider mamakinging this function fully autonomous, as in, not require having - * an existing playback handle. That would make it easy to read waveforms, which doesn't seem to - * be affected by evaluated scene (waveworm comes from file). */ void BKE_sound_read_waveform(bSound *sound, short *stop) { AUD_SoundInfo info = AUD_getInfo(sound->playback_handle); @@ -935,14 +879,11 @@ static void sound_update_base(Scene *scene, Base *base, void *new_set) Speaker *speaker; float quat[4]; - sound_verify_evaluated_id(&scene->id); - sound_verify_evaluated_id(&ob->id); + if ((ob->id.tag & LIB_TAG_DOIT) == 0) { + return; + } - // TODO(sergey): Bring the test back, or make it a part of dependency graph update. - // if ((ob->id.tag & LIB_TAG_DOIT) == 0) { - // return; - // } - // ob->id.tag &= ~LIB_TAG_DOIT; + ob->id.tag &= ~LIB_TAG_DOIT; if ((ob->type != OB_SPEAKER) || !ob->adt) { return; @@ -1005,8 +946,6 @@ static void sound_update_base(Scene *scene, Base *base, void *new_set) void BKE_sound_update_scene(Main *bmain, Scene *scene) { - sound_verify_evaluated_id(&scene->id); - Base *base; Scene *sce_it; @@ -1016,8 +955,7 @@ void BKE_sound_update_scene(Main *bmain, Scene *scene) /* cheap test to skip looping over all objects (no speakers is a common case) */ if (!BLI_listbase_is_empty(&bmain->speakers)) { - // TODO(sergey): Bring the test back, or make it a part of dependency graph update. - // BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, true); + BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, true); for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { @@ -1054,7 +992,6 @@ void *BKE_sound_get_factory(void *sound) /* stupid wrapper because AUD_C-API.h includes Python.h which makesrna doesn't like */ float BKE_sound_get_length(bSound *sound) { - sound_verify_evaluated_id(&sound->id); AUD_SoundInfo info = AUD_getInfo(sound->playback_handle); return info.length; @@ -1217,94 +1154,4 @@ char **BKE_sound_get_device_names(void) return names; } -void BKE_sound_free_waveform(bSound *UNUSED(sound)) -{ -} - -void BKE_sound_load_audio(Main *UNUSED(bmain), bSound *UNUSED(sound)) -{ -} - #endif /* WITH_AUDASPACE */ - -void BKE_sound_update_and_seek(Main *bmain, Depsgraph *depsgraph) -{ - Scene *scene_orig = DEG_get_input_scene(depsgraph); - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - /* NOTE: We don't do copy-on-write or anything like that here because we need to know scene's - * flags like "scrubbing" in the BKE_sound_seek_scene(). So we simply update frame to which - * seek needs to happen. - * - * TODO(sergey): Might change API so the frame is passes explicitly. */ - scene_eval->r.cfra = scene_orig->r.cfra; - BKE_sound_seek_scene(bmain, scene_eval); -} - -void BKE_sound_reset_scene_runtime(Scene *scene) -{ - scene->sound_scene = NULL; - scene->playback_handle = NULL; - scene->sound_scrub_handle = NULL; - scene->speaker_handles = NULL; -} - -void BKE_sound_ensure_scene(struct Scene *scene) -{ - if (scene->sound_scene != NULL) { - return; - } - BKE_sound_create_scene(scene); -} - -void BKE_sound_reset_runtime(bSound *sound) -{ - sound->cache = NULL; - sound->playback_handle = NULL; -} - -void BKE_sound_ensure_loaded(Main *bmain, bSound *sound) -{ - if (sound->cache != NULL) { - return; - } - BKE_sound_load(bmain, sound); -} - -void BKE_sound_jack_sync_callback_set(SoundJackSyncCallback callback) -{ -#if defined(WITH_AUDASPACE) && defined(WITH_JACK) - sound_jack_sync_callback = callback; -#else - UNUSED_VARS(callback); -#endif -} - -void BKE_sound_jack_scene_update(Scene *scene, int mode, float time) -{ - sound_verify_evaluated_id(&scene->id); - - /* Ugly: Blender doesn't like it when the animation is played back during rendering. */ - if (G.is_rendering) { - return; - } - - if (mode) { - BKE_sound_play_scene(scene); - } - else { - BKE_sound_stop_scene(scene); - } -#ifdef WITH_AUDASPACE - if (scene->playback_handle != NULL) { - AUD_Handle_setPosition(scene->playback_handle, time); - } -#else - UNUSED_VARS(time); -#endif -} - -void BKE_sound_evaluate(Depsgraph *depsgraph, Main *bmain, bSound *sound) -{ - DEG_debug_print_eval(depsgraph, __func__, sound->id.name, sound); - BKE_sound_ensure_loaded(bmain, sound); -} diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c index f9584adc6e0..669eb5c42dc 100644 --- a/source/blender/blenkernel/intern/workspace.c +++ b/source/blender/blenkernel/intern/workspace.c @@ -36,6 +36,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_windowmanager_types.h" #include "DNA_workspace_types.h" #include "DEG_depsgraph.h" @@ -43,7 +44,8 @@ #include "MEM_guardedalloc.h" /* -------------------------------------------------------------------- */ -/* Internal utils */ +/** \name Internal Utils + * \{ */ static void workspace_layout_name_set(WorkSpace *workspace, WorkSpaceLayout *layout, @@ -134,8 +136,11 @@ static bool UNUSED_FUNCTION(workspaces_is_screen_used) return false; } +/** \} */ + /* -------------------------------------------------------------------- */ -/* Create, delete, init */ +/** \name Create, Delete, Init + * \{ */ WorkSpace *BKE_workspace_add(Main *bmain, const char *name) { @@ -253,8 +258,11 @@ void BKE_workspace_relations_free(ListBase *relation_list) } } +/** \} */ + /* -------------------------------------------------------------------- */ -/* General Utils */ +/** \name General Utils + * \{ */ WorkSpaceLayout *BKE_workspace_layout_find(const WorkSpace *workspace, const bScreen *screen) { @@ -354,8 +362,32 @@ void BKE_workspace_tool_remove(struct WorkSpace *workspace, struct bToolRef *tre MEM_freeN(tref); } +bool BKE_workspace_owner_id_check(const WorkSpace *workspace, const char *owner_id) +{ + if ((*owner_id == '\0') || ((workspace->flags & WORKSPACE_USE_FILTER_BY_ORIGIN) == 0)) { + return true; + } + else { + /* We could use hash lookup, for now this list is highly likely under < ~16 items. */ + return BLI_findstring(&workspace->owner_ids, owner_id, offsetof(wmOwnerID, name)) != NULL; + } +} + +void BKE_workspace_id_tag_all_visible(Main *bmain, int tag) +{ + BKE_main_id_tag_listbase(&bmain->workspaces, tag, false); + wmWindowManager *wm = bmain->wm.first; + for (wmWindow *win = wm->windows.first; win; win = win->next) { + WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook); + workspace->id.tag |= tag; + } +} + +/** \} */ + /* -------------------------------------------------------------------- */ -/* Getters/Setters */ +/** \name Getters/Setters + * \{ */ WorkSpace *BKE_workspace_active_get(WorkSpaceInstanceHook *hook) { @@ -433,13 +465,4 @@ void BKE_workspace_hook_layout_for_workspace_set(WorkSpaceInstanceHook *hook, workspace_relation_ensure_updated(&workspace->hook_layout_relations, hook, layout); } -bool BKE_workspace_owner_id_check(const WorkSpace *workspace, const char *owner_id) -{ - if ((*owner_id == '\0') || ((workspace->flags & WORKSPACE_USE_FILTER_BY_ORIGIN) == 0)) { - return true; - } - else { - /* we could use hash lookup, for now this list is highly under < ~16 items. */ - return BLI_findstring(&workspace->owner_ids, owner_id, offsetof(wmOwnerID, name)) != NULL; - } -} +/** \} */ diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index b72b99e514d..19425a0d80b 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -118,7 +118,6 @@ bMovieHandle *BKE_movie_handle_get(const char imtype) mh.start_movie = start_stub; mh.append_movie = append_stub; mh.end_movie = end_stub; - mh.get_next_frame = NULL; mh.get_movie_path = NULL; mh.context_create = context_create_stub; mh.context_free = context_free_stub; diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 652f096f32d..52d976daa2d 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -209,6 +209,7 @@ bool invert_m3(float R[3][3]); bool invert_m3_m3(float R[3][3], const float A[3][3]); bool invert_m4(float R[4][4]); bool invert_m4_m4(float R[4][4], const float A[4][4]); +bool invert_m4_m4_fallback(float R[4][4], const float A[4][4]); /* double arithmetic (mixed float/double) */ void mul_m4_v4d(const float M[4][4], double r[4]); @@ -260,6 +261,7 @@ float determinant_m2(float a, float b, float c, float d); float determinant_m3( float a, float b, float c, float d, float e, float f, float g, float h, float i); float determinant_m3_array(const float m[3][3]); +float determinant_m4_mat3_array(const float m[4][4]); float determinant_m4(const float A[4][4]); #define PSEUDOINVERSE_EPSILON 1e-8f @@ -277,6 +279,9 @@ void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4]); void scale_m3_fl(float R[3][3], float scale); void scale_m4_fl(float R[4][4], float scale); +float mat3_to_volume_scale(const float M[3][3]); +float mat4_to_volume_scale(const float M[4][4]); + float mat3_to_scale(const float M[3][3]); float mat4_to_scale(const float M[4][4]); float mat4_to_xy_scale(const float M[4][4]); diff --git a/source/blender/blenlib/BLI_memblock.h b/source/blender/blenlib/BLI_memblock.h new file mode 100644 index 00000000000..81dd2100362 --- /dev/null +++ b/source/blender/blenlib/BLI_memblock.h @@ -0,0 +1,57 @@ +/* + * 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) 2008 Blender Foundation. + * All rights reserved. + */ + +#ifndef __BLI_MEMBLOCK_H__ +#define __BLI_MEMBLOCK_H__ + +/** \file + * \ingroup bli + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "BLI_compiler_attrs.h" + +struct BLI_memblock; + +typedef struct BLI_memblock BLI_memblock; +typedef void (*MemblockValFreeFP)(void *val); + +BLI_memblock *BLI_memblock_create(uint elem_size, + const bool clear_alloc) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +void *BLI_memblock_alloc(BLI_memblock *mblk) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP valfreefp) ATTR_NONNULL(1); +void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback) ATTR_NONNULL(1); + +typedef struct BLI_memblock_iter { + BLI_memblock *mblk; + int current_index; + int elem_per_chunk; +} BLI_memblock_iter; + +void BLI_memblock_iternew(BLI_memblock *pool, BLI_memblock_iter *iter) ATTR_NONNULL(); +void *BLI_memblock_iterstep(BLI_memblock_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); + +#ifdef __cplusplus +} +#endif + +#endif /* __BLI_MEMBLOCK_H__ */ diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h index 151b02a33aa..eec4e885493 100644 --- a/source/blender/blenlib/BLI_rand.h +++ b/source/blender/blenlib/BLI_rand.h @@ -25,6 +25,10 @@ * \brief Random number functions. */ +#ifdef __cplusplus +extern "C" { +#endif + /* RNG is an abstract random number generator type that avoids using globals. * Always use this instead of the global RNG unless you have a good reason, * the global RNG is not thread safe and will not give repeatable results. @@ -106,4 +110,8 @@ void BLI_hammersley_1d(unsigned int n, double *r); void BLI_halton_2d_sequence(unsigned int prime[2], double offset[2], int n, double *r); void BLI_hammersley_2d_sequence(unsigned int n, double *r); +#ifdef __cplusplus +} +#endif + #endif /* __BLI_RAND_H__ */ diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index dbc72ff1213..0ec6e7ee4fc 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -48,6 +48,7 @@ set(SRC intern/BLI_linklist.c intern/BLI_linklist_lockfree.c intern/BLI_memarena.c + intern/BLI_memblock.c intern/BLI_memiter.c intern/BLI_mempool.c intern/BLI_timer.c @@ -194,6 +195,7 @@ set(SRC BLI_math_statistics.h BLI_math_vector.h BLI_memarena.h + BLI_memblock.h BLI_memiter.h BLI_memory_utils.h BLI_mempool.h diff --git a/source/blender/blenlib/intern/BLI_memblock.c b/source/blender/blenlib/intern/BLI_memblock.c new file mode 100644 index 00000000000..50b1e14757c --- /dev/null +++ b/source/blender/blenlib/intern/BLI_memblock.c @@ -0,0 +1,174 @@ +/* + * 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) 2008 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bli + * + * Dead simple, fast memory allocator for allocating many elements of the same size. + * + */ + +#include <string.h> +#include <stdlib.h> + +#include "atomic_ops.h" + +#include "BLI_utildefines.h" + +#include "BLI_memblock.h" /* own include */ + +#include "MEM_guardedalloc.h" + +#include "BLI_strict_flags.h" /* keep last */ + +#define BLI_MEM_BLOCK_CHUNK_SIZE (1 << 15) /* 32KiB */ +#define CHUNK_LIST_SIZE 16 + +struct BLI_memblock { + void **chunk_list; + + /** Element size in bytes. */ + int elem_size; + /** First unused element index. */ + int elem_next; + /** Last "touched" element. */ + int elem_last; + /** Chunck size in bytes. */ + int chunk_size; + /** Number of allocated chunck. */ + int chunk_len; + /** Clear newly allocated chuncks. */ + bool clear_alloc; +}; + +/** + * /clear_alloc will clear the memory the first time a chunck is allocated. + */ +BLI_memblock *BLI_memblock_create(uint elem_size, const bool clear_alloc) +{ + BLI_assert(elem_size < BLI_MEM_BLOCK_CHUNK_SIZE); + + BLI_memblock *mblk = MEM_mallocN(sizeof(BLI_memblock), "BLI_memblock"); + mblk->elem_size = (int)elem_size; + mblk->elem_next = 0; + mblk->elem_last = -1; + mblk->chunk_size = BLI_MEM_BLOCK_CHUNK_SIZE; + mblk->chunk_len = CHUNK_LIST_SIZE; + mblk->chunk_list = MEM_callocN(sizeof(void *) * (uint)mblk->chunk_len, "chunk list"); + mblk->clear_alloc = clear_alloc; + return mblk; +} + +void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback) +{ + if (free_callback) { + int elem_per_chunk = mblk->chunk_size / mblk->elem_size; + + for (int i = mblk->elem_last; i >= 0; i--) { + int chunk_idx = i / elem_per_chunk; + int elem_idx = i - elem_per_chunk * chunk_idx; + void *val = (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx; + free_callback(val); + } + } + + for (int i = 0; i < mblk->chunk_len; i++) { + MEM_SAFE_FREE(mblk->chunk_list[i]); + } + MEM_SAFE_FREE(mblk->chunk_list); + MEM_freeN(mblk); +} + +/* Reset elem count to 0 but keep as much memory allocated needed for at least the previous elem + * count. */ +void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP free_callback) +{ + int elem_per_chunk = mblk->chunk_size / mblk->elem_size; + int last_used_chunk = (mblk->elem_next - 1) / elem_per_chunk; + + if (free_callback) { + for (int i = mblk->elem_last; i >= mblk->elem_next; i--) { + int chunk_idx = i / elem_per_chunk; + int elem_idx = i - elem_per_chunk * chunk_idx; + void *val = (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx; + free_callback(val); + } + } + + for (int i = last_used_chunk + 1; i < mblk->chunk_len; i++) { + MEM_SAFE_FREE(mblk->chunk_list[i]); + } + + if (UNLIKELY(last_used_chunk + 1 < mblk->chunk_len - CHUNK_LIST_SIZE)) { + mblk->chunk_len -= CHUNK_LIST_SIZE; + mblk->chunk_list = MEM_recallocN(mblk->chunk_list, sizeof(void *) * (uint)mblk->chunk_len); + } + + mblk->elem_last = mblk->elem_next - 1; + mblk->elem_next = 0; +} + +void *BLI_memblock_alloc(BLI_memblock *mblk) +{ + int elem_per_chunk = mblk->chunk_size / mblk->elem_size; + int chunk_idx = mblk->elem_next / elem_per_chunk; + int elem_idx = mblk->elem_next - elem_per_chunk * chunk_idx; + + if (mblk->elem_last < mblk->elem_next) { + mblk->elem_last = mblk->elem_next; + } + + mblk->elem_next++; + + if (UNLIKELY(chunk_idx >= mblk->chunk_len)) { + mblk->chunk_len += CHUNK_LIST_SIZE; + mblk->chunk_list = MEM_recallocN(mblk->chunk_list, sizeof(void *) * (uint)mblk->chunk_len); + } + + if (UNLIKELY(mblk->chunk_list[chunk_idx] == NULL)) { + if (mblk->clear_alloc) { + mblk->chunk_list[chunk_idx] = MEM_callocN((uint)mblk->chunk_size, "BLI_memblock chunk"); + } + else { + mblk->chunk_list[chunk_idx] = MEM_mallocN((uint)mblk->chunk_size, "BLI_memblock chunk"); + } + } + + return (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx; +} + +void BLI_memblock_iternew(BLI_memblock *mblk, BLI_memblock_iter *iter) +{ + iter->mblk = mblk; + iter->current_index = 0; + iter->elem_per_chunk = mblk->chunk_size / mblk->elem_size; +} + +void *BLI_memblock_iterstep(BLI_memblock_iter *iter) +{ + if (iter->current_index >= iter->mblk->elem_next) { + return NULL; + } + + int chunk_idx = iter->current_index / iter->elem_per_chunk; + int elem_idx = iter->current_index - iter->elem_per_chunk * chunk_idx; + iter->current_index++; + + return (char *)(iter->mblk->chunk_list[chunk_idx]) + iter->mblk->elem_size * elem_idx; +} diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index e09fae7d140..6ac1ac776b3 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -931,6 +931,13 @@ float determinant_m3_array(const float m[3][3]) m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1])); } +float determinant_m4_mat3_array(const float m[4][4]) +{ + return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) - + m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) + + m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1])); +} + bool invert_m3_ex(float m[3][3], const float epsilon) { float tmp[3][3]; @@ -1011,6 +1018,81 @@ bool invert_m4(float m[4][4]) return success; } +/** + * Computes the inverse of mat and puts it in inverse. + * Uses Gaussian Elimination with partial (maximal column) pivoting. + * \return true on success (i.e. can always find a pivot) and false on failure. + * Mark Segal - 1992. + * + * \note this is less performant than #EIG_invert_m4_m4 (Eigen), but e.g. + * for non-invertible scale matrices, findinging a partial solution can + * be useful to have a valid local transform center, see T57767. + */ +bool invert_m4_m4_fallback(float inverse[4][4], const float mat[4][4]) +{ + if (EIG_invert_m4_m4(inverse, mat)) { + return true; + } + + int i, j, k; + double temp; + float tempmat[4][4]; + float max; + int maxj; + + BLI_assert(inverse != mat); + + /* Set inverse to identity */ + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) + inverse[i][j] = 0; + for (i = 0; i < 4; i++) + inverse[i][i] = 1; + + /* Copy original matrix so we don't mess it up */ + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) + tempmat[i][j] = mat[i][j]; + + for (i = 0; i < 4; i++) { + /* Look for row with max pivot */ + max = fabsf(tempmat[i][i]); + maxj = i; + for (j = i + 1; j < 4; j++) { + if (fabsf(tempmat[j][i]) > max) { + max = fabsf(tempmat[j][i]); + maxj = j; + } + } + /* Swap rows if necessary */ + if (maxj != i) { + for (k = 0; k < 4; k++) { + SWAP(float, tempmat[i][k], tempmat[maxj][k]); + SWAP(float, inverse[i][k], inverse[maxj][k]); + } + } + + if (UNLIKELY(tempmat[i][i] == 0.0f)) { + return false; /* No non-zero pivot */ + } + temp = (double)tempmat[i][i]; + for (k = 0; k < 4; k++) { + tempmat[i][k] = (float)((double)tempmat[i][k] / temp); + inverse[i][k] = (float)((double)inverse[i][k] / temp); + } + for (j = 0; j < 4; j++) { + if (j != i) { + temp = tempmat[j][i]; + for (k = 0; k < 4; k++) { + tempmat[j][k] -= (float)((double)tempmat[i][k] * temp); + inverse[j][k] -= (float)((double)inverse[i][k] * temp); + } + } + } + } + return true; +} + bool invert_m4_m4(float inverse[4][4], const float mat[4][4]) { /* Use optimized matrix inverse from Eigen, since performance @@ -1641,9 +1723,26 @@ void mat4_to_size(float size[3], const float mat[4][4]) size[2] = len_v3(mat[2]); } -/* this gets the average scale of a matrix, only use when your scaling +/** + * This computes the overall volume scale factor of a transformation matrix. + * For an orthogonal matrix, it is the product of all three scale values. + * Returns a negative value if the transform is flipped by negative scale. + */ +float mat3_to_volume_scale(const float mat[3][3]) +{ + return determinant_m3_array(mat); +} + +float mat4_to_volume_scale(const float mat[4][4]) +{ + return determinant_m4_mat3_array(mat); +} + +/** + * This gets the average scale of a matrix, only use when your scaling * data that has no idea of scale axis, examples are bone-envelope-radius - * and curve radius */ + * and curve radius. + */ float mat3_to_scale(const float mat[3][3]) { /* unit length vector */ @@ -2003,10 +2102,12 @@ bool equals_m4m4(const float mat1[4][4], const float mat2[4][4]) equals_v4v4(mat1[2], mat2[2]) && equals_v4v4(mat1[3], mat2[3])); } -/* make a 4x4 matrix out of 3 transform components */ -/* matrices are made in the order: scale * rot * loc */ -/* TODO: need to have a version that allows for rotation order... */ - +/** + * Make a 4x4 matrix out of 3 transform components. + * Matrices are made in the order: `scale * rot * loc` + * + * TODO: need to have a version that allows for rotation order... + */ void loc_eul_size_to_mat4(float mat[4][4], const float loc[3], const float eul[3], @@ -2031,9 +2132,10 @@ void loc_eul_size_to_mat4(float mat[4][4], mat[3][2] = loc[2]; } -/* make a 4x4 matrix out of 3 transform components */ - -/* matrices are made in the order: scale * rot * loc */ +/** + * Make a 4x4 matrix out of 3 transform components. + * Matrices are made in the order: `scale * rot * loc` + */ void loc_eulO_size_to_mat4(float mat[4][4], const float loc[3], const float eul[3], @@ -2059,9 +2161,10 @@ void loc_eulO_size_to_mat4(float mat[4][4], mat[3][2] = loc[2]; } -/* make a 4x4 matrix out of 3 transform components */ - -/* matrices are made in the order: scale * rot * loc */ +/** + * Make a 4x4 matrix out of 3 transform components. + * Matrices are made in the order: `scale * rot * loc` + */ void loc_quat_size_to_mat4(float mat[4][4], const float loc[3], const float quat[4], diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 28412bf6f34..e060c0f68d2 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3764,9 +3764,6 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose) } } - /* avoid string */ - GHash *bone_hash = BKE_armature_bone_from_name_map(arm); - if (ob->proxy) { /* sync proxy layer */ if (pose->proxy_layer) { @@ -3775,7 +3772,7 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose) /* sync proxy active bone */ if (pose->proxy_act_bone[0]) { - Bone *bone = BLI_ghash_lookup(bone_hash, pose->proxy_act_bone); + Bone *bone = BKE_armature_find_bone_name(arm, pose->proxy_act_bone); if (bone) { arm->act_bone = bone; } @@ -3785,7 +3782,7 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose) for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) { lib_link_constraints(fd, (ID *)ob, &pchan->constraints); - pchan->bone = BLI_ghash_lookup(bone_hash, pchan->name); + pchan->bone = BKE_armature_find_bone_name(arm, pchan->name); IDP_LibLinkProperty(pchan->prop, fd); @@ -3800,8 +3797,6 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose) } } - BLI_ghash_free(bone_hash, NULL, NULL); - if (rebuild) { DEG_id_tag_update_ex( bmain, &ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); @@ -3859,6 +3854,7 @@ static void direct_link_armature(FileData *fd, bArmature *arm) Bone *bone; link_list(fd, &arm->bonebase); + arm->bonehash = NULL; arm->edbo = NULL; arm->adt = newdataadr(fd, arm->adt); @@ -3870,6 +3866,8 @@ static void direct_link_armature(FileData *fd, bArmature *arm) arm->act_bone = newdataadr(fd, arm->act_bone); arm->act_edbone = NULL; + + BKE_armature_bone_hash_make(arm); } /** \} */ @@ -6466,7 +6464,9 @@ static void lib_link_scene(FileData *fd, Main *main) seq->scene_sound = NULL; if (seq->scene) { seq->scene = newlibadr(fd, sce->id.lib, seq->scene); - seq->scene_sound = NULL; + if (seq->scene) { + seq->scene_sound = BKE_sound_scene_add_scene_sound_defaults(sce, seq); + } } if (seq->clip) { seq->clip = newlibadr_us(fd, sce->id.lib, seq->clip); @@ -6487,7 +6487,7 @@ static void lib_link_scene(FileData *fd, Main *main) } if (seq->sound) { id_us_plus_no_lib((ID *)seq->sound); - seq->scene_sound = NULL; + seq->scene_sound = BKE_sound_add_scene_sound_defaults(sce, seq); } } if (seq->type == SEQ_TYPE_TEXT) { @@ -6506,6 +6506,9 @@ static void lib_link_scene(FileData *fd, Main *main) } } + BKE_sequencer_update_muting(sce->ed); + BKE_sequencer_update_sound_bounds_all(sce); + /* rigidbody world relies on it's linked collections */ if (sce->rigidbody_world) { RigidBodyWorld *rbw = sce->rigidbody_world; @@ -6635,6 +6638,13 @@ static void direct_link_paint(FileData *fd, const Scene *scene, Paint *p) p->tool_slots = newdataadr(fd, p->tool_slots); + /* Workaround for invalid data written in older versions. */ + const size_t expected_size = sizeof(PaintToolSlot) * p->tool_slots_len; + if (p->tool_slots && MEM_allocN_len(p->tool_slots) < expected_size) { + MEM_freeN(p->tool_slots); + p->tool_slots = MEM_callocN(expected_size, "PaintToolSlot"); + } + BKE_paint_runtime_init(scene->toolsettings, p); } @@ -6687,7 +6697,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) memset(&sce->customdata_mask, 0, sizeof(sce->customdata_mask)); memset(&sce->customdata_mask_modal, 0, sizeof(sce->customdata_mask_modal)); - BKE_sound_reset_scene_runtime(sce); + BKE_sound_create_scene(sce); /* set users to one by default, not in lib-link, this will increase it for compo nodes */ id_us_ensure_real(&sce->id); @@ -7123,7 +7133,6 @@ static void direct_link_panel_list(FileData *fd, ListBase *lb) link_list(fd, lb); for (Panel *pa = lb->first; pa; pa = pa->next) { - pa->paneltab = newdataadr(fd, pa->paneltab); pa->runtime_flag = 0; pa->activedata = NULL; pa->type = NULL; @@ -8428,9 +8437,10 @@ static void direct_link_sound(FileData *fd, bSound *sound) sound->waveform = NULL; } - sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); - BLI_spin_init(sound->spinlock); - + if (sound->spinlock) { + sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); + BLI_spin_init(sound->spinlock); + } /* clear waveform loading flag */ sound->tags &= ~SOUND_TAGS_WAVEFORM_LOADING; @@ -8447,7 +8457,7 @@ static void lib_link_sound(FileData *fd, Main *main) sound->ipo = newlibadr_us( fd, sound->id.lib, sound->ipo); // XXX deprecated - old animation system - BKE_sound_reset_runtime(sound); + BKE_sound_load(main, sound); sound->id.tag &= ~LIB_TAG_NEED_LINK; } @@ -9623,6 +9633,9 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) /* Don't read the active app template, use the default one. */ user->app_template[0] = '\0'; + /* Clear runtime data. */ + user->runtime.is_dirty = false; + /* free fd->datamap again */ oldnewmap_free_unused(fd->datamap); oldnewmap_clear(fd->datamap); @@ -9643,14 +9656,17 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) ListBase mainlist = {NULL, NULL}; bfd = MEM_callocN(sizeof(BlendFileData), "blendfiledata"); - bfd->main = BKE_main_new(); - BLI_addtail(&mainlist, bfd->main); - fd->mainlist = &mainlist; + bfd->main = BKE_main_new(); bfd->main->versionfile = fd->fileversion; bfd->type = BLENFILETYPE_BLEND; - BLI_strncpy(bfd->main->name, filepath, sizeof(bfd->main->name)); + + if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) { + BLI_addtail(&mainlist, bfd->main); + fd->mainlist = &mainlist; + BLI_strncpy(bfd->main->name, filepath, sizeof(bfd->main->name)); + } if (G.background) { /* We only read & store .blend thumbnail in background mode @@ -9728,45 +9744,52 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) /* do before read_libraries, but skip undo case */ if (fd->memfile == NULL) { - do_versions(fd, NULL, bfd->main); - do_versions_userdef(fd, bfd); + if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) { + do_versions(fd, NULL, bfd->main); + } + + if ((fd->skip_flags & BLO_READ_SKIP_USERDEF) == 0) { + do_versions_userdef(fd, bfd); + } } - read_libraries(fd, &mainlist); + if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) { + read_libraries(fd, &mainlist); - blo_join_main(&mainlist); + blo_join_main(&mainlist); - lib_link_all(fd, bfd->main); + lib_link_all(fd, bfd->main); - /* Skip in undo case. */ - if (fd->memfile == NULL) { - /* Yep, second splitting... but this is a very cheap operation, so no big deal. */ - blo_split_main(&mainlist, bfd->main); - for (Main *mainvar = mainlist.first; mainvar; mainvar = mainvar->next) { - BLI_assert(mainvar->versionfile != 0); - do_versions_after_linking(mainvar); - } - blo_join_main(&mainlist); + /* Skip in undo case. */ + if (fd->memfile == NULL) { + /* Yep, second splitting... but this is a very cheap operation, so no big deal. */ + blo_split_main(&mainlist, bfd->main); + for (Main *mainvar = mainlist.first; mainvar; mainvar = mainvar->next) { + BLI_assert(mainvar->versionfile != 0); + do_versions_after_linking(mainvar); + } + blo_join_main(&mainlist); - /* After all data has been read and versioned, uses LIB_TAG_NEW. */ - ntreeUpdateAllNew(bfd->main); - } + /* After all data has been read and versioned, uses LIB_TAG_NEW. */ + ntreeUpdateAllNew(bfd->main); + } - BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false); + BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false); - /* Now that all our data-blocks are loaded, - * we can re-generate overrides from their references. */ - if (fd->memfile == NULL) { - /* Do not apply in undo case! */ - BKE_main_override_static_update(bfd->main); - } + /* Now that all our data-blocks are loaded, + * we can re-generate overrides from their references. */ + if (fd->memfile == NULL) { + /* Do not apply in undo case! */ + BKE_main_override_static_update(bfd->main); + } - BKE_collections_after_lib_link(bfd->main); + BKE_collections_after_lib_link(bfd->main); - fix_relpaths_library(fd->relabase, - bfd->main); /* make all relative paths, relative to the open blend file */ + /* Make all relative paths, relative to the open blend file. */ + fix_relpaths_library(fd->relabase, bfd->main); - link_global(fd, bfd); /* as last */ + link_global(fd, bfd); /* as last */ + } fd->mainlist = NULL; /* Safety, this is local variable, shall not be used afterward. */ diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index face4b61d1e..7b239105251 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -285,8 +285,8 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb) memcpy(&ar->v2d, &sipo->v2d, sizeof(View2D)); /* init mainarea view2d */ - ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); - ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL); + ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); + ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_VERTICAL_HANDLES); ar->v2d.min[0] = FLT_MIN; ar->v2d.min[1] = FLT_MIN; @@ -304,7 +304,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb) ar->v2d.tot.ymin = (float)(-sa->winy) / 3.0f; ar->v2d.tot.ymax = 0.0f; - ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); + ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); ar->v2d.scroll |= (V2D_SCROLL_RIGHT); ar->v2d.align = V2D_ALIGN_NO_POS_Y; ar->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL; @@ -330,7 +330,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb) ar->v2d.minzoom = 0.01f; ar->v2d.maxzoom = 50; - ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); + ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); ar->v2d.scroll |= (V2D_SCROLL_RIGHT); ar->v2d.keepzoom = V2D_LOCKZOOM_Y; ar->v2d.align = V2D_ALIGN_NO_POS_Y; @@ -349,8 +349,8 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb) SpaceSeq *sseq = (SpaceSeq *)sl; memcpy(&ar->v2d, &sseq->v2d, sizeof(View2D)); - ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); - ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL); + ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); + ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_VERTICAL_HANDLES); ar->v2d.align = V2D_ALIGN_NO_NEG_Y; ar->v2d.flag |= V2D_IS_INITIALISED; break; diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 3a16389dfda..c7bcbf3d864 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -421,10 +421,13 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene) Collection *collection = BKE_collection_add(bmain, collection_master, name); collection->id.lib = scene->id.lib; + if (collection->id.lib != NULL) { + collection->id.tag |= LIB_TAG_INDIRECT; + } collections[layer] = collection; if (!(scene->lay & (1 << layer))) { - collection->flag |= COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER; + collection->flag |= COLLECTION_RESTRICT_VIEWPORT | COLLECTION_RESTRICT_RENDER; } } @@ -692,6 +695,26 @@ static void do_version_bbone_scale_animdata_cb(ID *UNUSED(id), } } +static void do_version_constraints_maintain_volume_mode_uniform(ListBase *lb) +{ + for (bConstraint *con = lb->first; con; con = con->next) { + if (con->type == CONSTRAINT_TYPE_SAMEVOL) { + bSameVolumeConstraint *data = (bSameVolumeConstraint *)con->data; + data->mode = SAMEVOL_UNIFORM; + } + } +} + +static void do_version_constraints_copy_scale_power(ListBase *lb) +{ + for (bConstraint *con = lb->first; con; con = con->next) { + if (con->type == CONSTRAINT_TYPE_SIZELIKE) { + bSizeLikeConstraint *data = (bSizeLikeConstraint *)con->data; + data->power = 1.0f; + } + } +} + void do_versions_after_linking_280(Main *bmain) { bool use_collection_compat_28 = true; @@ -705,7 +728,7 @@ void do_versions_after_linking_280(Main *bmain) /* Add fake user for all existing groups. */ id_fake_user_set(&collection->id); - if (collection->flag & (COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER)) { + if (collection->flag & (COLLECTION_RESTRICT_VIEWPORT | COLLECTION_RESTRICT_RENDER)) { continue; } @@ -731,7 +754,8 @@ void do_versions_after_linking_280(Main *bmain) char name[MAX_ID_NAME]; BLI_snprintf(name, sizeof(name), DATA_("Hidden %d"), coll_idx + 1); *collection_hidden = BKE_collection_add(bmain, collection, name); - (*collection_hidden)->flag |= COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER; + (*collection_hidden)->flag |= COLLECTION_RESTRICT_VIEWPORT | + COLLECTION_RESTRICT_RENDER; } BKE_collection_object_add(bmain, *collection_hidden, ob); @@ -1290,6 +1314,16 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /* 2.79 style Maintain Volume mode. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + do_version_constraints_maintain_volume_mode_uniform(&ob->constraints); + if (ob->pose) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { + do_version_constraints_maintain_volume_mode_uniform(&pchan->constraints); + } + } + } } #ifdef USE_COLLECTION_COMPAT_28 @@ -2842,7 +2876,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } for (Material *mat = bmain->materials.first; mat; mat = mat->id.next) { - mat->blend_flag &= ~(MA_BL_FLAG_UNUSED_2); + mat->blend_flag &= ~(1 << 2); /* UNUSED */ } } @@ -3353,7 +3387,69 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 280, 61)) { + /* Added a power option to Copy Scale. */ + if (!DNA_struct_elem_find(fd->filesdna, "bSizeLikeConstraint", "float", "power")) { + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + do_version_constraints_copy_scale_power(&ob->constraints); + if (ob->pose) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { + do_version_constraints_copy_scale_power(&pchan->constraints); + } + } + } + } + + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { + if (ELEM(sl->spacetype, SPACE_CLIP, SPACE_GRAPH, SPACE_SEQ)) { + ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase; + + ARegion *ar = NULL; + if (sl->spacetype == SPACE_CLIP) { + if (((SpaceClip *)sl)->view == SC_VIEW_GRAPH) { + ar = do_versions_find_region(regionbase, RGN_TYPE_PREVIEW); + } + } + else { + ar = do_versions_find_region(regionbase, RGN_TYPE_WINDOW); + } + + if (ar != NULL) { + ar->v2d.scroll &= ~V2D_SCROLL_LEFT; + ar->v2d.scroll |= V2D_SCROLL_RIGHT; + } + } + } + } + } + + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + for (ScrArea *area = screen->areabase.first; area; area = area->next) { + for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype != SPACE_OUTLINER) { + continue; + } + SpaceOutliner *so = (SpaceOutliner *)sl; + so->filter &= ~SO_FLAG_UNUSED_1; + so->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_SELECT | SO_RESTRICT_HIDE; + } + } + } + } + { /* Versioning code until next subversion bump goes here. */ + LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) { + arm->flag &= ~(ARM_FLAG_UNUSED_7 | ARM_FLAG_UNUSED_9); + } + + /* Initializes sun lights with the new angular diameter property */ + if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "sun_angle")) { + LISTBASE_FOREACH (Light *, light, &bmain->lights) { + light->sun_angle = 2.0f * atanf(light->area_size); + } + } } } diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c index 023bd685352..7616e62af9f 100644 --- a/source/blender/blenloader/intern/versioning_cycles.c +++ b/source/blender/blenloader/intern/versioning_cycles.c @@ -38,6 +38,8 @@ #include "BKE_main.h" #include "BKE_node.h" +#include "IMB_colormanagement.h" + #include "BLO_readfile.h" #include "readfile.h" @@ -47,6 +49,12 @@ static float *cycles_node_socket_float_value(bNodeSocket *socket) return &socket_data->value; } +static float *cycles_node_socket_rgba_value(bNodeSocket *socket) +{ + bNodeSocketValueRGBA *socket_data = socket->default_value; + return socket_data->value; +} + static IDProperty *cycles_properties_from_ID(ID *id) { IDProperty *idprop = IDP_GetProperties(id, false); @@ -262,6 +270,114 @@ static void ambient_occlusion_node_relink(bNodeTree *ntree) } } +static void image_node_colorspace(bNode *node) +{ + if (node->id == NULL) { + return; + } + + int color_space; + if (node->type == SH_NODE_TEX_IMAGE) { + NodeTexImage *tex = node->storage; + color_space = tex->color_space; + } + else if (node->type == SH_NODE_TEX_ENVIRONMENT) { + NodeTexEnvironment *tex = node->storage; + color_space = tex->color_space; + } + else { + return; + } + + const int SHD_COLORSPACE_NONE = 0; + Image *image = (Image *)node->id; + if (color_space == SHD_COLORSPACE_NONE) { + STRNCPY(image->colorspace_settings.name, + IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DATA)); + } +} + +static void light_emission_node_to_energy(Light *light, float *energy, float color[3]) +{ + *energy = 1.0; + copy_v3_fl(color, 1.0f); + + /* If nodetree has animation or drivers, don't try to convert. */ + bNodeTree *ntree = light->nodetree; + if (ntree == NULL || ntree->adt) { + return; + } + + /* Find emission node */ + bNode *output_node = ntreeShaderOutputNode(ntree, SHD_OUTPUT_CYCLES); + if (output_node == NULL) { + return; + } + + bNode *emission_node = NULL; + for (bNodeLink *link = ntree->links.first; link; link = link->next) { + if (link->tonode == output_node && link->fromnode->type == SH_NODE_EMISSION) { + emission_node = link->fromnode; + break; + } + } + + if (emission_node == NULL) { + return; + } + + /* Don't convert if anything is linked */ + bNodeSocket *strength_socket = nodeFindSocket(emission_node, SOCK_IN, "Strength"); + bNodeSocket *color_socket = nodeFindSocket(emission_node, SOCK_IN, "Color"); + + if ((strength_socket->flag & SOCK_IN_USE) || (color_socket->flag & SOCK_IN_USE)) { + return; + } + + float *strength_value = cycles_node_socket_float_value(strength_socket); + float *color_value = cycles_node_socket_rgba_value(color_socket); + + *energy = *strength_value; + copy_v3_v3(color, color_value); + + *strength_value = 1.0f; + copy_v4_fl(color_value, 1.0f); + light->use_nodes = false; +} + +static void light_emission_unify(Light *light, const char *engine) +{ + if (light->type != LA_SUN) { + light->energy *= 100.0f; + } + + /* Attempt to extract constant energy and color from nodes. */ + bool use_nodes = light->use_nodes; + float energy, color[3]; + light_emission_node_to_energy(light, &energy, color); + + if (STREQ(engine, "CYCLES")) { + if (use_nodes) { + /* Energy extracted from nodes */ + light->energy = energy; + copy_v3_v3(&light->r, color); + } + else { + /* Default cycles multipliers if there are no nodes */ + if (light->type == LA_SUN) { + light->energy = 1.0f; + } + else { + light->energy = 100.0f; + } + } + } + else { + /* Disable nodes if scene was configured for Eevee */ + light->use_nodes = false; + } +} + void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain) { /* Particle shape shared with Eevee. */ @@ -326,7 +442,23 @@ void do_versions_after_linking_cycles(Main *bmain) if (!MAIN_VERSION_ATLEAST(bmain, 279, 5)) { ambient_occlusion_node_relink(ntree); } + + if (!MAIN_VERSION_ATLEAST(bmain, 280, 63)) { + for (bNode *node = ntree->nodes.first; node; node = node->next) { + image_node_colorspace(node); + } + } } FOREACH_NODETREE_END; } + + if (!MAIN_VERSION_ATLEAST(bmain, 280, 64)) { + /* Unfiy Cycles and Eevee settings. */ + Scene *scene = bmain->scenes.first; + const char *engine = (scene) ? scene->r.engine : "CYCLES"; + + for (Light *light = bmain->lights.first; light; light = light->id.next) { + light_emission_unify(light, engine); + } + } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 1da9d692440..2d6f0015634 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -281,17 +281,45 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) } for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { - /* Hide channels in timelines. */ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { - SpaceAction *saction = (sa->spacetype == SPACE_ACTION) ? sa->spacedata.first : NULL; + if (sa->spacetype == SPACE_ACTION) { + /* Show marker lines, hide channels and collapse summary in timelines. */ + SpaceAction *saction = sa->spacedata.first; + saction->flag |= SACTION_SHOW_MARKER_LINES; - if (saction && saction->mode == SACTCONT_TIMELINE) { - for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_CHANNELS) { - ar->flag |= RGN_FLAG_HIDDEN; + if (saction->mode == SACTCONT_TIMELINE) { + saction->ads.flag |= ADS_FLAG_SUMMARY_COLLAPSED; + + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_CHANNELS) { + ar->flag |= RGN_FLAG_HIDDEN; + } } } } + else if (sa->spacetype == SPACE_GRAPH) { + SpaceGraph *sipo = sa->spacedata.first; + sipo->flag |= SIPO_MARKER_LINES; + } + else if (sa->spacetype == SPACE_NLA) { + SpaceNla *snla = sa->spacedata.first; + snla->flag |= SNLA_SHOW_MARKER_LINES; + } + else if (sa->spacetype == SPACE_TEXT) { + /* Show syntax and line numbers in Script workspace text editor. */ + SpaceText *stext = sa->spacedata.first; + stext->showsyntax = true; + stext->showlinenrs = true; + } + else if (sa->spacetype == SPACE_VIEW3D) { + /* Screen space cavity by default for faster performance. */ + View3D *v3d = sa->spacedata.first; + v3d->shading.cavity_type = V3D_SHADING_CAVITY_CURVATURE; + } + else if (sa->spacetype == SPACE_CLIP) { + SpaceClip *sclip = sa->spacedata.first; + sclip->around = V3D_AROUND_CENTER_MEDIAN; + } } } diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index 46fd58e59c1..909334ae26f 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -19,7 +19,7 @@ * * Version patch user preferences. */ - +#define DNA_DEPRECATED_ALLOW #include <string.h> #include "BLI_math.h" @@ -28,6 +28,7 @@ #include "DNA_userdef_types.h" #include "DNA_curve_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_scene_types.h" #include "BKE_addon.h" #include "BKE_colorband.h" @@ -42,7 +43,7 @@ /* Disallow access to global userdef. */ #define U (_error_) -static void do_versions_theme(UserDef *userdef, bTheme *btheme) +static void do_versions_theme(const UserDef *userdef, bTheme *btheme) { #define USER_VERSION_ATLEAST(ver, subver) MAIN_VERSION_ATLEAST(userdef, ver, subver) @@ -113,13 +114,30 @@ static void do_versions_theme(UserDef *userdef, bTheme *btheme) FROM_DEFAULT_V4_UCHAR(space_info.info_info); } + if (!USER_VERSION_ATLEAST(280, 64)) { + FROM_DEFAULT_V4_UCHAR(tui.icon_scene); + + if (btheme->space_view3d.obcenter_dia == 0) { + btheme->space_view3d.obcenter_dia = U_theme_default.space_view3d.obcenter_dia; + } + + FROM_DEFAULT_V4_UCHAR(space_graph.text); + FROM_DEFAULT_V4_UCHAR(space_action.text); + FROM_DEFAULT_V4_UCHAR(space_nla.text); + FROM_DEFAULT_V4_UCHAR(space_sequencer.text); + FROM_DEFAULT_V4_UCHAR(space_clip.text); + + FROM_DEFAULT_V4_UCHAR(space_graph.scrubbing_background); + FROM_DEFAULT_V4_UCHAR(space_action.scrubbing_background); + FROM_DEFAULT_V4_UCHAR(space_nla.scrubbing_background); + FROM_DEFAULT_V4_UCHAR(space_sequencer.scrubbing_background); + FROM_DEFAULT_V4_UCHAR(space_clip.scrubbing_background); + } + /** * Include next version bump. */ { - if (btheme->space_view3d.obcenter_dia == 0) { - btheme->space_view3d.obcenter_dia = U_theme_default.space_view3d.obcenter_dia; - } } #undef FROM_DEFAULT_V4_UCHAR @@ -542,19 +560,48 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef) userdef->dupflag |= USER_DUP_GPENCIL; } - /** - * Include next version bump. - */ - { + if (!USER_VERSION_ATLEAST(280, 60)) { + const float GPU_VIEWPORT_QUALITY_FXAA = 0.10f; + const float GPU_VIEWPORT_QUALITY_TAA8 = 0.25f; + const float GPU_VIEWPORT_QUALITY_TAA16 = 0.6f; + const float GPU_VIEWPORT_QUALITY_TAA32 = 0.8f; + + if (userdef->gpu_viewport_quality <= GPU_VIEWPORT_QUALITY_FXAA) { + userdef->viewport_aa = SCE_DISPLAY_AA_OFF; + } + else if (userdef->gpu_viewport_quality <= GPU_VIEWPORT_QUALITY_TAA8) { + userdef->viewport_aa = SCE_DISPLAY_AA_FXAA; + } + else if (userdef->gpu_viewport_quality <= GPU_VIEWPORT_QUALITY_TAA16) { + userdef->viewport_aa = SCE_DISPLAY_AA_SAMPLES_8; + } + else if (userdef->gpu_viewport_quality <= GPU_VIEWPORT_QUALITY_TAA32) { + userdef->viewport_aa = SCE_DISPLAY_AA_SAMPLES_16; + } + else { + userdef->viewport_aa = SCE_DISPLAY_AA_SAMPLES_32; + } + } + + if (!USER_VERSION_ATLEAST(280, 62)) { /* (keep this block even if it becomes empty). */ if (userdef->vbotimeout == 0) { userdef->vbocollectrate = 60; userdef->vbotimeout = 120; } - if (userdef->lookdev_ball_size == 0) { - userdef->lookdev_ball_size = 150; + if (userdef->lookdev_sphere_size == 0) { + userdef->lookdev_sphere_size = 150; } + + userdef->pref_flag |= USER_PREF_FLAG_SAVE; + } + + /** + * Include next version bump. + */ + { + /* pass */ } if (userdef->pixelsize == 0.0f) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 1e2bbc138a3..5a1ce7177c2 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2417,7 +2417,7 @@ static void write_paint(WriteData *wd, Paint *p) if (p->cavity_curve) { write_curvemapping(wd, p->cavity_curve); } - writedata(wd, DATA, sizeof(PaintToolSlot) * p->tool_slots_len, p->tool_slots); + writestruct(wd, DATA, PaintToolSlot, p->tool_slots_len, p->tool_slots); } static void write_layer_collections(WriteData *wd, ListBase *lb) diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index cb10ec9d701..a35d10db697 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -1440,7 +1440,6 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops) * Note that this is On² piece of code, * but it is not designed to be used with huge selection sets, * rather with only a few items selected at most.*/ - printf("using face history selection\n"); /* Goes from last selected to the first selected element. */ for (ese = bm->selected.last; ese; ese = ese->prev) { if (ese->htype == BM_FACE) { @@ -1473,7 +1472,6 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops) else { if (sel_faces) { /* Only select all loops of selected faces. */ - printf("using face selection\n"); BMLoop *l; BMFace *f; BMIter liter, fiter; @@ -1487,7 +1485,6 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops) } if (sel_edges) { /* Only select all loops of selected edges. */ - printf("using edge selection\n"); BMLoop *l; BMEdge *e; BMIter liter, eiter; @@ -1510,7 +1507,6 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops) } if (sel_verts) { /* Select all loops of selected verts. */ - printf("using vert selection\n"); BMLoop *l; BMVert *v; BMIter liter, viter; diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index af5ce4ed9ac..a559d13fc70 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -5222,7 +5222,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) BMIter iter; EdgeHalf *e; float weight, z; - float vert_axis[3]; + float vert_axis[3] = {0, 0, 0}; int i, ccw_test_sum; int nsel = 0; int ntot = 0; @@ -5357,7 +5357,6 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) normalize_v3(edge_dir); add_v3_v3v3(vert_axis, vert_axis, edge_dir); } - mul_v3_fl(vert_axis, 1 / ntot); } } @@ -5430,8 +5429,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) case BEVEL_AMT_WIDTH: { v2 = BM_edge_other_vert(e->e, bv->v); sub_v3_v3v3(edge_dir, bv->v->co, v2->co); - normalize_v3(edge_dir); - z = fabsf(2.0f * sinf(angle_normalized_v3v3(vert_axis, edge_dir))); + z = fabsf(2.0f * sinf(angle_v3v3(vert_axis, edge_dir))); if (z < BEVEL_EPSILON) { e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel. */ } @@ -5443,8 +5441,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) case BEVEL_AMT_DEPTH: { v2 = BM_edge_other_vert(e->e, bv->v); sub_v3_v3v3(edge_dir, bv->v->co, v2->co); - normalize_v3(edge_dir); - z = fabsf(cosf(angle_normalized_v3v3(vert_axis, edge_dir))); + z = fabsf(cosf(angle_v3v3(vert_axis, edge_dir))); if (z < BEVEL_EPSILON) { e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel. */ } diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index 650e1bfcd57..b606799efde 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -61,7 +61,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) return; } - bool is_dirty = (imbuf->userflags & IB_BITMAPDIRTY) != 0; + bool is_dirty = BKE_image_is_dirty(image); ImageFormatData imageFormat; BKE_imbuf_to_image_format(&imageFormat, imbuf); diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h index 78434411a22..3030bfb28b3 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.h +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -72,10 +72,15 @@ void DEG_get_customdata_mask_for_object(const struct Depsgraph *graph, struct Object *object, struct CustomData_MeshMasks *r_mask); -/* Get scene the despgraph is created for. */ +/* Get scene at its evaluated state. + * + * Technically, this is a copied-on-written and fully evaluated version of the input scene. + * This function will check that the datablock has been expanded (and copied) from the original + * one. Assert will happen if it's not. */ struct Scene *DEG_get_evaluated_scene(const struct Depsgraph *graph); -/* Get scene layer the despgraph is created for. */ +/* Get view layer at its evaluated state. + * This is a shortcut for accessing active view layer from evaluated scene. */ struct ViewLayer *DEG_get_evaluated_view_layer(const struct Depsgraph *graph); /* Get evaluated version of object for given original one. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index b8e0ba51019..36c6d246097 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -103,7 +103,7 @@ bool DepsgraphBuilder::need_pull_base_into_graph(Base *base) bool DepsgraphBuilder::check_pchan_has_bbone(Object *object, const bPoseChannel *pchan) { BLI_assert(object->type == OB_ARMATURE); - if (pchan->bone == NULL) { + if (pchan == NULL || pchan->bone == NULL) { return false; } /* We don't really care whether segments are higher than 1 due to static user input (as in, @@ -114,7 +114,10 @@ bool DepsgraphBuilder::check_pchan_has_bbone(Object *object, const bPoseChannel } bArmature *armature = static_cast<bArmature *>(object->data); AnimatedPropertyID property_id(&armature->id, &RNA_Bone, pchan->bone, "bbone_segments"); - return cache_->isPropertyAnimated(&armature->id, property_id); + /* Check both Object and Armature animation data, because drivers modifying Armature + * state could easily be created in the Object AnimData. */ + return cache_->isPropertyAnimated(&object->id, property_id) || + cache_->isPropertyAnimated(&armature->id, property_id); } bool DepsgraphBuilder::check_pchan_has_bbone_segments(Object *object, const bPoseChannel *pchan) diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h index 224e3212d57..040bb6cfeea 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.h +++ b/source/blender/depsgraph/intern/builder/deg_builder.h @@ -23,10 +23,10 @@ #pragma once -struct bPoseChannel; struct Base; struct Main; struct Object; +struct bPoseChannel; namespace DEG { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 64ca5902136..0d10bd1d3dc 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -58,7 +58,6 @@ extern "C" { #include "DNA_lightprobe_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" -#include "DNA_sequence_types.h" #include "DNA_sound_types.h" #include "DNA_speaker_types.h" #include "DNA_texture_types.h" @@ -90,8 +89,6 @@ extern "C" { #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_rigidbody.h" -#include "BKE_scene.h" -#include "BKE_sequencer.h" #include "BKE_shader_fx.h" #include "BKE_sound.h" #include "BKE_tracking.h" @@ -466,7 +463,7 @@ void DepsgraphNodeBuilder::build_id(ID *id) void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collection, Collection *collection) { - const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEW : + const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEWPORT : COLLECTION_RESTRICT_RENDER; const bool is_collection_restricted = (collection->flag & restrict_flag); const bool is_collection_visible = !is_collection_restricted && is_parent_collection_visible_; @@ -1563,42 +1560,12 @@ void DepsgraphNodeBuilder::build_sound(bSound *sound) if (built_map_.checkIsBuiltAndTag(sound)) { return; } - add_id_node(&sound->id); - bSound *sound_cow = get_cow_datablock(sound); - add_operation_node(&sound->id, - NodeType::AUDIO, - OperationCode::SOUND_EVAL, - function_bind(BKE_sound_evaluate, _1, bmain_, sound_cow)); + /* Placeholder so we can add relations and tag ID node for update. */ + add_operation_node(&sound->id, NodeType::AUDIO, OperationCode::SOUND_EVAL); build_animdata(&sound->id); build_parameters(&sound->id); } -void DepsgraphNodeBuilder::build_sequencer(Scene *scene) -{ - if (scene->ed == NULL) { - return; - } - Scene *scene_cow = get_cow_datablock(scene_); - add_operation_node(&scene->id, - NodeType::SEQUENCER, - OperationCode::SEQUENCES_EVAL, - function_bind(BKE_scene_eval_sequencer_sequences, _1, scene_cow)); - /* Make sure data for sequences is in the graph. */ - Sequence *seq; - SEQ_BEGIN (scene->ed, seq) { - if (seq->sound != NULL) { - build_sound(seq->sound); - } - /* TODO(sergey): Movie clip, scene, camera, mask. */ - } - SEQ_END; -} - -void DepsgraphNodeBuilder::build_scene_audio(Scene *scene) -{ - add_operation_node(&scene->id, NodeType::AUDIO, OperationCode::SOUND_EVAL); -} - /* **** ID traversal callbacks functions **** */ void DepsgraphNodeBuilder::modifier_walk(void *user_data, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 9074efefe50..41314380b23 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -32,7 +32,6 @@ #include "DEG_depsgraph.h" struct Base; -struct bSound; struct CacheFile; struct Camera; struct Collection; @@ -63,6 +62,7 @@ struct bConstraint; struct bGPdata; struct bNodeTree; struct bPoseChannel; +struct bSound; struct PropertyRNA; @@ -208,8 +208,6 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { void build_lightprobe(LightProbe *probe); void build_speaker(Speaker *speaker); void build_sound(bSound *sound); - void build_sequencer(Scene *scene); - void build_scene_audio(Scene *scene); /* Per-ID information about what was already in the dependency graph. * Allows to re-use certain values, to speed up following evaluation. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index 1b9524e5832..b898b3d3519 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -60,7 +60,7 @@ namespace DEG { void DepsgraphNodeBuilder::build_layer_collections(ListBase *lb) { - const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEW : + const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEWPORT : COLLECTION_RESTRICT_RENDER; for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) { @@ -92,7 +92,6 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene, /* Get pointer to a CoW version of scene ID. */ Scene *scene_cow = get_cow_datablock(scene); /* Scene objects. */ - int select_id = 1; /* NOTE: Base is used for function bindings as-is, so need to pass CoW base, * but object is expected to be an original one. Hence we go into some * tricks here iterating over the view layer. */ @@ -108,7 +107,6 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene, build_object(base_index, base->object, linked_state, true); ++base_index; } - base->object->select_id = select_id++; } build_layer_collections(&view_layer->layer_collections); if (scene->camera != NULL) { @@ -152,11 +150,6 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene, build_collection(NULL, fls->group); } } - /* Sequencer. */ - if (linked_state == DEG_ID_LINKED_DIRECTLY) { - build_scene_audio(scene); - build_sequencer(scene); - } /* Collections. */ add_operation_node( &scene->id, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 4c4bc01a3dd..c7a728fd0d7 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -58,7 +58,6 @@ extern "C" { #include "DNA_object_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" -#include "DNA_sequence_types.h" #include "DNA_sound_types.h" #include "DNA_speaker_types.h" #include "DNA_texture_types.h" @@ -85,7 +84,6 @@ extern "C" { #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_rigidbody.h" -#include "BKE_sequencer.h" #include "BKE_shader_fx.h" #include "BKE_shrinkwrap.h" #include "BKE_sound.h" @@ -2069,6 +2067,7 @@ void DepsgraphRelationBuilder::build_camera(Camera *camera) if (built_map_.checkIsBuiltAndTag(camera)) { return; } + build_animdata(&camera->id); build_parameters(&camera->id); if (camera->dof_ob != NULL) { ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS); @@ -2083,6 +2082,7 @@ void DepsgraphRelationBuilder::build_light(Light *lamp) if (built_map_.checkIsBuiltAndTag(lamp)) { return; } + build_animdata(&lamp->id); build_parameters(&lamp->id); /* light's nodetree */ if (lamp->nodetree != NULL) { @@ -2316,35 +2316,6 @@ void DepsgraphRelationBuilder::build_sound(bSound *sound) build_parameters(&sound->id); } -void DepsgraphRelationBuilder::build_sequencer(Scene *scene) -{ - if (scene->ed == NULL) { - return; - } - /* Make sure dependencies from sequences data goes to the sequencer evaluation. */ - ComponentKey sequencer_key(&scene->id, NodeType::SEQUENCER); - Sequence *seq; - bool has_audio_strips = false; - SEQ_BEGIN (scene->ed, seq) { - if (seq->sound != NULL) { - build_sound(seq->sound); - ComponentKey sound_key(&seq->sound->id, NodeType::AUDIO); - add_relation(sound_key, sequencer_key, "Sound -> Sequencer"); - has_audio_strips = true; - } - /* TODO(sergey): Movie clip, scene, camera, mask. */ - } - SEQ_END; - if (has_audio_strips) { - ComponentKey scene_audio_key(&scene->id, NodeType::AUDIO); - add_relation(sequencer_key, scene_audio_key, "Sequencer -> Audio"); - } -} - -void DepsgraphRelationBuilder::build_scene_audio(Scene * /*scene*/) -{ -} - void DepsgraphRelationBuilder::build_copy_on_write_relations() { for (IDNode *id_node : graph_->id_nodes) { @@ -2408,10 +2379,6 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) (id_type == ID_CF && comp_node->type == NodeType::CACHE)) { rel_flag &= ~RELATION_FLAG_NO_FLUSH; } - /* TODO(sergey): Needs better solution for this. */ - if (id_type == ID_SO) { - rel_flag &= ~RELATION_FLAG_NO_FLUSH; - } /* Notes on exceptions: * - Parameters component is where drivers are living. Changing any * of the (custom) properties in the original datablock (even the diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 30fbe5bcf6b..1cf0b48128f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -41,12 +41,10 @@ #include "intern/builder/deg_builder_rna.h" #include "intern/depsgraph.h" #include "intern/node/deg_node.h" -#include "intern/node/deg_node_id.h" #include "intern/node/deg_node_component.h" #include "intern/node/deg_node_operation.h" struct Base; -struct bSound; struct CacheFile; struct Camera; struct Collection; @@ -80,6 +78,7 @@ struct bConstraint; struct bGPdata; struct bNodeTree; struct bPoseChannel; +struct bSound; struct PropertyRNA; @@ -196,9 +195,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { void build_id(ID *id); void build_layer_collections(ListBase *lb); - void build_view_layer(Scene *scene, - ViewLayer *view_layer, - eDepsNode_LinkedState_Type linked_state); + void build_view_layer(Scene *scene, ViewLayer *view_layer); void build_collection(LayerCollection *from_layer_collection, Object *object, Collection *collection); @@ -269,8 +266,6 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { void build_lightprobe(LightProbe *probe); void build_speaker(Speaker *speaker); void build_sound(bSound *sound); - void build_sequencer(Scene *scene); - void build_scene_audio(Scene *scene); void build_nested_datablock(ID *owner, ID *id); void build_nested_nodetree(ID *owner, bNodeTree *ntree); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc index fadce685d31..f8313dc854b 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc @@ -383,7 +383,13 @@ void DepsgraphRelationBuilder::build_rig(Object *object) bPoseChannel *prev, *next; BKE_pchan_bbone_handles_get(pchan, &prev, &next); if (prev) { - OperationKey prev_key(&object->id, NodeType::BONE, prev->name, OperationCode::BONE_DONE); + OperationCode opcode = OperationCode::BONE_DONE; + /* Inheriting parent roll requires access to prev handle's B-Bone properties. */ + if ((pchan->bone->flag & BONE_ADD_PARENT_END_ROLL) != 0 && + check_pchan_has_bbone_segments(object, prev)) { + opcode = OperationCode::BONE_SEGMENTS; + } + OperationKey prev_key(&object->id, NodeType::BONE, prev->name, opcode); add_relation(prev_key, bone_segments_key, "Prev Handle -> B-Bone Segments"); } if (next) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index cadb4ab3611..b5a926ad597 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -61,7 +61,7 @@ namespace DEG { void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb) { - const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEW : + const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEWPORT : COLLECTION_RESTRICT_RENDER; for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) { @@ -75,9 +75,7 @@ void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb) } } -void DepsgraphRelationBuilder::build_view_layer(Scene *scene, - ViewLayer *view_layer, - eDepsNode_LinkedState_Type linked_state) +void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_layer) { /* Setup currently building context. */ scene_ = scene; @@ -130,15 +128,10 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, build_collection(NULL, NULL, fls->group); } } - /* Sequencer. */ - if (linked_state == DEG_ID_LINKED_DIRECTLY) { - build_scene_audio(scene); - build_sequencer(scene); - } /* Build all set scenes. */ if (scene->set != NULL) { ViewLayer *set_view_layer = BKE_view_layer_default_render(scene->set); - build_view_layer(scene->set, set_view_layer, DEG_ID_LINKED_VIA_SET); + build_view_layer(scene->set, set_view_layer); } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index ea5f86a31a8..fa38dce1a9f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -196,11 +196,30 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, /* Bone - generally, we just want the bone component. */ node_identifier.type = NodeType::BONE; node_identifier.component_name = pchan->name; - /* But B-Bone properties should connect to the actual operation. */ - Object *object = reinterpret_cast<Object *>(node_identifier.id); - if (!ELEM(NULL, pchan->bone, prop) && STRPREFIX(RNA_property_identifier(prop), "bbone_") && - builder_->check_pchan_has_bbone_segments(object, pchan)) { - node_identifier.operation_code = OperationCode::BONE_SEGMENTS; + /* However check property name for special handling. */ + if (prop != NULL) { + Object *object = reinterpret_cast<Object *>(node_identifier.id); + const char *prop_name = RNA_property_identifier(prop); + /* B-Bone properties should connect to the final operation. */ + if (STRPREFIX(prop_name, "bbone_")) { + if (builder_->check_pchan_has_bbone_segments(object, pchan)) { + node_identifier.operation_code = OperationCode::BONE_SEGMENTS; + } + else { + node_identifier.operation_code = OperationCode::BONE_DONE; + } + } + /* Final transform properties go to the Done node for the exit. */ + else if (STREQ(prop_name, "head") || STREQ(prop_name, "tail") || + STRPREFIX(prop_name, "matrix")) { + if (source == RNAPointerSource::EXIT) { + node_identifier.operation_code = OperationCode::BONE_DONE; + } + } + /* And other properties can always go to the entry operation. */ + else { + node_identifier.operation_code = OperationCode::BONE_LOCAL; + } } } return node_identifier; diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index a4082c24dec..dd2979160cd 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -249,7 +249,7 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph, * order. */ DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache); relation_builder.begin_build(); - relation_builder.build_view_layer(scene, view_layer, DEG::DEG_ID_LINKED_DIRECTLY); + relation_builder.build_view_layer(scene, view_layer); relation_builder.build_copy_on_write_relations(); /* Detect and solve cycles. */ DEG::deg_graph_detect_cycles(deg_graph); diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index d3bf27747c0..4bc2ab557ec 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -145,7 +145,6 @@ bool deg_objects_dupli_iterator_next(BLI_Iterator *iter) Object *dupli_parent = data->dupli_parent; Object *temp_dupli_object = &data->temp_dupli_object; *temp_dupli_object = *dob->ob; - temp_dupli_object->select_id = dupli_parent->select_id; temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROM_DUPLI; temp_dupli_object->base_local_view_bits = dupli_parent->base_local_view_bits; temp_dupli_object->dt = MIN2(temp_dupli_object->dt, dupli_parent->dt); @@ -159,7 +158,13 @@ bool deg_objects_dupli_iterator_next(BLI_Iterator *iter) continue; } + /* This could be avoided by refactoring make_dupli() in order to track all negative scaling + * recursively. */ + bool is_neg_scale = is_negative_m4(dob->mat); + SET_FLAG_FROM_TEST(data->temp_dupli_object.transflag, is_neg_scale, OB_NEG_SCALE); + copy_m4_m4(data->temp_dupli_object.obmat, dob->mat); + invert_m4_m4(data->temp_dupli_object.imat, data->temp_dupli_object.obmat); iter->current = &data->temp_dupli_object; BLI_assert(DEG::deg_validate_copy_on_write_datablock(&data->temp_dupli_object.id)); return true; diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index f7d7b76cb69..7dcba8b7655 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -215,9 +215,6 @@ void depsgraph_tag_to_component_opcode(const ID *id, /* There is no such node in depsgraph, this tag is to be handled * separately. */ break; - case ID_RECALC_SEQUENCER: - *component_type = NodeType::SEQUENCER; - break; case ID_RECALC_ALL: case ID_RECALC_PSYS_ALL: BLI_assert(!"Should not happen"); @@ -248,6 +245,13 @@ void depsgraph_update_editors_tag(Main *bmain, Depsgraph *graph, ID *id) deg_editors_id_update(&update_ctx, id); } +void depsgraph_id_tag_copy_on_write(Depsgraph *graph, IDNode *id_node, eUpdateSource update_source) +{ + ComponentNode *cow_comp = id_node->find_component(NodeType::COPY_ON_WRITE); + cow_comp->tag_update(graph, update_source); + id_node->id_orig->recalc |= ID_RECALC_COPY_ON_WRITE; +} + void depsgraph_tag_component(Depsgraph *graph, IDNode *id_node, NodeType component_type, @@ -255,7 +259,13 @@ void depsgraph_tag_component(Depsgraph *graph, eUpdateSource update_source) { ComponentNode *component_node = id_node->find_component(component_type); + /* NOTE: Animation component might not be existing yet (which happens when adding new driver or + * adding a new keyframe), so the required copy-on-write tag needs to be taken care explicitly + * here. */ if (component_node == NULL) { + if (component_type == NodeType::ANIMATION) { + depsgraph_id_tag_copy_on_write(graph, id_node, update_source); + } return; } if (operation_code == OperationCode::OPERATION) { @@ -269,9 +279,7 @@ void depsgraph_tag_component(Depsgraph *graph, } /* If component depends on copy-on-write, tag it as well. */ if (component_node->need_tag_cow_before_update()) { - ComponentNode *cow_comp = id_node->find_component(NodeType::COPY_ON_WRITE); - cow_comp->tag_update(graph, update_source); - id_node->id_orig->recalc |= ID_RECALC_COPY_ON_WRITE; + depsgraph_id_tag_copy_on_write(graph, id_node, update_source); } } @@ -465,7 +473,9 @@ void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph) * Need to solve those issues carefully, for until then we evaluate * animation for datablocks which appears in the graph for the first * time. */ - flag |= ID_RECALC_ANIMATION; + if (BKE_animdata_from_id(id_node->id_orig) != NULL) { + flag |= ID_RECALC_ANIMATION; + } } /* We only tag components which needs an update. Tagging everything is * not a good idea because that might reset particles cache (or any @@ -618,8 +628,6 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag) return "POINT_CACHE"; case ID_RECALC_EDITORS: return "EDITORS"; - case ID_RECALC_SEQUENCER: - return "SEQUENCER"; case ID_RECALC_ALL: return "ALL"; } 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 bb4300e5330..2a76d5cd362 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 @@ -59,8 +59,6 @@ extern "C" { #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_scene_types.h" -#include "DNA_sequence_types.h" -#include "DNA_sound_types.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" @@ -86,8 +84,6 @@ extern "C" { #include "BKE_library_query.h" #include "BKE_modifier.h" #include "BKE_object.h" -#include "BKE_sequencer.h" -#include "BKE_sound.h" } #include "intern/depsgraph.h" @@ -428,25 +424,6 @@ void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph, * Still not an excuse to have those. */ } -void update_sequence_orig_pointers(const ListBase *sequences_orig, ListBase *sequences_cow) -{ - Sequence *sequence_orig = reinterpret_cast<Sequence *>(sequences_orig->first); - Sequence *sequence_cow = reinterpret_cast<Sequence *>(sequences_cow->first); - while (sequence_orig != NULL) { - update_sequence_orig_pointers(&sequence_orig->seqbase, &sequence_cow->seqbase); - sequence_cow->orig_sequence = sequence_orig; - sequence_cow = sequence_cow->next; - sequence_orig = sequence_orig->next; - } -} - -void update_scene_orig_pointers(const Scene *scene_orig, Scene *scene_cow) -{ - if (scene_orig->ed != NULL) { - update_sequence_orig_pointers(&scene_orig->ed->seqbase, &scene_cow->ed->seqbase); - } -} - /* Check whether given ID is expanded or still a shallow copy. */ BLI_INLINE bool check_datablock_expanded(const ID *id_cow) { @@ -731,7 +708,6 @@ void update_id_after_copy(const Depsgraph *depsgraph, scene_cow->toolsettings = scene_orig->toolsettings; scene_cow->eevee.light_cache = scene_orig->eevee.light_cache; scene_setup_view_layers_after_remap(depsgraph, id_node, reinterpret_cast<Scene *>(id_cow)); - update_scene_orig_pointers(scene_orig, scene_cow); break; } default: @@ -862,205 +838,6 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph, namespace { -/* Backup of sequencer strips runtime data. */ - -/* Backup of a single strip. */ -class SequenceBackup { - public: - SequenceBackup() - { - reset(); - } - - inline void reset() - { - scene_sound = NULL; - } - - void init_from_sequence(Sequence *sequence) - { - scene_sound = sequence->scene_sound; - - sequence->scene_sound = NULL; - } - - void restore_to_sequence(Sequence *sequence) - { - sequence->scene_sound = scene_sound; - reset(); - } - - inline bool isEmpty() const - { - return (scene_sound == NULL); - } - - void *scene_sound; -}; - -class SequencerBackup { - public: - SequencerBackup(); - - void init_from_scene(Scene *scene); - void restore_to_scene(Scene *scene); - - typedef map<Sequence *, SequenceBackup> SequencesBackupMap; - SequencesBackupMap sequences_backup; -}; - -SequencerBackup::SequencerBackup() -{ -} - -void SequencerBackup::init_from_scene(Scene *scene) -{ - Sequence *sequence; - SEQ_BEGIN (scene->ed, sequence) { - SequenceBackup sequence_backup; - sequence_backup.init_from_sequence(sequence); - if (!sequence_backup.isEmpty()) { - sequences_backup.insert(make_pair(sequence->orig_sequence, sequence_backup)); - } - } - SEQ_END; -} - -void SequencerBackup::restore_to_scene(Scene *scene) -{ - Sequence *sequence; - SEQ_BEGIN (scene->ed, sequence) { - SequencesBackupMap::iterator it = sequences_backup.find(sequence->orig_sequence); - if (it == sequences_backup.end()) { - continue; - } - SequenceBackup &sequence_backup = it->second; - sequence_backup.restore_to_sequence(sequence); - } - SEQ_END; - /* Cleanup audio while the scene is still known. */ - for (SequencesBackupMap::value_type &it : sequences_backup) { - SequenceBackup &sequence_backup = it.second; - if (sequence_backup.scene_sound != NULL) { - BKE_sound_remove_scene_sound(scene, sequence_backup.scene_sound); - } - } -} - -/* Backup of scene runtime data. */ - -class SceneBackup { - public: - SceneBackup(); - - void reset(); - - void init_from_scene(Scene *scene); - void restore_to_scene(Scene *scene); - - /* Sound/audio related pointers of the scene itself. - * - * NOTE: Scene can not disappear after relations update, because otherwise the entire dependency - * graph will be gone. This means we don't need to compare original scene pointer, or worry about - * freeing those if they cant' be restorted: we just copy them over to a new scene. */ - void *sound_scene; - void *playback_handle; - void *sound_scrub_handle; - void *speaker_handles; - - SequencerBackup sequencer_backup; -}; - -SceneBackup::SceneBackup() -{ - reset(); -} - -void SceneBackup::reset() -{ - sound_scene = NULL; - playback_handle = NULL; - sound_scrub_handle = NULL; - speaker_handles = NULL; -} - -void SceneBackup::init_from_scene(Scene *scene) -{ - sound_scene = scene->sound_scene; - playback_handle = scene->playback_handle; - sound_scrub_handle = scene->sound_scrub_handle; - speaker_handles = scene->speaker_handles; - - /* Clear pointers stored in the scene, so they are not freed when copied-on-written datablock - * is freed for re-allocation. */ - scene->sound_scene = NULL; - scene->playback_handle = NULL; - scene->sound_scrub_handle = NULL; - scene->speaker_handles = NULL; - - sequencer_backup.init_from_scene(scene); -} - -void SceneBackup::restore_to_scene(Scene *scene) -{ - scene->sound_scene = sound_scene; - scene->playback_handle = playback_handle; - scene->sound_scrub_handle = sound_scrub_handle; - scene->speaker_handles = speaker_handles; - - sequencer_backup.restore_to_scene(scene); - - reset(); -} - -/* Backup of sound datablocks runtime data. */ - -class SoundBackup { - public: - SoundBackup(); - - void reset(); - - void init_from_sound(bSound *sound); - void restore_to_sound(bSound *sound); - - void *cache; - void *waveform; - void *playback_handle; -}; - -SoundBackup::SoundBackup() -{ - reset(); -} - -void SoundBackup::reset() -{ - cache = NULL; - waveform = NULL; - playback_handle = NULL; -} - -void SoundBackup::init_from_sound(bSound *sound) -{ - cache = sound->cache; - waveform = sound->waveform; - playback_handle = sound->playback_handle; - - sound->cache = NULL; - sound->waveform = NULL; - sound->playback_handle = NULL; -} - -void SoundBackup::restore_to_sound(bSound *sound) -{ - sound->cache = cache; - sound->waveform = waveform; - sound->playback_handle = playback_handle; - - reset(); -} - /* Identifier used to match modifiers to backup/restore their runtime data. * Identification is happening using original modifier data pointer and the * modifier type. @@ -1101,8 +878,7 @@ typedef map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup; /* Storage for backed up pose channel runtime data. */ typedef map<bPoseChannel *, bPoseChannel_Runtime> PoseChannelRuntimeDataBackup; -class ObjectRuntimeBackup { - public: +struct ObjectRuntimeBackup { ObjectRuntimeBackup() : base_flag(0), base_local_view_bits(0) { /* TODO(sergey): Use something like BKE_object_runtime_reset(). */ @@ -1280,8 +1056,6 @@ class RuntimeBackup { /* Restore fields to the given ID. */ void restore_to_id(ID *id); - SceneBackup scene_backup; - SoundBackup sound_backup; ObjectRuntimeBackup object_backup; DrawDataList drawdata_backup; DrawDataList *drawdata_ptr; @@ -1297,12 +1071,6 @@ void RuntimeBackup::init_from_id(ID *id) case ID_OB: object_backup.init_from_object(reinterpret_cast<Object *>(id)); break; - case ID_SCE: - scene_backup.init_from_scene(reinterpret_cast<Scene *>(id)); - break; - case ID_SO: - sound_backup.init_from_sound(reinterpret_cast<bSound *>(id)); - break; default: break; } @@ -1322,12 +1090,6 @@ void RuntimeBackup::restore_to_id(ID *id) case ID_OB: object_backup.restore_to_object(reinterpret_cast<Object *>(id)); break; - case ID_SCE: - scene_backup.restore_to_scene(reinterpret_cast<Scene *>(id)); - break; - case ID_SO: - sound_backup.restore_to_sound(reinterpret_cast<bSound *>(id)); - break; default: break; } @@ -1516,7 +1278,9 @@ bool deg_copy_on_write_is_expanded(const ID *id_cow) bool deg_copy_on_write_is_needed(const ID *id_orig) { const ID_Type id_type = GS(id_orig->name); - return !ELEM(id_type, ID_IM); + /* TODO(sergey): Make Sound copyable. It is here only because the code for dependency graph is + * being work in progress. */ + return !ELEM(id_type, ID_IM, ID_SO); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc index 09a761d282f..62a61675bcc 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc @@ -185,9 +185,6 @@ const char *operationCodeAsString(OperationCode opcode) /* Generic datablock. */ case OperationCode::GENERIC_DATABLOCK_UPDATE: return "GENERIC_DATABLOCK_UPDATE"; - /* Sequencer. */ - case OperationCode::SEQUENCES_EVAL: - return "SEQUENCES_EVAL"; /* instancing/duplication. */ case OperationCode::DUPLI: return "DUPLI"; diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h index 8fc565cfa77..ab6242a6196 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.h +++ b/source/blender/depsgraph/intern/node/deg_node_operation.h @@ -185,16 +185,12 @@ enum class OperationCode { /* Images. -------------------------------------------------------------- */ IMAGE_ANIMATION, - /* Synchronization. ----------------------------------------------------- */ + /* Synchronization clips. ----------------------------------------------- */ SYNCHRONIZE_TO_ORIGINAL, /* Generic datablock ---------------------------------------------------- */ GENERIC_DATABLOCK_UPDATE, - /* Sequencer. ----------------------------------------------------------- */ - - SEQUENCES_EVAL, - /* Duplication/instancing system. --------------------------------------- */ DUPLI, }; diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index f07568965bb..3cdf07fd7ff 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -138,6 +138,7 @@ set(SRC intern/DRW_render.h intern/draw_cache.h intern/draw_cache_impl.h + intern/draw_cache_inline.h intern/draw_common.h intern/draw_debug.h intern/draw_hair_private.h diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index da1f5c7863a..5919e100ddd 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -38,6 +38,7 @@ struct IDProperty; struct Main; struct Material; struct Object; +struct RegionView3D; struct RenderEngine; struct RenderEngineType; struct Scene; @@ -135,6 +136,15 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, void DRW_draw_depth_object(struct ARegion *ar, struct GPUViewport *viewport, struct Object *object); +void DRW_draw_select_id_object(struct Scene *scene, + struct RegionView3D *rv3d, + struct Object *ob, + short select_mode, + bool draw_facedot, + uint initial_offset, + uint *r_vert_offset, + uint *r_edge_offset, + uint *r_face_offset); void DRW_framebuffer_select_id_setup(struct ARegion *ar, const bool clear); void DRW_framebuffer_select_id_release(struct ARegion *ar); @@ -146,7 +156,6 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph void DRW_gpencil_freecache(struct Object *ob); /* This is here because GPUViewport needs it */ -void DRW_pass_free(struct DRWPass *pass); struct DRWInstanceDataList *DRW_instance_data_list_create(void); void DRW_instance_data_list_free(struct DRWInstanceDataList *idatalist); diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c index 05ee485e053..360d1d30736 100644 --- a/source/blender/draw/engines/basic/basic_engine.c +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -143,7 +143,7 @@ static void basic_cache_populate(void *vedata, Object *ob) const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; if (draw_as == PART_DRAW_PATH) { struct GPUBatch *hairs = DRW_cache_particles_get_hair(ob, psys, NULL); - DRW_shgroup_call_add(stl->g_data->depth_shgrp, hairs, NULL); + DRW_shgroup_call(stl->g_data->depth_shgrp, hairs, NULL); } } } @@ -159,7 +159,7 @@ static void basic_cache_populate(void *vedata, Object *ob) if (is_flat_object_viewed_from_side) { /* Avoid losing flat objects when in ortho views (see T56549) */ struct GPUBatch *geom = DRW_cache_object_all_edges_get(ob); - DRW_shgroup_call_object_add(stl->g_data->depth_shgrp, geom, ob); + DRW_shgroup_call_object(stl->g_data->depth_shgrp, geom, ob); return; } } @@ -169,7 +169,7 @@ static void basic_cache_populate(void *vedata, Object *ob) const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->shading.flag & V3D_SHADING_BACKFACE_CULLING)); /* Depth Prepass */ - DRW_shgroup_call_object_add( + DRW_shgroup_call_object( (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob); } } diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c index b0013151a70..e0165ea020a 100644 --- a/source/blender/draw/engines/eevee/eevee_bloom.c +++ b/source/blender/draw/engines/eevee/eevee_bloom.c @@ -186,7 +186,7 @@ static DRWShadingGroup *eevee_create_bloom_pass(const char *name, *pass = DRW_pass_create(name, DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(sh, *pass); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); DRW_shgroup_uniform_texture_ref(grp, "sourceBuffer", &effects->unf_source_buffer); DRW_shgroup_uniform_vec2(grp, "sourceBufferTexelSize", effects->unf_source_texel_size, 1); if (upsample) { 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 8fb73bd605f..3d058f7e46e 100644 --- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c +++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c @@ -212,7 +212,7 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1); DRW_shgroup_uniform_vec2(grp, "dofParams", effects->dof_params, 1); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); psl->dof_scatter = DRW_pass_create("DoF Scatter", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE_FULL); @@ -222,13 +222,14 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_ const float *viewport_size = DRW_viewport_size_get(); const int sprite_len = ((int)viewport_size[0] / 2) * ((int)viewport_size[1] / 2); /* brackets matters */ - grp = DRW_shgroup_empty_tri_batch_create( - e_data.dof_scatter_sh[use_alpha], psl->dof_scatter, sprite_len); + grp = DRW_shgroup_create(e_data.dof_scatter_sh[use_alpha], psl->dof_scatter); DRW_shgroup_uniform_texture_ref(grp, "nearBuffer", &effects->dof_down_near); DRW_shgroup_uniform_texture_ref(grp, "farBuffer", &effects->dof_down_far); DRW_shgroup_uniform_texture_ref(grp, "cocBuffer", &effects->dof_coc); DRW_shgroup_uniform_vec4(grp, "bokehParams", effects->dof_bokeh, 2); + DRW_shgroup_call_procedural_triangles(grp, sprite_len, NULL); + psl->dof_resolve = DRW_pass_create("DoF Resolve", DRW_STATE_WRITE_COLOR); grp = DRW_shgroup_create(e_data.dof_resolve_sh[use_alpha], psl->dof_resolve); @@ -237,7 +238,7 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1); DRW_shgroup_uniform_vec2(grp, "dofParams", effects->dof_params, 1); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); if (use_alpha) { DRW_shgroup_uniform_texture_ref(grp, "scatterAlphaBuffer", &effects->dof_blur_alpha); diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index a8b4159e030..c4075fc2bef 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -301,19 +301,17 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) 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); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } { - static int zero = 0; - static uint six = 6; 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); - DRW_shgroup_uniform_int(grp, "Layer", &zero, 1); - DRW_shgroup_call_instances_add(grp, quad, NULL, &six); + DRW_shgroup_uniform_int_copy(grp, "Layer", 0); + DRW_shgroup_call_instances(grp, quad, NULL, 6); } { @@ -324,7 +322,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) 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); + DRW_shgroup_call(grp, quad, NULL); /* Copy depth buffer to halfres top level of HiZ */ @@ -332,27 +330,27 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) 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); + DRW_shgroup_call(grp, quad, NULL); 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); + DRW_shgroup_call(grp, quad, NULL); 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); + DRW_shgroup_call(grp, quad, NULL); psl->maxz_copydepth_layer_ps = DRW_pass_create("HiZ Max Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_copydepth_layer_sh, psl->maxz_copydepth_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); + DRW_shgroup_call(grp, quad, NULL); } if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) { @@ -364,7 +362,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_uniform_mat4(grp, "currPersinv", effects->velocity_curr_persinv); DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } if ((effects->enabled_effects & EFFECT_ALPHA_CHECKER) != 0) { @@ -381,7 +379,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_vec4(grp, "color1", effects->color_checker_dark, 1); DRW_shgroup_uniform_vec4(grp, "color2", effects->color_checker_light, 1); DRW_shgroup_uniform_int_copy(grp, "size", 8); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } } @@ -572,7 +570,7 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) /* NOTE: Lookdev drawing happens before TAA but after * motion blur and dof to avoid distortions. * Velocity resolve use a hack to exclude lookdev - * balls from creating shimering reprojection vectors. */ + * spheres from creating shimering reprojection vectors. */ EEVEE_lookdev_draw(vedata); EEVEE_velocity_resolve(vedata); diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index a4a17de7a57..2dd5debfb83 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -249,7 +249,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); - DRW_shgroup_call_add(grp, geom, NULL); + DRW_shgroup_call(grp, geom, NULL); } { @@ -272,7 +272,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); - DRW_shgroup_call_add(grp, geom, NULL); + DRW_shgroup_call(grp, geom, NULL); } { @@ -294,7 +294,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); - DRW_shgroup_call_add(grp, geom, NULL); + DRW_shgroup_call(grp, geom, NULL); } { @@ -306,7 +306,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &light_cache->grid_tx.tex); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); - DRW_shgroup_call_add(grp, geom, NULL); + DRW_shgroup_call(grp, geom, NULL); } } @@ -360,7 +360,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_call_add(grp, geom, NULL); + DRW_shgroup_call(grp, geom, NULL); break; default: col = error_col; @@ -374,7 +374,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat grp = DRW_shgroup_create(EEVEE_shaders_probe_default_sh_get(), psl->probe_background); DRW_shgroup_uniform_vec3(grp, "color", col, 1); DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f); - DRW_shgroup_call_add(grp, geom, NULL); + DRW_shgroup_call(grp, geom, NULL); } } @@ -386,8 +386,8 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat /* Cube Display */ if (scene_eval->eevee.flag & SCE_EEVEE_SHOW_CUBEMAPS && lcache->cube_len > 1) { int cube_len = lcache->cube_len - 1; /* don't count the world. */ - DRWShadingGroup *grp = DRW_shgroup_empty_tri_batch_create( - EEVEE_shaders_probe_cube_display_sh_get(), psl->probe_display, cube_len * 2); + DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_cube_display_sh_get(), + psl->probe_display); DRW_shgroup_uniform_texture_ref(grp, "probeCubes", &lcache->cube_tx.tex); DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); @@ -398,6 +398,8 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat /* TODO (fclem) get rid of those UBO. */ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); + + DRW_shgroup_call_procedural_triangles(grp, cube_len * 2, NULL); } /* Grid Display */ @@ -423,7 +425,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); int tri_count = egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2] * 2; - DRW_shgroup_call_procedural_triangles_add(shgrp, tri_count, NULL); + DRW_shgroup_call_procedural_triangles(shgrp, tri_count, NULL); } } @@ -434,29 +436,16 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat {"probe_mat", DRW_ATTR_FLOAT, 16}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(EEVEE_shaders_probe_planar_display_sh_get(), - psl->probe_display, - DRW_cache_quad_get(), - e_data.format_probe_display_planar); - stl->g_data->planar_display_shgrp = grp; + DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_planar_display_sh_get(), + psl->probe_display); DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &txl->planar_pool); + + stl->g_data->planar_display_shgrp = DRW_shgroup_call_buffer_instance( + grp, e_data.format_probe_display_planar, DRW_cache_quad_get()); } else { stl->g_data->planar_display_shgrp = NULL; } - - { - psl->probe_planar_downsample_ps = DRW_pass_create("LightProbe Planar Downsample", - DRW_STATE_WRITE_COLOR); - - DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_planar_downsample_sh_get(), - psl->probe_planar_downsample_ps); - - DRW_shgroup_uniform_texture_ref(grp, "source", &txl->planar_pool); - DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1); - DRW_shgroup_call_instances_add( - grp, DRW_cache_fullscreen_quad_get(), NULL, (uint *)&pinfo->num_planar); - } } static bool eevee_lightprobes_culling_test(Object *ob) @@ -510,9 +499,9 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata EEVEE_lightprobes_planar_data_from_object( ob, &pinfo->planar_data[pinfo->num_planar], &pinfo->planar_vis_tests[pinfo->num_planar]); /* Debug Display */ - DRWShadingGroup *grp = vedata->stl->g_data->planar_display_shgrp; + DRWCallBuffer *grp = vedata->stl->g_data->planar_display_shgrp; if (grp && (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) { - DRW_shgroup_call_dynamic_add(grp, &pinfo->num_planar, ob->obmat); + DRW_buffer_add_entry(grp, &pinfo->num_planar, ob->obmat); } pinfo->num_planar++; @@ -772,6 +761,20 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved } } } + + if (pinfo->num_planar) { + EEVEE_PassList *psl = vedata->psl; + EEVEE_TextureList *txl = vedata->txl; + psl->probe_planar_downsample_ps = DRW_pass_create("LightProbe Planar Downsample", + DRW_STATE_WRITE_COLOR); + + DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_planar_downsample_sh_get(), + psl->probe_planar_downsample_ps); + + DRW_shgroup_uniform_texture_ref(grp, "source", &txl->planar_pool); + DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1); + DRW_shgroup_call_procedural_triangles(grp, pinfo->num_planar, NULL); + } } /* -------------------------------------------------------------------- */ diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 270defb039b..f64cd340ab2 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -53,6 +53,8 @@ extern char datatoc_shadow_store_frag_glsl[]; extern char datatoc_shadow_copy_frag_glsl[]; extern char datatoc_concentric_samples_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; + /* Prototypes */ static void eevee_light_setup(Object *ob, EEVEE_Light *evli); static float light_attenuation_radius_get(Light *la, float light_threshold); @@ -111,8 +113,11 @@ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata) const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); if (!e_data.shadow_sh) { - e_data.shadow_sh = DRW_shader_create( - datatoc_shadow_vert_glsl, NULL, datatoc_shadow_frag_glsl, NULL); + e_data.shadow_sh = DRW_shader_create_with_lib(datatoc_shadow_vert_glsl, + NULL, + datatoc_shadow_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); } if (!sldata->lights) { @@ -258,7 +263,7 @@ static DRWPass *eevee_lights_cube_store_pass_get(EEVEE_PassList *psl, DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cube_blur); DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } return *pass; } @@ -280,7 +285,7 @@ static DRWPass *eevee_lights_cascade_store_pass_get(EEVEE_PassList *psl, DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1); DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } return *pass; } @@ -322,7 +327,7 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1); DRW_shgroup_uniform_int(grp, "faceId", &linfo->current_shadow_face, 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } { @@ -335,7 +340,7 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo); DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1); DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } { @@ -449,7 +454,7 @@ void EEVEE_lights_cache_shcaster_add(EEVEE_ViewLayerData *UNUSED(sldata), struct GPUBatch *geom, Object *ob) { - DRW_shgroup_call_object_add(stl->g_data->shadow_shgrp, geom, ob); + DRW_shgroup_call_object(stl->g_data->shadow_shgrp, geom, ob); } void EEVEE_lights_cache_shcaster_material_add(EEVEE_ViewLayerData *sldata, @@ -479,7 +484,7 @@ void EEVEE_lights_cache_shcaster_material_add(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1); } - DRW_shgroup_call_object_add(grp, geom, ob); + DRW_shgroup_call_object(grp, geom, ob); } /* Make that object update shadow casting lights inside its influence bounding box. */ @@ -640,7 +645,7 @@ float light_attenuation_radius_get(Light *la, float light_threshold) /* Compute max light power. */ float power = max_fff(la->r, la->g, la->b); - power *= fabsf(la->energy); + power *= fabsf(la->energy / 100.0f); power *= max_ff(1.0f, la->spec_fac); /* Compute the distance (using the inverse square law) * at which the light power reaches the light_threshold. */ @@ -667,6 +672,9 @@ static void light_shape_parameters_set(EEVEE_Light *evli, const Light *la, float evli->sizey = max_ff(0.003f, la->area_size * scale[1] * 0.5f); } } + else if (la->type == LA_SUN) { + evli->radius = max_ff(0.001f, tanf(la->sun_angle / 2.0f)); + } else { evli->radius = max_ff(0.001f, la->area_size); } @@ -678,7 +686,7 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli) /* 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 */ + 0.8f; /* XXX : Empirical, Fit cycles power */ if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { /* Scale power to account for the lower area of the ellipse compared to the surrounding * rectangle. */ @@ -686,8 +694,7 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli) } } 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²) */ - M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */ + power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI); /* 1/(4*r²*Pi²) */ /* for point lights (a.k.a radius == 0.0) */ // power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */ diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index 13f7ab1c562..bd786c06e69 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -72,21 +72,21 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, Scene *scene = draw_ctx->scene; if (LOOK_DEV_OVERLAY_ENABLED(v3d)) { - /* Viewport / Ball size. */ + /* Viewport / Spheres size. */ rcti rect; ED_region_visible_rect(draw_ctx->ar, &rect); - /* Make the viewport width scale the lookdev balls a bit. + /* Make the viewport width scale the lookdev spheres a bit. * Scale between 1000px and 2000px. */ const float viewport_scale = clamp_f( BLI_rcti_size_x(&rect) / (2000.0f * U.dpi_fac), 0.5f, 1.0f); - const int ball_size = U.lookdev_ball_size * U.dpi_fac * viewport_scale; + const int sphere_size = U.lookdev_sphere_size * U.dpi_fac * viewport_scale; - if (ball_size != effects->ball_size || rect.xmax != effects->anchor[0] || + if (sphere_size != effects->sphere_size || rect.xmax != effects->anchor[0] || rect.ymin != effects->anchor[1]) { - /* If ball size or anchor point moves, reset TAA to avoid ghosting issue. + /* If sphere size or anchor point moves, reset TAA to avoid ghosting issue. * This needs to happen early because we are changing taa_current_sample. */ - effects->ball_size = ball_size; + effects->sphere_size = sphere_size; effects->anchor[0] = rect.xmax; effects->anchor[1] = rect.ymin; EEVEE_temporal_sampling_reset(vedata); @@ -151,7 +151,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, DRW_shgroup_uniform_mat3(*grp, "StudioLightMatrix", stl->g_data->studiolight_matrix); DRW_shgroup_uniform_float_copy(*grp, "backgroundAlpha", background_alpha); DRW_shgroup_uniform_vec3(*grp, "color", background_color, 1); - DRW_shgroup_call_add(*grp, geom, NULL); + DRW_shgroup_call(*grp, geom, NULL); if (!pinfo) { /* Do not fadeout when doing probe rendering, only when drawing the background */ DRW_shgroup_uniform_float( @@ -184,7 +184,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, } static void eevee_lookdev_apply_taa(const EEVEE_EffectsInfo *effects, - int ball_size, + int sphere_size, float winmat[4][4]) { if (DRW_state_is_image_render() || ((effects->enabled_effects & EFFECT_TAA) != 0)) { @@ -195,8 +195,8 @@ static void eevee_lookdev_apply_taa(const EEVEE_EffectsInfo *effects, BLI_halton_2d(ht_primes, ht_offset, effects->taa_current_sample, ht_point); EEVEE_temporal_sampling_offset_calc(ht_point, 1.5f, ofs); - winmat[3][0] += ofs[0] / ball_size; - winmat[3][1] += ofs[1] / ball_size; + winmat[3][0] += ofs[0] / sphere_size; + winmat[3][1] += ofs[1] / sphere_size; } } @@ -226,7 +226,7 @@ void EEVEE_lookdev_draw(EEVEE_Data *vedata) DRWMatrixState matstate; unit_m4(matstate.winmat); - eevee_lookdev_apply_taa(effects, effects->ball_size, matstate.winmat); + eevee_lookdev_apply_taa(effects, effects->sphere_size, matstate.winmat); /* "Remove" view matrix location. Leaving only rotation. */ DRW_viewport_matrix_get(matstate.viewmat, DRW_MAT_VIEW); @@ -246,25 +246,25 @@ void EEVEE_lookdev_draw(EEVEE_Data *vedata) GPU_framebuffer_bind(fb); - const int ball_margin = effects->ball_size / 6.0f; - float offset[2] = {0.0f, ball_margin}; + const int sphere_margin = effects->sphere_size / 6.0f; + float offset[2] = {0.0f, sphere_margin}; - offset[0] = effects->ball_size + ball_margin; + offset[0] = effects->sphere_size + sphere_margin; GPU_framebuffer_viewport_set(fb, effects->anchor[0] - offset[0], effects->anchor[1] + offset[1], - effects->ball_size, - effects->ball_size); + effects->sphere_size, + effects->sphere_size); DRW_draw_pass(psl->lookdev_diffuse_pass); - offset[0] = (effects->ball_size + ball_margin) + - (ball_margin + effects->ball_size + ball_margin); + offset[0] = (effects->sphere_size + sphere_margin) + + (sphere_margin + effects->sphere_size + sphere_margin); GPU_framebuffer_viewport_set(fb, effects->anchor[0] - offset[0], effects->anchor[1] + offset[1], - effects->ball_size, - effects->ball_size); + effects->sphere_size, + effects->sphere_size); DRW_draw_pass(psl->lookdev_glossy_pass); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index c55f3f0150c..c6b228c29d3 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -48,6 +48,7 @@ static struct { char *frag_shader_lib; char *vert_shader_str; + char *vert_shadow_shader_str; char *volume_shader_lib; struct GPUShader *default_prepass_sh; @@ -133,7 +134,7 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h)) DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); - DRW_shgroup_call_add(grp, geom, NULL); + DRW_shgroup_call(grp, geom, NULL); float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut"); @@ -196,7 +197,7 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h) DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); - DRW_shgroup_call_add(grp, geom, NULL); + DRW_shgroup_call(grp, geom, NULL); float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut"); @@ -609,18 +610,20 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, e_data.vert_shader_str = BLI_string_joinN( datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl); + e_data.vert_shadow_shader_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl); + e_data.default_background = DRW_shader_create( datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, NULL); - e_data.default_prepass_sh = DRW_shader_create( - datatoc_prepass_vert_glsl, NULL, datatoc_prepass_frag_glsl, NULL); - - e_data.default_prepass_clip_sh = DRW_shader_create( - datatoc_prepass_vert_glsl, NULL, datatoc_prepass_frag_glsl, "#define CLIP_PLANES\n"); - char *vert_str = BLI_string_joinN( datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_prepass_vert_glsl); + e_data.default_prepass_sh = DRW_shader_create(vert_str, NULL, datatoc_prepass_frag_glsl, NULL); + + e_data.default_prepass_clip_sh = DRW_shader_create( + vert_str, NULL, datatoc_prepass_frag_glsl, "#define CLIP_PLANES\n"); + e_data.default_hair_prepass_sh = DRW_shader_create( vert_str, NULL, datatoc_prepass_frag_glsl, "#define HAIR_SHADER\n"); @@ -853,7 +856,7 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, ma, engine, options, - (is_shadow) ? datatoc_shadow_vert_glsl : + (is_shadow) ? e_data.vert_shadow_shader_str : e_data.vert_shader_str, NULL, frag_str, @@ -1032,7 +1035,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_call_add(grp, geom, NULL); + DRW_shgroup_call(grp, geom, NULL); break; case GPU_MAT_QUEUED: /* TODO Bypass probe compilation. */ @@ -1051,7 +1054,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) grp = DRW_shgroup_create(e_data.default_background, psl->background_pass); DRW_shgroup_uniform_vec3(grp, "color", col, 1); DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); - DRW_shgroup_call_add(grp, geom, NULL); + DRW_shgroup_call(grp, geom, NULL); } } @@ -1140,7 +1143,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRWShadingGroup *grp = DRW_shgroup_create(e_data.update_noise_sh, psl->update_noise_pass); DRW_shgroup_uniform_texture(grp, "blueNoise", e_data.noise_tex); DRW_shgroup_uniform_vec3(grp, "offsets", e_data.noise_offsets, 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } if (LOOK_DEV_OVERLAY_ENABLED(draw_ctx->v3d)) { @@ -1165,7 +1168,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_float_copy(shgrp, "metallic", 0.0f); DRW_shgroup_uniform_float_copy(shgrp, "specular", 0.5f); DRW_shgroup_uniform_float_copy(shgrp, "roughness", 1.0f); - DRW_shgroup_call_add(shgrp, sphere, NULL); + DRW_shgroup_call(shgrp, sphere, NULL); psl->lookdev_glossy_pass = DRW_pass_create("LookDev Glossy Pass", state); shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_glossy_pass); @@ -1173,25 +1176,25 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_vec3(shgrp, "basecol", color_chrome, 1); DRW_shgroup_uniform_float_copy(shgrp, "metallic", 1.0f); DRW_shgroup_uniform_float_copy(shgrp, "roughness", 0.0f); - DRW_shgroup_call_add(shgrp, sphere, NULL); + DRW_shgroup_call(shgrp, sphere, NULL); } } -#define ADD_SHGROUP_CALL(shgrp, ob, ma, geom, oedata) \ +#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \ do { \ if (oedata) { \ - DRW_shgroup_call_object_add_with_callback( \ - shgrp, geom, ob, ma, EEVEE_lightprobes_obj_visibility_cb, oedata); \ + DRW_shgroup_call_object_with_callback( \ + shgrp, geom, ob, EEVEE_lightprobes_obj_visibility_cb, oedata); \ } \ else { \ - DRW_shgroup_call_object_add_ex(shgrp, geom, ob, ma, false); \ + DRW_shgroup_call_object_ex(shgrp, geom, ob, false); \ } \ } while (0) -#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, ma, geom, oedata) \ +#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) \ do { \ if (shgrp) { \ - ADD_SHGROUP_CALL(shgrp, ob, ma, geom, oedata); \ + ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \ } \ } while (0) @@ -1205,7 +1208,6 @@ static void material_opaque(Material *ma, GHash *material_hash, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - bool do_cull, struct GPUMaterial **gpumat, struct GPUMaterial **gpumat_depth, struct DRWShadingGroup **shgrp, @@ -1225,6 +1227,7 @@ static void material_opaque(Material *ma, float *spec_p = &ma->spec; float *rough_p = &ma->roughness; + const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0; const bool use_gpumat = (ma->use_nodes && ma->nodetree); const bool use_ssrefract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && ((effects->enabled_effects & EFFECT_REFRACT) != 0); @@ -1457,7 +1460,6 @@ static void material_opaque(Material *ma, static void material_transparent(Material *ma, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - bool do_cull, struct GPUMaterial **gpumat, struct DRWShadingGroup **shgrp, struct DRWShadingGroup **shgrp_depth) @@ -1468,6 +1470,7 @@ static void material_transparent(Material *ma, EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; EEVEE_LightsInfo *linfo = sldata->lights; + const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0; const bool use_ssrefract = (((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0)); float *color_p = &ma->r; @@ -1601,8 +1604,6 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, Scene *scene = draw_ctx->scene; GHash *material_hash = stl->g_data->material_hash; - const bool do_cull = (draw_ctx->v3d && - (draw_ctx->v3d->shading.flag & V3D_SHADING_BACKFACE_CULLING)); bool is_sculpt_mode = DRW_object_use_pbvh_drawing(ob); /* For now just force fully shaded with eevee when supported. */ is_sculpt_mode = is_sculpt_mode && @@ -1638,7 +1639,6 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, material_hash, sldata, vedata, - do_cull, &gpumat_array[i], &gpumat_depth_array[i], &shgrp_array[i], @@ -1651,7 +1651,6 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, material_transparent(ma_array[i], sldata, vedata, - do_cull, &gpumat_array[i], &shgrp_array[i], &shgrp_depth_array[i]); @@ -1686,10 +1685,11 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, } if (is_sculpt_mode) { - /* TODO(fclem): Support Vcol. */ - DRW_shgroup_call_sculpt_with_materials_add(shgrp_array, ma_array, ob, false); - DRW_shgroup_call_sculpt_with_materials_add(shgrp_depth_array, ma_array, ob, false); - DRW_shgroup_call_sculpt_with_materials_add(shgrp_depth_clip_array, ma_array, ob, false); + /* Vcol is not supported in the modes that require PBVH drawing. */ + bool use_vcol = false; + DRW_shgroup_call_sculpt_with_materials(shgrp_array, ob, use_vcol); + DRW_shgroup_call_sculpt_with_materials(shgrp_depth_array, ob, use_vcol); + DRW_shgroup_call_sculpt_with_materials(shgrp_depth_clip_array, ob, use_vcol); /* TODO(fclem): Support shadows in sculpt mode. */ } else if (mat_geom) { @@ -1714,9 +1714,9 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, oedata->test_data = &sldata->probes->vis_data; } - ADD_SHGROUP_CALL(shgrp_array[i], ob, ma_array[i], mat_geom[i], oedata); - ADD_SHGROUP_CALL_SAFE(shgrp_depth_array[i], ob, ma_array[i], mat_geom[i], oedata); - ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, ma_array[i], mat_geom[i], oedata); + ADD_SHGROUP_CALL(shgrp_array[i], ob, mat_geom[i], oedata); + ADD_SHGROUP_CALL_SAFE(shgrp_depth_array[i], ob, mat_geom[i], oedata); + ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, mat_geom[i], oedata); char *name = auto_layer_names; for (int j = 0; j < auto_layer_count; ++j) { @@ -1895,6 +1895,7 @@ void EEVEE_materials_free(void) } MEM_SAFE_FREE(e_data.frag_shader_lib); MEM_SAFE_FREE(e_data.vert_shader_str); + MEM_SAFE_FREE(e_data.vert_shadow_shader_str); MEM_SAFE_FREE(e_data.volume_shader_lib); DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_sh); DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_clip_sh); diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c index 1ea1e086aea..d8127d7ea1f 100644 --- a/source/blender/draw/engines/eevee/eevee_mist.c +++ b/source/blender/draw/engines/eevee/eevee_mist.c @@ -111,7 +111,7 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_uniform_vec3(grp, "mistSettings", &g_data->mist_start, 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index f8795a7ff0e..f38252590d8 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -203,7 +203,7 @@ void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat DRW_shgroup_uniform_mat4(grp, "pastViewProjMatrix", effects->past_world_to_ndc); DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } } diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index 822df19f899..577d7125641 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -159,7 +159,7 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input); DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } else { /* Cleanup to release memory */ @@ -196,7 +196,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &effects->ao_src_depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); psl->ao_horizon_search_layer = DRW_pass_create("GTAO Horizon Search Layer", DRW_STATE_WRITE_COLOR); @@ -206,7 +206,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "depthBufferLayered", &effects->ao_src_depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); if (G.debug_value == 6) { psl->ao_horizon_debug = DRW_pass_create("GTAO Horizon Debug", DRW_STATE_WRITE_COLOR); @@ -217,7 +217,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input); DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } } } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 6112921ff39..ca9314daa95 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -606,7 +606,7 @@ typedef struct EEVEE_EffectsInfo { /* Other */ float prev_persmat[4][4]; /* Lookdev */ - int ball_size; + int sphere_size; int anchor[2]; /* Bloom */ int bloom_iteration_len; @@ -816,8 +816,7 @@ typedef struct EEVEE_PrivateData { struct DRWShadingGroup *refract_depth_shgrp_cull; struct DRWShadingGroup *refract_depth_shgrp_clip; struct DRWShadingGroup *refract_depth_shgrp_clip_cull; - struct DRWShadingGroup *cube_display_shgrp; - struct DRWShadingGroup *planar_display_shgrp; + struct DRWCallBuffer *planar_display_shgrp; struct GHash *material_hash; float background_alpha; /* TODO find a better place for this. */ /* Chosen lightcache: can come from Lookdev or the viewlayer. */ diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index 22c7dd00b97..ed69c5f4727 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -230,7 +230,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v if (!effects->reflection_trace_full) { DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1); } - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); psl->ssr_resolve = DRW_pass_create("SSR Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); grp = DRW_shgroup_create(resolve_shader, psl->ssr_resolve); @@ -253,7 +253,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons); } - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } } diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index cbe0f474ac7..592de2b2389 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -229,7 +229,7 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_stencil_mask(grp, sss_id); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); struct GPUShader *sh = (effects->sss_separate_albedo) ? e_data.sss_sh[2] : e_data.sss_sh[1]; grp = DRW_shgroup_create(sh, psl->sss_resolve_ps); @@ -239,7 +239,7 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_stencil_mask(grp, sss_id); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); if (effects->sss_separate_albedo) { DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo); @@ -253,7 +253,7 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_stencil_mask(grp, sss_id); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); if (effects->sss_separate_albedo) { DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo); diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index 194fff9b93c..1b7adba4284 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -287,7 +287,7 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data else { DRW_shgroup_uniform_float(grp, "alpha", &effects->taa_alpha, 1); } - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } } diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 76c8f010142..8867bf107ec 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -400,8 +400,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) !LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) { struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo); - grp = DRW_shgroup_material_empty_tri_batch_create( - mat, psl->volumetric_world_ps, common_data->vol_tex_size[2]); + grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps); if (grp) { DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); @@ -416,15 +415,18 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density); DRW_shgroup_uniform_texture(grp, "sampflame", e_data.dummy_flame); DRW_shgroup_uniform_vec2(grp, "unftemperature", (float[2]){0.0f, 1.0f}, 1); + + DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL); } } if (grp == NULL) { /* If no world or volume material is present just clear the buffer with this drawcall */ - grp = DRW_shgroup_empty_tri_batch_create( - e_data.volumetric_clear_sh, psl->volumetric_world_ps, common_data->vol_tex_size[2]); + grp = DRW_shgroup_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + + DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL); } /* Volumetric Objects */ @@ -435,8 +437,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) e_data.volumetric_scatter_with_lights_sh : e_data.volumetric_scatter_sh; psl->volumetric_scatter_ps = DRW_pass_create("Volumetric Scattering", DRW_STATE_WRITE_COLOR); - grp = DRW_shgroup_empty_tri_batch_create( - scatter_sh, psl->volumetric_scatter_ps, common_data->vol_tex_size[2]); + grp = DRW_shgroup_create(scatter_sh, psl->volumetric_scatter_ps); DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &lcache->grid_tx.tex); DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool); DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool); @@ -451,15 +452,17 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL); + psl->volumetric_integration_ps = DRW_pass_create("Volumetric Integration", DRW_STATE_WRITE_COLOR); - grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh, - psl->volumetric_integration_ps, - common_data->vol_tex_size[2]); + grp = DRW_shgroup_create(e_data.volumetric_integration_sh, psl->volumetric_integration_ps); DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter); DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmittance); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL); + psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR); grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps); DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter); @@ -467,7 +470,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "inSceneColor", &e_data.color_src); DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } } @@ -500,11 +503,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, return; } - DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create( - mat, vedata->psl->volumetric_objects_ps, sldata->common_data.vol_tex_size[2]); - - /* Making sure it's updated. */ - invert_m4_m4(ob->imat, ob->obmat); + DRWShadingGroup *grp = DRW_shgroup_material_create(mat, vedata->psl->volumetric_objects_ps); BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, NULL, &texcosize); @@ -578,6 +577,10 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_vec3(grp, "volumeColor", white, 1); DRW_shgroup_uniform_vec2(grp, "unftemperature", (float[2]){0.0f, 1.0f}, 1); } + + /* TODO Reduce to number of slices intersecting. */ + /* TODO Preemptive culling. */ + DRW_shgroup_call_procedural_triangles(grp, sldata->common_data.vol_tex_size[2], NULL); } void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index 3a5f20b952e..12e60f0250f 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -15,7 +15,7 @@ uniform sampler2D maxzBuffer; uniform sampler2D minzBuffer; uniform sampler2DArray planarDepth; -#define cameraForward normalize(ViewMatrixInverse[2].xyz) +#define cameraForward ViewMatrixInverse[2].xyz #define cameraPos ViewMatrixInverse[3].xyz #define cameraVec \ ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - worldPosition) : cameraForward) @@ -836,18 +836,22 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac) cl.radiance /= max(1e-8, cl.opacity); # ifdef USE_SSS - cl.sss_data.rgb = mix(cl1.sss_data.rgb, cl2.sss_data.rgb, fac); - cl.sss_data.a = (cl1.sss_data.a > 0.0) ? cl1.sss_data.a : cl2.sss_data.a; + /* Apply Mix on input */ + cl1.sss_data.rgb *= 1.0 - fac; + cl2.sss_data.rgb *= fac; + + /* Select biggest radius. */ + bool use_cl1 = (cl1.sss_data.a > cl2.sss_data.a); + cl.sss_data = (use_cl1) ? cl1.sss_data : cl2.sss_data; # ifdef USE_SSS_ALBEDO /* TODO Find a solution to this. Dither? */ - cl.sss_albedo = (cl1.sss_data.a > 0.0) ? cl1.sss_albedo : cl2.sss_albedo; + cl.sss_albedo = (use_cl1) ? cl1.sss_albedo : cl2.sss_albedo; /* Add radiance that was supposed to be filtered but was rejected. */ - cl.radiance += (cl1.sss_data.a > 0.0) ? cl2.sss_data.rgb * cl2.sss_albedo : - cl1.sss_data.rgb * cl1.sss_albedo; + cl.radiance += (use_cl1) ? cl2.sss_data.rgb * cl2.sss_albedo : cl1.sss_data.rgb * cl1.sss_albedo; # else /* Add radiance that was supposed to be filtered but was rejected. */ - cl.radiance += (cl1.sss_data.a > 0.0) ? cl2.sss_data.rgb : cl1.sss_data.rgb; + cl.radiance += (use_cl1) ? cl2.sss_data.rgb : cl1.sss_data.rgb; # endif # endif diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl index 1c943bd51bc..588cd402bb3 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl @@ -1,11 +1,12 @@ -in vec2 pos; - out int instance; out vec2 vPos; void main() { - instance = gl_InstanceID; - vPos = pos; + int v = gl_VertexID % 3; + vPos.x = -1.0 + float((v & 1) << 2); + vPos.y = -1.0 + float((v & 2) << 1); + + instance = gl_VertexID / 3; } diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl index 40075ed64be..0a2785bafca 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl @@ -1,13 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelViewMatrix; -uniform mat3 WorldNormalMatrix; -#ifndef USE_ATTR -uniform mat4 ModelMatrix; -uniform mat3 NormalMatrix; -uniform mat4 ModelMatrixInverse; -#endif - #ifndef HAIR_SHADER in vec3 pos; in vec3 nor; @@ -57,20 +48,20 @@ void main() hairThickness, hairThickTime); - gl_Position = ViewProjectionMatrix * vec4(pos, 1.0); - viewPosition = (ViewMatrix * vec4(pos, 1.0)).xyz; - worldPosition = pos; hairTangent = normalize(hairTangent); worldNormal = cross(binor, hairTangent); - viewNormal = mat3(ViewMatrix) * worldNormal; + worldPosition = pos; #else - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz; - worldPosition = (ModelMatrix * vec4(pos, 1.0)).xyz; - worldNormal = normalize(WorldNormalMatrix * nor); - viewNormal = normalize(NormalMatrix * nor); + worldPosition = point_object_to_world(pos); + worldNormal = normalize(normal_object_to_world(nor)); #endif + /* No need to normalize since this is just a rotation. */ + viewNormal = normal_world_to_view(worldNormal); + + viewPosition = point_world_to_view(worldPosition); + gl_Position = point_world_to_ndc(worldPosition); + /* Used for planar reflections */ gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), ClipPlanes[0]); diff --git a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl index 9196253478a..fe274f59167 100644 --- a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl @@ -1,8 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; -uniform mat4 ModelMatrixInverse; - #ifdef CLIP_PLANES /* keep in sync with DRWManager.view_data */ layout(std140) uniform clip_block @@ -19,25 +15,23 @@ void main() { #ifdef HAIR_SHADER float time, thick_time, thickness; - vec3 pos, tan, binor; + vec3 worldPosition, tan, binor; hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0), ModelMatrixInverse, ViewMatrixInverse[3].xyz, ViewMatrixInverse[2].xyz, - pos, + worldPosition, tan, binor, time, thickness, thick_time); - - gl_Position = ViewProjectionMatrix * vec4(pos, 1.0); - vec4 worldPosition = vec4(pos, 1.0); #else - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - vec4 worldPosition = (ModelMatrix * vec4(pos, 1.0)); + vec3 worldPosition = point_object_to_world(pos); #endif + gl_Position = point_world_to_ndc(worldPosition); + #ifdef CLIP_PLANES gl_ClipDistance[0] = dot(vec4(worldPosition.xyz, 1.0), ClipPlanes[0]); #endif diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl index f9225cd100b..7dd9af310ed 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl @@ -1,14 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; -#ifdef MESH_SHADER -uniform mat4 ModelViewMatrix; -uniform mat3 WorldNormalMatrix; -# ifndef USE_ATTR -uniform mat4 ModelMatrix; -uniform mat3 NormalMatrix; -# endif -#endif - in vec3 pos; in vec3 nor; @@ -21,12 +11,15 @@ out vec3 viewNormal; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); #ifdef MESH_SHADER - viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz; - worldPosition = (ModelMatrix * vec4(pos, 1.0)).xyz; - viewNormal = normalize(NormalMatrix * nor); - worldNormal = normalize(WorldNormalMatrix * nor); + worldPosition = world_pos; + viewPosition = point_world_to_view(worldPosition); + + worldNormal = normalize(normal_object_to_world(nor)); + /* No need to normalize since this is just a rotation. */ + viewNormal = normal_world_to_view(worldNormal); # ifdef USE_ATTR pass_attr(pos); # endif diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index ed8c609c01f..643f51facd4 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -191,7 +191,7 @@ static void external_cache_populate(void *vedata, Object *ob) struct GPUBatch *geom = DRW_cache_object_surface_get(ob); if (geom) { /* Depth Prepass */ - DRW_shgroup_call_add(stl->g_data->depth_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->depth_shgrp, geom, ob->obmat); } } } diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c index 7dabbcf4c41..7b2c0ed168e 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c @@ -133,7 +133,8 @@ static void gpencil_vbo_ensure_size(GpencilBatchCacheElem *be, int totvertex) void DRW_gpencil_get_point_geom(GpencilBatchCacheElem *be, bGPDstroke *gps, short thickness, - const float ink[4]) + const float ink[4], + const int alignment_mode) { int totvertex = gps->totpoints; if (be->vbo == NULL) { @@ -177,26 +178,34 @@ void DRW_gpencil_get_point_geom(GpencilBatchCacheElem *be, /* use previous point to determine stroke direction */ bGPDspoint *pt2 = NULL; float fpt[3]; - if (i == 0) { - if (gps->totpoints > 1) { - /* extrapolate a point before first point */ - pt2 = &gps->points[1]; - interp_v3_v3v3(fpt, &pt2->x, &pt->x, 1.5f); - GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt); + if (alignment_mode != GP_STYLE_FOLLOW_PATH) { + /* add small offset to get a vector */ + copy_v3_v3(fpt, &pt->x); + fpt[0] += 0.00001f; + fpt[1] += 0.00001f; + GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt); + } + else { + if (i == 0) { + if (gps->totpoints > 1) { + /* extrapolate a point before first point */ + pt2 = &gps->points[1]; + interp_v3_v3v3(fpt, &pt2->x, &pt->x, 1.5f); + GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt); + } + else { + /* add small offset to get a vector */ + copy_v3_v3(fpt, &pt->x); + fpt[0] += 0.00001f; + fpt[1] += 0.00001f; + GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt); + } } else { - /* add small offset to get a vector */ - copy_v3_v3(fpt, &pt->x); - fpt[0] += 0.00001f; - fpt[1] += 0.00001f; - GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt); + pt2 = &gps->points[i - 1]; + GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, &pt2->x); } } - else { - pt2 = &gps->points[i - 1]; - GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, &pt2->x); - } - be->vbo_len++; } } diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 4b6c913785d..71e83dac461 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -465,7 +465,7 @@ static DRWShadingGroup *DRW_gpencil_shgroup_fill_create(GPENCIL_e_data *e_data, BKE_image_release_ibuf(image, ibuf, NULL); } else { - GPUTexture *texture = GPU_texture_from_blender(gp_style->ima, &iuser, GL_TEXTURE_2D, true); + GPUTexture *texture = GPU_texture_from_blender(gp_style->ima, &iuser, GL_TEXTURE_2D); DRW_shgroup_uniform_texture(grp, "myTexture", texture); stl->shgroups[id].texture_clamp = gp_style->flag & GP_STYLE_COLOR_TEX_CLAMP ? 1 : 0; @@ -631,7 +631,7 @@ DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(GPENCIL_e_data *e_data, BKE_image_release_ibuf(image, ibuf, NULL); } else { - GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true); + GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D); DRW_shgroup_uniform_texture(grp, "myTexture", texture); BKE_image_release_ibuf(image, ibuf, NULL); @@ -725,8 +725,8 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create(GPENCIL_e_data *e_data, DRW_shgroup_uniform_float(grp, "mix_stroke_factor", &stl->shgroups[id].mix_stroke_factor, 1); /* lock rotation of dots and boxes */ - stl->shgroups[id].use_follow_path = (gp_style->flag & GP_STYLE_COLOR_LOCK_DOTS) ? 0 : 1; - DRW_shgroup_uniform_int(grp, "use_follow_path", &stl->shgroups[id].use_follow_path, 1); + stl->shgroups[id].alignment_mode = gp_style->alignment_mode; + DRW_shgroup_uniform_int(grp, "alignment_mode", &stl->shgroups[id].alignment_mode, 1); } else { stl->storage->obj_scale = 1.0f; @@ -758,7 +758,7 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create(GPENCIL_e_data *e_data, DRW_shgroup_uniform_float(grp, "mix_stroke_factor", &stl->storage->mix_stroke_factor, 1); /* lock rotation of dots and boxes */ - DRW_shgroup_uniform_int(grp, "use_follow_path", &stl->storage->use_follow_path, 1); + DRW_shgroup_uniform_int(grp, "alignment_mode", &stl->storage->alignment_mode, 1); } DRW_shgroup_uniform_vec4(grp, "colormix", gp_style->stroke_rgba, 1); @@ -787,7 +787,7 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create(GPENCIL_e_data *e_data, BKE_image_release_ibuf(image, ibuf, NULL); } else { - GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true); + GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D); DRW_shgroup_uniform_texture(grp, "myTexture", texture); BKE_image_release_ibuf(image, ibuf, NULL); @@ -870,6 +870,7 @@ static void gpencil_add_stroke_vertexdata(GpencilBatchCache *cache, float ink[4]; short sthickness; MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1); + const int alignment_mode = (gp_style) ? gp_style->alignment_mode : GP_STYLE_FOLLOW_PATH; /* set color using base color, tint color and opacity */ if (cache->is_dirty) { @@ -919,7 +920,7 @@ static void gpencil_add_stroke_vertexdata(GpencilBatchCache *cache, else { /* create vertex data */ const int old_len = cache->b_point.vbo_len; - DRW_gpencil_get_point_geom(&cache->b_point, gps, sthickness, ink); + DRW_gpencil_get_point_geom(&cache->b_point, gps, sthickness, ink, alignment_mode); /* add to list of groups */ if (old_len < cache->b_point.vbo_len) { @@ -1490,7 +1491,7 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, /* save gradient info */ stl->storage->gradient_f = brush->gpencil_settings->gradient_f; copy_v2_v2(stl->storage->gradient_s, brush->gpencil_settings->gradient_s); - stl->storage->use_follow_path = (gp_style->flag & GP_STYLE_COLOR_LOCK_DOTS) ? 0 : 1; + stl->storage->alignment_mode = (gp_style) ? gp_style->alignment_mode : GP_STYLE_FOLLOW_PATH; /* if only one point, don't need to draw buffer because the user has no time to see it */ if (gpd->runtime.sbuffer_size > 1) { @@ -1543,9 +1544,9 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, } /* buffer strokes, must show stroke always */ - DRW_shgroup_call_add(stl->g_data->shgrps_drawing_stroke, - e_data->batch_buffer_stroke, - stl->storage->unit_matrix); + DRW_shgroup_call(stl->g_data->shgrps_drawing_stroke, + e_data->batch_buffer_stroke, + stl->storage->unit_matrix); if ((gpd->runtime.sbuffer_size >= 3) && (gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) && @@ -1567,9 +1568,9 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, } e_data->batch_buffer_fill = DRW_gpencil_get_buffer_fill_geom(gpd); - DRW_shgroup_call_add(stl->g_data->shgrps_drawing_fill, - e_data->batch_buffer_fill, - stl->storage->unit_matrix); + DRW_shgroup_call(stl->g_data->shgrps_drawing_fill, + e_data->batch_buffer_fill, + stl->storage->unit_matrix); stl->storage->buffer_fill = true; } stl->storage->buffer_stroke = true; @@ -1599,7 +1600,7 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, e_data->batch_buffer_ctrlpoint = DRW_gpencil_get_buffer_ctrlpoint_geom(gpd); - DRW_shgroup_call_add(shgrp, e_data->batch_buffer_ctrlpoint, stl->storage->unit_matrix); + DRW_shgroup_call(shgrp, e_data->batch_buffer_ctrlpoint, stl->storage->unit_matrix); stl->storage->buffer_ctrlpoint = true; } @@ -1721,12 +1722,12 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, scale, cache_ob->shading_type); if ((do_onion) || (elm->onion == false)) { - DRW_shgroup_call_range_add(shgrp, - cache->b_stroke.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : - cache_ob->obmat, - start_stroke, - len); + DRW_shgroup_call_range(shgrp, + cache->b_stroke.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_stroke, + len); } stl->storage->shgroup_id++; start_stroke = elm->vertex_idx; @@ -1750,12 +1751,12 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, cache_ob->shading_type); if ((do_onion) || (elm->onion == false)) { - DRW_shgroup_call_range_add(shgrp, - cache->b_point.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : - cache_ob->obmat, - start_point, - len); + DRW_shgroup_call_range(shgrp, + cache->b_point.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_point, + len); } stl->storage->shgroup_id++; start_point = elm->vertex_idx; @@ -1776,12 +1777,12 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, cache_ob->shading_type); if ((do_onion) || (elm->onion == false)) { - DRW_shgroup_call_range_add(shgrp, - cache->b_fill.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : - cache_ob->obmat, - start_fill, - len); + DRW_shgroup_call_range(shgrp, + cache->b_fill.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_fill, + len); } stl->storage->shgroup_id++; start_fill = elm->vertex_idx; @@ -1791,12 +1792,12 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, if (stl->g_data->shgrps_edit_point) { const int len = elm->vertex_idx - start_edit; /* use always the same group */ - DRW_shgroup_call_range_add(stl->g_data->shgrps_edit_point, - cache->b_edit.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : - cache_ob->obmat, - start_edit, - len); + DRW_shgroup_call_range(stl->g_data->shgrps_edit_point, + cache->b_edit.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_edit, + len); start_edit = elm->vertex_idx; } @@ -1806,12 +1807,12 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data, if (stl->g_data->shgrps_edit_line) { const int len = elm->vertex_idx - start_edlin; /* use always the same group */ - DRW_shgroup_call_range_add(stl->g_data->shgrps_edit_line, - cache->b_edlin.batch, - (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : - cache_ob->obmat, - start_edlin, - len); + DRW_shgroup_call_range(stl->g_data->shgrps_edit_line, + cache->b_edlin.batch, + (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix : + cache_ob->obmat, + start_edlin, + len); start_edlin = elm->vertex_idx; } diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index ea578187765..280702020df 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -61,6 +61,8 @@ extern char datatoc_gpencil_edit_point_geom_glsl[]; extern char datatoc_gpencil_edit_point_frag_glsl[]; extern char datatoc_gpencil_blend_frag_glsl[]; +extern char datatoc_common_view_lib_glsl[]; + /* *********** STATIC *********** */ static GPENCIL_e_data e_data = {NULL}; /* Engine data */ @@ -167,31 +169,37 @@ static void GPENCIL_create_shaders(void) { /* normal fill shader */ if (!e_data.gpencil_fill_sh) { - e_data.gpencil_fill_sh = DRW_shader_create( - datatoc_gpencil_fill_vert_glsl, NULL, datatoc_gpencil_fill_frag_glsl, NULL); + e_data.gpencil_fill_sh = DRW_shader_create_with_lib(datatoc_gpencil_fill_vert_glsl, + NULL, + datatoc_gpencil_fill_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); } /* normal stroke shader using geometry to display lines (line mode) */ if (!e_data.gpencil_stroke_sh) { - e_data.gpencil_stroke_sh = DRW_shader_create(datatoc_gpencil_stroke_vert_glsl, - datatoc_gpencil_stroke_geom_glsl, - datatoc_gpencil_stroke_frag_glsl, - NULL); + e_data.gpencil_stroke_sh = DRW_shader_create_with_lib(datatoc_gpencil_stroke_vert_glsl, + datatoc_gpencil_stroke_geom_glsl, + datatoc_gpencil_stroke_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); } /* dot/rectangle mode for normal strokes using geometry */ if (!e_data.gpencil_point_sh) { - e_data.gpencil_point_sh = DRW_shader_create(datatoc_gpencil_point_vert_glsl, - datatoc_gpencil_point_geom_glsl, - datatoc_gpencil_point_frag_glsl, - NULL); + e_data.gpencil_point_sh = DRW_shader_create_with_lib(datatoc_gpencil_point_vert_glsl, + datatoc_gpencil_point_geom_glsl, + datatoc_gpencil_point_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); } /* used for edit points or strokes with one point only */ if (!e_data.gpencil_edit_point_sh) { - e_data.gpencil_edit_point_sh = DRW_shader_create(datatoc_gpencil_edit_point_vert_glsl, - datatoc_gpencil_edit_point_geom_glsl, - datatoc_gpencil_edit_point_frag_glsl, - NULL); + e_data.gpencil_edit_point_sh = DRW_shader_create_with_lib(datatoc_gpencil_edit_point_vert_glsl, + datatoc_gpencil_edit_point_geom_glsl, + datatoc_gpencil_edit_point_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); } /* used for edit lines for edit modes */ @@ -454,7 +462,7 @@ void GPENCIL_cache_init(void *vedata) DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); DRWShadingGroup *mix_shgrp = DRW_shgroup_create(e_data.gpencil_fullscreen_sh, psl->mix_pass); - DRW_shgroup_call_add(mix_shgrp, quad, NULL); + DRW_shgroup_call(mix_shgrp, quad, NULL); DRW_shgroup_uniform_texture_ref(mix_shgrp, "strokeColor", &e_data.input_color_tx); DRW_shgroup_uniform_texture_ref(mix_shgrp, "strokeDepth", &e_data.input_depth_tx); DRW_shgroup_uniform_int(mix_shgrp, "tonemapping", &stl->storage->tonemapping, 1); @@ -472,7 +480,7 @@ void GPENCIL_cache_init(void *vedata) DRW_STATE_DEPTH_LESS); DRWShadingGroup *mix_shgrp_noblend = DRW_shgroup_create(e_data.gpencil_fullscreen_sh, psl->mix_pass_noblend); - DRW_shgroup_call_add(mix_shgrp_noblend, quad, NULL); + DRW_shgroup_call(mix_shgrp_noblend, quad, NULL); DRW_shgroup_uniform_texture_ref(mix_shgrp_noblend, "strokeColor", &e_data.input_color_tx); DRW_shgroup_uniform_texture_ref(mix_shgrp_noblend, "strokeDepth", &e_data.input_depth_tx); DRW_shgroup_uniform_int(mix_shgrp_noblend, "tonemapping", &stl->storage->tonemapping, 1); @@ -490,7 +498,7 @@ void GPENCIL_cache_init(void *vedata) DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); DRWShadingGroup *background_shgrp = DRW_shgroup_create(e_data.gpencil_background_sh, psl->background_pass); - DRW_shgroup_call_add(background_shgrp, quad, NULL); + DRW_shgroup_call(background_shgrp, quad, NULL); DRW_shgroup_uniform_texture_ref(background_shgrp, "strokeColor", &e_data.background_color_tx); DRW_shgroup_uniform_texture_ref(background_shgrp, "strokeDepth", &e_data.background_depth_tx); @@ -503,7 +511,7 @@ void GPENCIL_cache_init(void *vedata) psl->paper_pass = DRW_pass_create("GPencil Paper Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); DRWShadingGroup *paper_shgrp = DRW_shgroup_create(e_data.gpencil_paper_sh, psl->paper_pass); - DRW_shgroup_call_add(paper_shgrp, quad, NULL); + DRW_shgroup_call(paper_shgrp, quad, NULL); DRW_shgroup_uniform_vec3(paper_shgrp, "color", v3d->shading.background_color, 1); DRW_shgroup_uniform_float(paper_shgrp, "opacity", &v3d->overlay.gpencil_paper_opacity, 1); } @@ -522,7 +530,7 @@ void GPENCIL_cache_init(void *vedata) DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); DRWShadingGroup *blend_shgrp = DRW_shgroup_create(e_data.gpencil_blend_fullscreen_sh, psl->blend_pass); - DRW_shgroup_call_add(blend_shgrp, quad, NULL); + DRW_shgroup_call(blend_shgrp, quad, NULL); DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeColor", &e_data.temp_color_tx_a); DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeDepth", &e_data.temp_depth_tx_a); DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendColor", &e_data.temp_color_tx_fx); @@ -674,7 +682,7 @@ void GPENCIL_cache_populate(void *vedata, Object *ob) copy_v3_v3(stl->storage->grid_matrix[3], ob->obmat[3]); } - DRW_shgroup_call_add(stl->g_data->shgrps_grid, e_data.batch_grid, stl->storage->grid_matrix); + DRW_shgroup_call(stl->g_data->shgrps_grid, e_data.batch_grid, stl->storage->grid_matrix); } } } diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 2ac1dc3211c..9ebd168bc4c 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -129,7 +129,7 @@ typedef struct GPENCIL_shgroup { int caps_mode[2]; float obj_scale; int xray_mode; - int use_follow_path; + int alignment_mode; float gradient_f; float gradient_s[2]; @@ -182,7 +182,7 @@ typedef struct GPENCIL_Storage { float gradient_f; float gradient_s[2]; - int use_follow_path; + int alignment_mode; float mix_stroke_factor; @@ -437,7 +437,8 @@ void DRW_gpencil_multisample_ensure(struct GPENCIL_Data *vedata, int rect_w, int void DRW_gpencil_get_point_geom(struct GpencilBatchCacheElem *be, struct bGPDstroke *gps, short thickness, - const float ink[4]); + const float ink[4], + const int follow_mode); void DRW_gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be, struct bGPDstroke *gps, short thickness, @@ -514,7 +515,7 @@ void GPENCIL_render_to_image(void *vedata, /* Use of multisample framebuffers. */ #define MULTISAMPLE_GP_SYNC_ENABLE(lvl, fbl) \ { \ - if ((lvl > 0) && (fbl->multisample_fb != NULL)) { \ + if ((lvl > 0) && (fbl->multisample_fb != NULL) && (DRW_state_is_fbo())) { \ DRW_stats_query_start("GP Multisample Blit"); \ GPU_framebuffer_bind(fbl->multisample_fb); \ GPU_framebuffer_clear_color_depth(fbl->multisample_fb, (const float[4]){0.0f}, 1.0f); \ @@ -525,7 +526,7 @@ void GPENCIL_render_to_image(void *vedata, #define MULTISAMPLE_GP_SYNC_DISABLE(lvl, fbl, fb, txl) \ { \ - if ((lvl > 0) && (fbl->multisample_fb != NULL)) { \ + if ((lvl > 0) && (fbl->multisample_fb != NULL) && (DRW_state_is_fbo())) { \ DRW_stats_query_start("GP Multisample Resolve"); \ GPU_framebuffer_bind(fb); \ DRW_multisamples_resolve(txl->multisample_depth, txl->multisample_color, true); \ diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index 355235618f6..ccb79ea2b93 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -210,7 +210,7 @@ static void DRW_gpencil_fx_blur(ShaderFxData *fx, GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); @@ -235,7 +235,7 @@ static void DRW_gpencil_fx_colorize(ShaderFxData *fx, GPENCIL_e_data *e_data, GP GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_colorize_sh, psl->fx_shader_pass); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); DRW_shgroup_uniform_vec4(fx_shgrp, "low_color", &fxd->low_color[0], 1); @@ -267,7 +267,7 @@ static void DRW_gpencil_fx_flip(ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCI GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_flip_sh, psl->fx_shader_pass); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); DRW_shgroup_uniform_int(fx_shgrp, "flipmode", &fxd->flipmode, 1); @@ -297,7 +297,7 @@ static void DRW_gpencil_fx_light(ShaderFxData *fx, GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_light_sh, psl->fx_shader_pass); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); @@ -352,7 +352,7 @@ static void DRW_gpencil_fx_pixel(ShaderFxData *fx, GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_pixel_sh, psl->fx_shader_pass); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); DRW_shgroup_uniform_int(fx_shgrp, "size", &fxd->size[0], 3); @@ -386,7 +386,7 @@ static void DRW_gpencil_fx_rim(ShaderFxData *fx, /* prepare pass */ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_rim_prepare_sh, psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); @@ -403,7 +403,7 @@ static void DRW_gpencil_fx_rim(ShaderFxData *fx, /* blur pass */ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx); DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); @@ -417,7 +417,7 @@ static void DRW_gpencil_fx_rim(ShaderFxData *fx, /* resolve pass */ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_rim_resolve_sh, psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeRim", &e_data->temp_color_tx_fx); @@ -453,7 +453,7 @@ static void DRW_gpencil_fx_shadow(ShaderFxData *fx, GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); /* prepare pass */ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_shadow_prepare_sh, psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); @@ -488,7 +488,7 @@ static void DRW_gpencil_fx_shadow(ShaderFxData *fx, /* blur pass */ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx); DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); @@ -502,7 +502,7 @@ static void DRW_gpencil_fx_shadow(ShaderFxData *fx, /* resolve pass */ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_shadow_resolve_sh, psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "shadowColor", &e_data->temp_color_tx_fx); @@ -531,7 +531,7 @@ static void DRW_gpencil_fx_glow(ShaderFxData *fx, GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); /* prepare pass */ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_glow_prepare_sh, psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); @@ -544,7 +544,7 @@ static void DRW_gpencil_fx_glow(ShaderFxData *fx, /* blur pass */ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx); DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1); @@ -558,7 +558,7 @@ static void DRW_gpencil_fx_glow(ShaderFxData *fx, /* resolve pass */ fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_glow_resolve_sh, psl->fx_shader_pass_blend); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "glowColor", &e_data->temp_color_tx_fx); @@ -593,7 +593,7 @@ static void DRW_gpencil_fx_swirl(ShaderFxData *fx, GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_swirl_sh, psl->fx_shader_pass); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); @@ -624,7 +624,7 @@ static void DRW_gpencil_fx_wave(ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCI GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); DRWShadingGroup *fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_wave_sh, psl->fx_shader_pass); - DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_call(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); DRW_shgroup_uniform_float(fx_shgrp, "amplitude", &fxd->amplitude, 1); diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl index 8c3fd022004..e0634a7d1a7 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl @@ -1,4 +1,3 @@ -uniform mat4 ModelViewProjectionMatrix; uniform vec2 Viewport; layout(points) in; diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl index eea28755ae6..a1cfb2ae4ae 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl @@ -1,4 +1,3 @@ -uniform mat4 ModelViewProjectionMatrix; in vec3 pos; in vec4 color; @@ -9,7 +8,7 @@ out float finalThickness; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = point_object_to_ndc(pos); finalColor = color; finalThickness = size; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl index acf60fc2d59..192720a4e98 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl @@ -89,6 +89,27 @@ void set_color(in vec4 color, ocolor.a *= layer_opacity; } +float linearrgb_to_srgb(float c) +{ + if (c < 0.0031308) { + return (c < 0.0) ? 0.0 : c * 12.92; + } + else { + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; + } +} + +vec4 texture_read_as_srgb(sampler2D tex, vec2 co) +{ + /* By convention image textures return scene linear colors, but + * grease pencil still works in srgb. */ + vec4 color = texture(tex, co); + color.r = linearrgb_to_srgb(color.r); + color.g = linearrgb_to_srgb(color.g); + color.b = linearrgb_to_srgb(color.b); + return color; +} + void main() { vec2 t_center = vec2(0.5, 0.5); @@ -97,8 +118,8 @@ void main() vec2 rot_tex = (matrot_tex * (texCoord_interp - t_center)) + t_center + texture_offset; vec4 tmp_color; tmp_color = (texture_clamp == 0) ? - texture2D(myTexture, rot_tex * texture_scale) : - texture2D(myTexture, clamp(rot_tex * texture_scale, 0.0, 1.0)); + texture_read_as_srgb(myTexture, rot_tex * texture_scale) : + texture_read_as_srgb(myTexture, clamp(rot_tex * texture_scale, 0.0, 1.0)); vec4 text_color = vec4(tmp_color[0], tmp_color[1], tmp_color[2], tmp_color[3] * texture_opacity); vec4 chesscolor; diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl index d71f57eb98c..eb452f4c660 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl @@ -1,14 +1,14 @@ -uniform mat4 ModelViewProjectionMatrix; in vec3 pos; in vec4 color; in vec2 texCoord; + out vec4 finalColor; out vec2 texCoord_interp; void main(void) { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = point_object_to_ndc(pos); finalColor = color; texCoord_interp = texCoord; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl index 3c1424f98ff..1d1cd6349dc 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl @@ -5,5 +5,5 @@ out vec4 FragColor; void main() { - FragColor = vec4(color, opacity); + FragColor = vec4(color, 1.0 - opacity); } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl index cc47e12b303..569a68679b4 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl @@ -47,6 +47,27 @@ vec2 check_box_point(vec2 pt, vec2 radius) return rtn; } +float linearrgb_to_srgb(float c) +{ + if (c < 0.0031308) { + return (c < 0.0) ? 0.0 : c * 12.92; + } + else { + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; + } +} + +vec4 texture_read_as_srgb(sampler2D tex, vec2 co) +{ + /* By convention image textures return scene linear colors, but + * grease pencil still works in srgb. */ + vec4 color = texture(tex, co); + color.r = linearrgb_to_srgb(color.r); + color.g = linearrgb_to_srgb(color.g); + color.b = linearrgb_to_srgb(color.b); + return color; +} + void main() { vec2 centered = mTexCoord - vec2(0.5); @@ -65,7 +86,7 @@ void main() } } - vec4 tmp_color = texture2D(myTexture, mTexCoord); + vec4 tmp_color = texture_read_as_srgb(myTexture, mTexCoord); /* Solid */ if ((color_type == GPENCIL_COLOR_SOLID) || (no_texture)) { @@ -73,7 +94,7 @@ void main() } /* texture */ if ((color_type == GPENCIL_COLOR_TEXTURE) && (!no_texture)) { - vec4 text_color = texture2D(myTexture, mTexCoord); + vec4 text_color = texture_read_as_srgb(myTexture, mTexCoord); if (mix_stroke_factor > 0.0) { fragColor.rgb = mix(text_color.rgb, colormix.rgb, mix_stroke_factor); fragColor.a = text_color.a; @@ -87,7 +108,7 @@ void main() } /* pattern */ if ((color_type == GPENCIL_COLOR_PATTERN) && (!no_texture)) { - vec4 text_color = texture2D(myTexture, mTexCoord); + vec4 text_color = texture_read_as_srgb(myTexture, mTexCoord); fragColor = mColor; /* mult both alpha factor to use strength factor with color alpha limit */ fragColor.a = min(text_color.a * mColor.a, mColor.a); diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl index a64a7ecb9be..a2f4c1f9b15 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl @@ -1,7 +1,6 @@ -uniform mat4 ModelViewProjectionMatrix; uniform vec2 Viewport; uniform int xraymode; -uniform int use_follow_path; +uniform int alignment_mode; layout(points) in; layout(triangle_strip, max_vertices = 4) out; @@ -21,6 +20,9 @@ out vec2 mTexCoord; #define M_2PI 6.28318530717958647692 /* 2*pi */ #define FALSE 0 +/* keep this definition equals to GP_STYLE_FOLLOW_FIXED value */ +#define FIXED 2 + /* project 3d point to 2d on screen space */ vec2 toScreenSpace(vec4 vertex) { @@ -70,7 +72,7 @@ float getAngle(vec2 pt0, vec2 pt1) return 0.0; } - if (use_follow_path == FALSE) { + if (alignment_mode == FIXED) { return 0.0; } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl index 9cef7601770..ef8b361373f 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl @@ -1,5 +1,3 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ProjectionMatrix; uniform float pixsize; /* rv3d->pixsize */ uniform int keep_size; @@ -32,8 +30,8 @@ float defaultpixsize = pixsize * (1000.0 / pixfactor); void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - finalprev_pos = ModelViewProjectionMatrix * vec4(prev_pos, 1.0); + gl_Position = point_object_to_ndc(pos); + finalprev_pos = point_object_to_ndc(prev_pos); finalColor = color; if (keep_size == TRUE) { diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl index 6b7cee888ea..a5580e305d6 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl @@ -27,6 +27,27 @@ out vec4 fragColor; bool no_texture = (shading_type[0] == OB_SOLID) && (shading_type[1] != V3D_SHADING_TEXTURE_COLOR); +float linearrgb_to_srgb(float c) +{ + if (c < 0.0031308) { + return (c < 0.0) ? 0.0 : c * 12.92; + } + else { + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; + } +} + +vec4 texture_read_as_srgb(sampler2D tex, vec2 co) +{ + /* By convention image textures return scene linear colors, but + * grease pencil still works in srgb. */ + vec4 color = texture(tex, co); + color.r = linearrgb_to_srgb(color.r); + color.g = linearrgb_to_srgb(color.g); + color.b = linearrgb_to_srgb(color.b); + return color; +} + void main() { @@ -47,10 +68,10 @@ void main() /* texture for endcaps */ vec4 text_color; if (uvfac[1] == ENDCAP) { - text_color = texture2D(myTexture, vec2(mTexCoord.x, mTexCoord.y)); + text_color = texture_read_as_srgb(myTexture, vec2(mTexCoord.x, mTexCoord.y)); } else { - text_color = texture2D(myTexture, mTexCoord); + text_color = texture_read_as_srgb(myTexture, mTexCoord); } /* texture */ diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl index b90f5b33a57..9ea96806481 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl @@ -1,4 +1,3 @@ -uniform mat4 ModelViewProjectionMatrix; uniform vec2 Viewport; uniform int xraymode; uniform int color_type; diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl index 946b39c006a..c7089f357f9 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl @@ -1,5 +1,3 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ProjectionMatrix; uniform float pixsize; /* rv3d->pixsize */ uniform int keep_size; @@ -30,7 +28,7 @@ float defaultpixsize = pixsize * (1000.0 / pixfactor); void main(void) { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = point_object_to_ndc(pos); finalColor = color; if (keep_size == TRUE) { 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 c76ad8c1d7b..96f8f6e4c7a 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl @@ -140,32 +140,18 @@ vec2 matcap_uv_compute(vec3 I, vec3 N, bool flipped) return matcap_uv * 0.496 + 0.5; } -float srgb_to_linearrgb(float c) -{ - if (c < 0.04045) { - return (c < 0.0) ? 0.0 : c * (1.0 / 12.92); - } - else { - return pow((c + 0.055) * (1.0 / 1.055), 2.4); - } -} - -vec4 srgb_to_linearrgb(vec4 col_from) -{ - vec4 col_to; - col_to.r = srgb_to_linearrgb(col_from.r); - col_to.g = srgb_to_linearrgb(col_from.g); - col_to.b = srgb_to_linearrgb(col_from.b); - col_to.a = col_from.a; - return col_to; -} - -vec4 workbench_sample_texture(sampler2D image, vec2 coord, bool srgb, bool nearest_sampling) +vec4 workbench_sample_texture(sampler2D image, vec2 coord, bool nearest_sampling) { vec2 tex_size = vec2(textureSize(image, 0).xy); /* TODO(fclem) We could do the same with sampler objects. * But this is a quick workaround instead of messing with the GPUTexture itself. */ vec2 uv = nearest_sampling ? (floor(coord * tex_size) + 0.5) / tex_size : coord; vec4 color = texture(image, uv); - return (srgb) ? srgb_to_linearrgb(color) : color; + + /* Unpremultiply, ideally shaders would be added so this is not needed. */ + if (!(color.a == 0.0 || color.a == 1.0)) { + color.rgb = color.rgb / color.a; + } + + return color; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl index 65196c1a836..a1f80440404 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl @@ -1,8 +1,5 @@ out vec4 fragColor; -uniform mat4 ProjectionMatrix; -uniform mat4 ViewMatrixInverse; - uniform usampler2D objectId; uniform sampler2D materialBuffer; uniform sampler2D normalBuffer; 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 5eff0b41e20..51bce639b63 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 @@ -1,11 +1,8 @@ uniform float ImageTransparencyCutoff = 0.1; uniform sampler2D image; -uniform bool imageSrgb; uniform bool imageNearest; -uniform mat4 ProjectionMatrix; -uniform mat4 ViewMatrixInverse; uniform float alpha = 0.5; uniform vec2 invertedViewportSize; uniform vec4 viewvecs[3]; @@ -46,7 +43,7 @@ void main() vec4 diffuse_color; #if defined(V3D_SHADING_TEXTURE_COLOR) - diffuse_color = workbench_sample_texture(image, uv_interp, imageSrgb, imageNearest); + diffuse_color = workbench_sample_texture(image, uv_interp, imageNearest); if (diffuse_color.a < ImageTransparencyCutoff) { discard; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl index 2596fc4cf88..af9f1d14f4a 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -6,7 +6,6 @@ uniform float materialRoughness; uniform sampler2D image; uniform float ImageTransparencyCutoff = 0.1; -uniform bool imageSrgb; uniform bool imageNearest; #ifdef NORMAL_VIEWPORT_PASS_ENABLED @@ -41,7 +40,7 @@ void main() vec4 color; # if defined(V3D_SHADING_TEXTURE_COLOR) - color = workbench_sample_texture(image, uv_interp, imageSrgb, imageNearest); + color = workbench_sample_texture(image, uv_interp, imageNearest); if (color.a < ImageTransparencyCutoff) { discard; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl index f2c684cdb6a..5d4153999c0 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -1,10 +1,3 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; -uniform mat4 ModelMatrixInverse; -uniform mat4 ProjectionMatrix; -uniform mat4 ViewProjectionMatrix; -uniform mat4 ViewMatrixInverse; -uniform mat3 NormalMatrix; #ifndef HAIR_SHADER in vec3 pos; @@ -50,6 +43,18 @@ vec3 srgb_to_linear_attr(vec3 c) } #endif +vec3 workbench_hair_hair_normal(vec3 tan, vec3 binor, float rand) +{ + /* To "simulate" anisotropic shading, randomize hair normal per strand. */ + tan = normalize(tan); + vec3 nor = normalize(cross(binor, tan)); + // nor = normalize(mix(nor, -tan, rand * 0.1)); + // float cos_theta = (rand * 2.0 - 1.0) * 0.2; + // float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta)); + // nor = nor * sin_theta + binor * cos_theta; + return nor; +} + void main() { #ifdef HAIR_SHADER @@ -57,29 +62,25 @@ void main() vec2 uv = hair_get_customdata_vec2(u); # endif float time, thick_time, thickness; - vec3 pos, tan, binor; + vec3 world_pos, tan, binor; hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0), ModelMatrixInverse, ViewMatrixInverse[3].xyz, ViewMatrixInverse[2].xyz, - pos, + world_pos, tan, binor, time, thickness, thick_time); - /* To "simulate" anisotropic shading, randomize hair normal per strand. */ + hair_rand = integer_noise(hair_get_strand_id()); - tan = normalize(tan); - vec3 nor = normalize(cross(binor, tan)); - nor = normalize(mix(nor, -tan, hair_rand * 0.10)); - float cos_theta = (hair_rand * 2.0 - 1.0) * 0.20; - float sin_theta = sqrt(max(0.0, 1.0f - cos_theta * cos_theta)); - nor = nor * sin_theta + binor * cos_theta; - gl_Position = ViewProjectionMatrix * vec4(pos, 1.0); + vec3 nor = workbench_hair_hair_normal(tan, binor, hair_rand); #else - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); #endif + gl_Position = point_world_to_ndc(world_pos); + #ifdef V3D_SHADING_TEXTURE_COLOR uv_interp = uv; #endif @@ -91,13 +92,13 @@ void main() #endif #ifdef NORMAL_VIEWPORT_PASS_ENABLED - normal_viewport = NormalMatrix * nor; + normal_viewport = normal_object_to_view(nor); # ifndef HAIR_SHADER normal_viewport = normalize(normal_viewport); # endif #endif #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl index afd704a7d3a..e07f87525e2 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl @@ -1,7 +1,5 @@ #define INFINITE 1000.0 -uniform mat4 ModelViewProjectionMatrix; - uniform vec3 lightDirection = vec3(0.57, 0.57, -0.57); uniform float lightDistance = 1e4; @@ -18,6 +16,6 @@ vData; void main() { vData.pos = pos; - vData.frontPosition = ModelViewProjectionMatrix * vec4(pos, 1.0); - vData.backPosition = ModelViewProjectionMatrix * vec4(pos + lightDirection * lightDistance, 1.0); + vData.frontPosition = point_object_to_ndc(pos); + vData.backPosition = point_object_to_ndc(pos + lightDirection * lightDistance); } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl index a1c269d5a65..848cd49bf53 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl @@ -1,8 +1,4 @@ -uniform mat4 ProjectionMatrix; -uniform mat4 ModelMatrixInverse; -uniform mat4 ModelViewMatrixInverse; -uniform mat4 ModelMatrix; uniform vec3 OrcoTexCoFactors[2]; uniform sampler2D depthBuffer; @@ -219,9 +215,11 @@ void main() vec3 vs_ray_dir = (is_persp) ? (vs_ray_end - vs_ray_ori) : vec3(0.0, 0.0, -1.0); vs_ray_dir /= abs(vs_ray_dir.z); - vec3 ls_ray_dir = mat3(ModelViewMatrixInverse) * vs_ray_dir * OrcoTexCoFactors[1] * 2.0; - vec3 ls_ray_ori = (ModelViewMatrixInverse * vec4(vs_ray_ori, 1.0)).xyz; - vec3 ls_ray_end = (ModelViewMatrixInverse * vec4(vs_ray_end, 1.0)).xyz; + /* TODO(fclem) Precompute the matrix/ */ + vec3 ls_ray_dir = vs_ray_dir * OrcoTexCoFactors[1] * 2.0; + ls_ray_dir = mat3(ModelMatrixInverse) * (mat3(ViewMatrixInverse) * ls_ray_dir); + vec3 ls_ray_ori = point_view_to_object(vs_ray_ori); + vec3 ls_ray_end = point_view_to_object(vs_ray_end); ls_ray_ori = (OrcoTexCoFactors[0] + ls_ray_ori * OrcoTexCoFactors[1]) * 2.0 - 1.0; ls_ray_end = (OrcoTexCoFactors[0] + ls_ray_end * OrcoTexCoFactors[1]) * 2.0 - 1.0; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl index 7a418243fd3..6f0bb56fafd 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl @@ -1,5 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; uniform vec3 OrcoTexCoFactors[2]; uniform float slicePosition; uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */ @@ -29,5 +28,5 @@ void main() vec3 final_pos = pos; #endif final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0]) / OrcoTexCoFactors[1]; - gl_Position = ModelViewProjectionMatrix * vec4(final_pos, 1.0); + gl_Position = point_object_to_ndc(final_pos); } diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index abf167d53b0..eacd319cc4a 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -91,6 +91,7 @@ static struct { /* Shaders */ extern char datatoc_common_hair_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; extern char datatoc_workbench_prepass_vert_glsl[]; extern char datatoc_workbench_prepass_frag_glsl[]; @@ -119,6 +120,7 @@ static char *workbench_build_composite_frag(WORKBENCH_PrivateData *wpd) { DynStr *ds = BLI_dynstr_new(); + BLI_dynstr_append(ds, datatoc_common_view_lib_glsl); BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); BLI_dynstr_append(ds, datatoc_workbench_background_lib_glsl); @@ -159,6 +161,7 @@ static char *workbench_build_prepass_vert(bool is_hair) if (is_hair) { BLI_dynstr_append(ds, datatoc_common_hair_lib_glsl); } + BLI_dynstr_append(ds, datatoc_common_view_lib_glsl); BLI_dynstr_append(ds, datatoc_workbench_prepass_vert_glsl); char *str = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); @@ -382,33 +385,60 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) const char *shadow_frag = datatoc_gpu_shader_depth_only_frag_glsl; #endif /* TODO only compile on demand */ - 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"); + e_data.shadow_pass_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){datatoc_common_view_lib_glsl, + datatoc_workbench_shadow_vert_glsl, + NULL}, + .geom = (const char *[]){datatoc_workbench_shadow_geom_glsl, NULL}, + .frag = (const char *[]){shadow_frag, NULL}, + .defs = (const char *[]){"#define SHADOW_PASS\n" + "#define DOUBLE_MANIFOLD\n", + NULL}, + }); + e_data.shadow_pass_manifold_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){datatoc_common_view_lib_glsl, + datatoc_workbench_shadow_vert_glsl, + NULL}, + .geom = (const char *[]){datatoc_workbench_shadow_geom_glsl, NULL}, + .frag = (const char *[]){shadow_frag, NULL}, + .defs = (const char *[]){"#define SHADOW_PASS\n", NULL}, + }); + e_data.shadow_fail_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){datatoc_common_view_lib_glsl, + datatoc_workbench_shadow_vert_glsl, + NULL}, + .geom = (const char *[]){datatoc_workbench_shadow_geom_glsl, NULL}, + .frag = (const char *[]){shadow_frag, NULL}, + .defs = (const char *[]){"#define SHADOW_FAIL\n" + "#define DOUBLE_MANIFOLD\n", + NULL}, + }); + e_data.shadow_fail_manifold_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){datatoc_common_view_lib_glsl, + datatoc_workbench_shadow_vert_glsl, + NULL}, + .geom = (const char *[]){datatoc_workbench_shadow_geom_glsl, NULL}, + .frag = (const char *[]){shadow_frag, NULL}, + .defs = (const char *[]){"#define SHADOW_FAIL\n", NULL}, + }); + e_data.shadow_caps_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){datatoc_common_view_lib_glsl, + datatoc_workbench_shadow_vert_glsl, + NULL}, + .geom = (const char *[]){datatoc_workbench_shadow_caps_geom_glsl, NULL}, + .frag = (const char *[]){shadow_frag, NULL}, + .defs = (const char *[]){"#define SHADOW_FAIL\n" + "#define DOUBLE_MANIFOLD\n", + NULL}, + }); + e_data.shadow_caps_manifold_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){datatoc_common_view_lib_glsl, + datatoc_workbench_shadow_vert_glsl, + NULL}, + .geom = (const char *[]){datatoc_workbench_shadow_caps_geom_glsl, NULL}, + .frag = (const char *[]){shadow_frag, NULL}, + .defs = (const char *[]){"#define SHADOW_FAIL\n", NULL}, + }); e_data.ghost_resolve_sh = DRW_shader_create_fullscreen( datatoc_workbench_ghost_resolve_frag_glsl, NULL); @@ -549,7 +579,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.ghost_resolve_sh, psl->ghost_resolve_pass); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.ghost_depth_tx); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } { @@ -583,7 +613,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata) DRW_shgroup_uniform_vec2(grp, "curvature_settings", &wpd->world_data.curvature_ridge, 1); } - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } } @@ -694,13 +724,13 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) if (OBJECT_OUTLINE_ENABLED(wpd)) { DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); } - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); if (draw_ctx->rv3d && (draw_ctx->rv3d->rflag & RV3D_CLIPPING) && draw_ctx->rv3d->clipbb) { GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND); grp = DRW_shgroup_create(shader, psl->background_pass); wpd->world_clip_planes_batch = DRW_draw_background_clipping_batch_from_rv3d(draw_ctx->rv3d); - DRW_shgroup_call_add(grp, wpd->world_clip_planes_batch, NULL); + DRW_shgroup_call(grp, wpd->world_clip_planes_batch, NULL); DRW_shgroup_uniform_vec4(grp, "color", &wpd->world_clip_planes_color[0], 1); } } @@ -720,7 +750,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) DRW_shgroup_uniform_float(grp, "shadowMultiplier", &wpd->shadow_multiplier, 1); DRW_shgroup_uniform_float_copy(grp, "shadowShift", scene->display.shadow_shift); DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); /* Stencil Shadow passes. */ #ifdef DEBUG_SHADOW_VOLUME @@ -765,7 +795,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) DRW_shgroup_uniform_float(grp, "shadowMultiplier", &wpd->shadow_multiplier, 1); DRW_shgroup_uniform_float_copy(grp, "shadowShift", scene->display.shadow_shift); DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); #endif } else { @@ -773,7 +803,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER); 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); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } } @@ -807,7 +837,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "transparentAccum", &e_data.oit_accum_tx); DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.oit_revealage_tx); DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } } } @@ -961,7 +991,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) material = get_or_create_material_data( vedata, ob, mat, image, iuser, color_type, interp); } - DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); + DRW_shgroup_call_object(material->shgrp, geom_array[i], ob); } } } @@ -986,7 +1016,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) if (is_sculpt_mode) { bool use_vcol = (color_type == V3D_SHADING_VERTEX_COLOR); - DRW_shgroup_call_sculpt_add(material->shgrp, ob, false, false, use_vcol); + DRW_shgroup_call_sculpt(material->shgrp, ob, false, false, use_vcol); } else { struct GPUBatch *geom; @@ -998,7 +1028,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) } if (geom) { - DRW_shgroup_call_object_add(material->shgrp, geom, ob); + DRW_shgroup_call_object(material->shgrp, geom, ob); } } } @@ -1006,24 +1036,23 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) /* Draw material color */ if (is_sculpt_mode) { struct DRWShadingGroup **shgrps = BLI_array_alloca(shgrps, materials_len); - struct Material **mats = BLI_array_alloca(mats, materials_len); for (int i = 0; i < materials_len; ++i) { - mats[i] = give_current_material(ob, i + 1); - if (mats[i] != NULL && mats[i]->a < 1.0f) { + struct Material *mat = give_current_material(ob, i + 1); + if (mat != NULL && mat->a < 1.0f) { /* Hack */ - wpd->shading.xray_alpha = mats[i]->a; + wpd->shading.xray_alpha = mat->a; material = workbench_forward_get_or_create_material_data( - vedata, ob, mats[i], NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode); + vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode); has_transp_mat = true; } else { material = get_or_create_material_data( - vedata, ob, mats[i], NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); + vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); } shgrps[i] = material->shgrp; } - DRW_shgroup_call_sculpt_with_materials_add(shgrps, mats, ob, false); + DRW_shgroup_call_sculpt_with_materials(shgrps, ob, false); } else { struct GPUBatch **geoms; @@ -1046,7 +1075,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) material = get_or_create_material_data( vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0); } - DRW_shgroup_call_object_add(material->shgrp, geoms[i], ob); + DRW_shgroup_call_object(material->shgrp, geoms[i], ob); } } } @@ -1060,7 +1089,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) /* Currently unsupported in sculpt mode. We could revert to the slow * method in this case but I'm not sure if it's a good idea given that * sculpted meshes are heavy to begin with. */ - // DRW_shgroup_call_sculpt_add(wpd->shadow_shgrp, ob, ob->obmat); + // DRW_shgroup_call_sculpt(wpd->shadow_shgrp, ob, ob->obmat); } else { WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure( @@ -1072,7 +1101,6 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) if (studiolight_object_cast_visible_shadow(wpd, ob, engine_object_data)) { - invert_m4_m4(ob->imat, ob->obmat); mul_v3_mat3_m4v3( engine_object_data->shadow_dir, ob->imat, e_data.display.light_direction); @@ -1090,7 +1118,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) } DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); DRW_shgroup_uniform_float_copy(grp, "lightDistance", 1e5f); - DRW_shgroup_call_add(grp, geom_shadow, ob->obmat); + DRW_shgroup_call(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 @@ -1112,7 +1140,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) } DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); DRW_shgroup_uniform_float_copy(grp, "lightDistance", extrude_distance); - DRW_shgroup_call_add(grp, DRW_cache_object_surface_get(ob), ob->obmat); + DRW_shgroup_call(grp, DRW_cache_object_surface_get(ob), ob->obmat); } if (is_manifold) { @@ -1124,7 +1152,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) } DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1); DRW_shgroup_uniform_float_copy(grp, "lightDistance", extrude_distance); - DRW_shgroup_call_add(grp, geom_shadow, ob->obmat); + DRW_shgroup_call(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 diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.c b/source/blender/draw/engines/workbench/workbench_effect_dof.c index 3dea99a76cf..ee8c8a0343f 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_dof.c +++ b/source/blender/draw/engines/workbench/workbench_effect_dof.c @@ -314,37 +314,37 @@ void workbench_dof_create_pass(WORKBENCH_Data *vedata, DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); DRW_shgroup_uniform_vec3(grp, "dofParams", &wpd->dof_aperturesize, 1); DRW_shgroup_uniform_vec2(grp, "nearFar", wpd->dof_near_far, 1); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } { DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_downsample_sh, psl->dof_down2_ps); DRW_shgroup_uniform_texture(grp, "sceneColorTex", txl->dof_source_tx); DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } #if 0 { DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_flatten_h_sh, psl->dof_flatten_h_ps); DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } { DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_flatten_v_sh, psl->dof_flatten_v_ps); DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_temp_tx); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } { DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_dilate_v_sh, psl->dof_dilate_v_ps); DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_tiles_tx[0]); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } { DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_dilate_h_sh, psl->dof_dilate_h_ps); DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_tiles_tx[1]); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } #endif { @@ -357,14 +357,14 @@ void workbench_dof_create_pass(WORKBENCH_Data *vedata, DRW_shgroup_uniform_texture(grp, "halfResColorTex", txl->dof_source_tx); DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); DRW_shgroup_uniform_float_copy(grp, "noiseOffset", offset); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } { DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_blur2_sh, psl->dof_blur2_ps); DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx); DRW_shgroup_uniform_texture(grp, "blurTex", wpd->dof_blur_tx); DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } { DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_resolve_sh, psl->dof_resolve_ps); @@ -373,7 +373,7 @@ void workbench_dof_create_pass(WORKBENCH_Data *vedata, DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); DRW_shgroup_uniform_vec3(grp, "dofParams", &wpd->dof_aperturesize, 1); DRW_shgroup_uniform_vec2(grp, "nearFar", wpd->dof_near_far, 1); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } } diff --git a/source/blender/draw/engines/workbench/workbench_effect_fxaa.c b/source/blender/draw/engines/workbench/workbench_effect_fxaa.c index 47355f324a8..6e3bf1658ab 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_fxaa.c +++ b/source/blender/draw/engines/workbench/workbench_effect_fxaa.c @@ -49,7 +49,7 @@ DRWPass *workbench_fxaa_create_pass(GPUTexture **color_buffer_tx) DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_fxaa_sh, pass); DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", color_buffer_tx); DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); return pass; } diff --git a/source/blender/draw/engines/workbench/workbench_effect_taa.c b/source/blender/draw/engines/workbench/workbench_effect_taa.c index 7c411135634..7b2faf0ddcd 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_taa.c +++ b/source/blender/draw/engines/workbench/workbench_effect_taa.c @@ -91,23 +91,19 @@ int workbench_taa_calculate_num_iterations(WORKBENCH_Data *vedata) WORKBENCH_StorageList *stl = vedata->stl; WORKBENCH_PrivateData *wpd = stl->g_data; const Scene *scene = DRW_context_state_get()->scene; - int result = scene->display.viewport_aa; + int result; if (workbench_is_taa_enabled(wpd)) { if (DRW_state_is_image_render()) { - result = scene->display.render_aa; - } - else if (IN_RANGE_INCL(wpd->preferences->gpu_viewport_quality, - GPU_VIEWPORT_QUALITY_TAA8, - GPU_VIEWPORT_QUALITY_TAA16)) { - result = MIN2(result, 8); - } - else if (IN_RANGE_INCL(wpd->preferences->gpu_viewport_quality, - GPU_VIEWPORT_QUALITY_TAA16, - GPU_VIEWPORT_QUALITY_TAA32)) { - result = MIN2(result, 16); + const DRWContextState *draw_ctx = DRW_context_state_get(); + if (draw_ctx->v3d) { + result = scene->display.viewport_aa; + } + else { + result = scene->display.render_aa; + } } else { - result = MIN2(result, 32); + result = wpd->preferences->viewport_aa; } } else { @@ -205,7 +201,7 @@ DRWPass *workbench_taa_create_pass(WORKBENCH_Data *vedata, GPUTexture **color_bu DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", color_buffer_tx); DRW_shgroup_uniform_texture_ref(grp, "historyBuffer", &txl->history_buffer_tx); DRW_shgroup_uniform_float(grp, "mixFactor", &effect_info->taa_mix_factor, 1); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); /* * Set the offset for the cavity shader so every iteration different diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index fe3e0579c8e..f12902b6801 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -68,6 +68,7 @@ static struct { /* Shaders */ extern char datatoc_common_hair_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; extern char datatoc_workbench_forward_composite_frag_glsl[]; extern char datatoc_workbench_forward_depth_frag_glsl[]; @@ -88,6 +89,7 @@ static char *workbench_build_forward_vert(bool is_hair) if (is_hair) { BLI_dynstr_append(ds, datatoc_common_hair_lib_glsl); } + BLI_dynstr_append(ds, datatoc_common_view_lib_glsl); BLI_dynstr_append(ds, datatoc_workbench_prepass_vert_glsl); char *str = BLI_dynstr_get_cstring(ds); @@ -99,6 +101,7 @@ static char *workbench_build_forward_transparent_accum_frag(void) { DynStr *ds = BLI_dynstr_new(); + BLI_dynstr_append(ds, datatoc_common_view_lib_glsl); BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl); BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl); BLI_dynstr_append(ds, datatoc_workbench_world_light_lib_glsl); @@ -199,8 +202,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ V3D_SHADING_TEXTURE_COLOR) { material->shgrp_object_outline = DRW_shgroup_create(sh_data->object_outline_texture_sh, psl->object_outline_pass); - GPUTexture *tex = GPU_texture_from_blender( - material->ima, material->iuser, GL_TEXTURE_2D, false); + GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D); DRW_shgroup_uniform_texture(material->shgrp_object_outline, "image", tex); } else { @@ -399,7 +401,7 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.transparent_revealage_tx); 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); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } /* TODO(campbell): displays but masks geometry, @@ -411,7 +413,7 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND); grp = DRW_shgroup_create(shader, psl->background_pass); wpd->world_clip_planes_batch = DRW_draw_background_clipping_batch_from_rv3d(draw_ctx->rv3d); - DRW_shgroup_call_add(grp, wpd->world_clip_planes_batch, NULL); + DRW_shgroup_call(grp, wpd->world_clip_planes_batch, NULL); DRW_shgroup_uniform_vec4(grp, "color", &wpd->world_clip_planes_color[0], 1); } @@ -441,7 +443,7 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) int state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS; psl->checker_depth_pass = DRW_pass_create("Checker Depth", state); grp = DRW_shgroup_create(e_data.checker_depth_sh, psl->checker_depth_pass); - DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); DRW_shgroup_uniform_float_copy(grp, "threshold", blend_threshold); DRW_shgroup_uniform_float_copy(grp, "offset", noise_offset); } @@ -580,8 +582,8 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) int color_type = workbench_material_determine_color_type(wpd, image, ob, is_sculpt_mode); material = workbench_forward_get_or_create_material_data( vedata, ob, mat, image, iuser, color_type, interp, is_sculpt_mode); - DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob); - DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); + DRW_shgroup_call_object(material->shgrp_object_outline, geom_array[i], ob); + DRW_shgroup_call_object(material->shgrp, geom_array[i], ob); } } else if (ELEM(wpd->shading.color_type, @@ -597,9 +599,9 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) vedata, ob, NULL, NULL, NULL, color_type, 0, is_sculpt_mode); bool use_vcol = (color_type == V3D_SHADING_VERTEX_COLOR); /* TODO(fclem) make this call optional */ - DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, false, false, false); + DRW_shgroup_call_sculpt(material->shgrp_object_outline, ob, false, false, false); if (!is_wire) { - DRW_shgroup_call_sculpt_add(material->shgrp, ob, false, false, use_vcol); + DRW_shgroup_call_sculpt(material->shgrp, ob, false, false, use_vcol); } } else { @@ -610,9 +612,9 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) material = workbench_forward_get_or_create_material_data( vedata, ob, NULL, NULL, NULL, color_type, 0, is_sculpt_mode); /* TODO(fclem) make this call optional */ - DRW_shgroup_call_object_add(material->shgrp_object_outline, geom, ob); + DRW_shgroup_call_object(material->shgrp_object_outline, geom, ob); if (!is_wire) { - DRW_shgroup_call_object_add(material->shgrp, geom, ob); + DRW_shgroup_call_object(material->shgrp, geom, ob); } } } @@ -621,18 +623,17 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) /* Draw material color */ if (is_sculpt_mode) { struct DRWShadingGroup **shgrps = BLI_array_alloca(shgrps, materials_len); - struct Material **mats = BLI_array_alloca(mats, materials_len); for (int i = 0; i < materials_len; ++i) { - mats[i] = give_current_material(ob, i + 1); + struct Material *mat = give_current_material(ob, i + 1); material = workbench_forward_get_or_create_material_data( - vedata, ob, mats[i], NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode); + vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode); shgrps[i] = material->shgrp; } /* TODO(fclem) make this call optional */ - DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, false, false, false); + DRW_shgroup_call_sculpt(material->shgrp_object_outline, ob, false, false, false); if (!is_wire) { - DRW_shgroup_call_sculpt_with_materials_add(shgrps, mats, ob, false); + DRW_shgroup_call_sculpt_with_materials(shgrps, ob, false); } } else { @@ -651,9 +652,9 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) material = workbench_forward_get_or_create_material_data( vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode); /* TODO(fclem) make this call optional */ - DRW_shgroup_call_object_add(material->shgrp_object_outline, mat_geom[i], ob); + DRW_shgroup_call_object(material->shgrp_object_outline, mat_geom[i], ob); if (!is_wire) { - DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob); + DRW_shgroup_call_object(material->shgrp, mat_geom[i], ob); } } } diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index c403e358d6a..b280b6fd01a 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -294,15 +294,8 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, if (workbench_material_determine_color_type(wpd, material->ima, ob, false) == V3D_SHADING_TEXTURE_COLOR) { - ImBuf *ibuf = BKE_image_acquire_ibuf(material->ima, material->iuser, NULL); - const bool do_color_correction = wpd->use_color_management && - (ibuf && - (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0); - BKE_image_release_ibuf(material->ima, ibuf, NULL); - GPUTexture *tex = GPU_texture_from_blender( - material->ima, material->iuser, GL_TEXTURE_2D, false); + GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D); DRW_shgroup_uniform_texture(grp, "image", tex); - DRW_shgroup_uniform_bool_copy(grp, "imageSrgb", do_color_correction); DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST)); } else { diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index e25503aef6e..09d9ad65717 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -319,23 +319,32 @@ typedef struct WORKBENCH_ObjectData { BLI_INLINE bool workbench_is_taa_enabled(WORKBENCH_PrivateData *wpd) { if (DRW_state_is_image_render()) { - return DRW_context_state_get()->scene->display.render_aa > SCE_DISPLAY_AA_FXAA; + const DRWContextState *draw_ctx = DRW_context_state_get(); + if (draw_ctx->v3d) { + return draw_ctx->scene->display.viewport_aa > SCE_DISPLAY_AA_FXAA; + } + else { + return draw_ctx->scene->display.render_aa > SCE_DISPLAY_AA_FXAA; + } } else { - return DRW_context_state_get()->scene->display.viewport_aa > SCE_DISPLAY_AA_FXAA && - wpd->preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8 && - !wpd->is_playback; + return wpd->preferences->viewport_aa > SCE_DISPLAY_AA_FXAA && !wpd->is_playback; } } BLI_INLINE bool workbench_is_fxaa_enabled(WORKBENCH_PrivateData *wpd) { if (DRW_state_is_image_render()) { - return DRW_context_state_get()->scene->display.render_aa == SCE_DISPLAY_AA_FXAA; + const DRWContextState *draw_ctx = DRW_context_state_get(); + if (draw_ctx->v3d) { + return draw_ctx->scene->display.viewport_aa == SCE_DISPLAY_AA_FXAA; + } + else { + return draw_ctx->scene->display.render_aa == SCE_DISPLAY_AA_FXAA; + } } else { - if (wpd->preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_FXAA && - DRW_context_state_get()->scene->display.viewport_aa == SCE_DISPLAY_AA_FXAA) { + if (wpd->preferences->viewport_aa == SCE_DISPLAY_AA_FXAA) { return true; } diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c index accc7e91576..1620584dc06 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.c +++ b/source/blender/draw/engines/workbench/workbench_volume.c @@ -53,6 +53,7 @@ static struct { extern char datatoc_workbench_volume_vert_glsl[]; extern char datatoc_workbench_volume_frag_glsl[]; +extern char datatoc_common_view_lib_glsl[]; static GPUShader *volume_shader_get(bool slice, bool coba, bool cubic) { @@ -77,8 +78,11 @@ static GPUShader *volume_shader_get(bool slice, bool coba, bool cubic) char *defines = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); - e_data.volume_sh[id] = DRW_shader_create( - datatoc_workbench_volume_vert_glsl, NULL, datatoc_workbench_volume_frag_glsl, defines); + e_data.volume_sh[id] = DRW_shader_create_with_lib(datatoc_workbench_volume_vert_glsl, + NULL, + datatoc_workbench_volume_frag_glsl, + datatoc_common_view_lib_glsl, + defines); MEM_freeN(defines); } @@ -207,10 +211,10 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness); if (use_slice) { - DRW_shgroup_call_object_add(grp, DRW_cache_quad_get(), ob); + DRW_shgroup_call_object(grp, DRW_cache_quad_get(), ob); } else { - DRW_shgroup_call_object_add(grp, DRW_cache_cube_get(), ob); + DRW_shgroup_call_object(grp, DRW_cache_cube_get(), ob); } BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd)); diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 51747c4aecc..19148352756 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -44,6 +44,7 @@ #include "DNA_world_types.h" #include "GPU_framebuffer.h" +#include "GPU_primitive.h" #include "GPU_texture.h" #include "GPU_shader.h" @@ -83,6 +84,9 @@ typedef struct DRWPass DRWPass; typedef struct DRWShadingGroup DRWShadingGroup; typedef struct DRWUniform DRWUniform; +/* Opaque type to avoid usage as a DRWCall but it is exactly the same thing. */ +typedef struct DRWCallBuffer DRWCallBuffer; + /* TODO Put it somewhere else? */ typedef struct BoundSphere { float center[3], radius; @@ -105,7 +109,7 @@ typedef char DRWViewportEmptyList; /* Use of multisample framebuffers. */ #define MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl) \ { \ - if (dfbl->multisample_fb != NULL) { \ + if (dfbl->multisample_fb != NULL && DRW_state_is_fbo()) { \ DRW_stats_query_start("Multisample Blit"); \ GPU_framebuffer_bind(dfbl->multisample_fb); \ /* TODO clear only depth but need to do alpha to coverage for transparencies. */ \ @@ -117,7 +121,7 @@ typedef char DRWViewportEmptyList; #define MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl) \ { \ - if (dfbl->multisample_fb != NULL) { \ + if (dfbl->multisample_fb != NULL && DRW_state_is_fbo()) { \ DRW_stats_query_start("Multisample Resolve"); \ GPU_framebuffer_bind(dfbl->default_fb); \ DRW_multisamples_resolve(dtxl->multisample_depth, dtxl->multisample_color, true); \ @@ -128,7 +132,7 @@ typedef char DRWViewportEmptyList; #define MULTISAMPLE_SYNC_DISABLE_NO_DEPTH(dfbl, dtxl) \ { \ - if (dfbl->multisample_fb != NULL) { \ + if (dfbl->multisample_fb != NULL && DRW_state_is_fbo()) { \ DRW_stats_query_start("Multisample Resolve"); \ GPU_framebuffer_bind(dfbl->default_fb); \ DRW_multisamples_resolve(dtxl->multisample_depth, dtxl->multisample_color, false); \ @@ -324,8 +328,8 @@ typedef enum { DRW_STATE_DEPTH_GREATER_EQUAL = (1 << 7), DRW_STATE_CULL_BACK = (1 << 8), DRW_STATE_CULL_FRONT = (1 << 9), - DRW_STATE_WIRE = (1 << 10), - DRW_STATE_POINT = (1 << 11), + DRW_STATE_WIRE = (1 << 10), /* TODO remove */ + DRW_STATE_POINT = (1 << 11), /* TODO remove */ /** Polygon offset. Does not work with lines and points. */ DRW_STATE_OFFSET_POSITIVE = (1 << 12), /** Polygon offset. Does not work with lines and points. */ @@ -382,26 +386,6 @@ struct GPUVertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttrFor DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass); DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup); DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass); -DRWShadingGroup *DRW_shgroup_material_instance_create(struct GPUMaterial *material, - DRWPass *pass, - struct GPUBatch *geom, - struct Object *ob, - struct GPUVertFormat *format); -DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(struct GPUMaterial *material, - DRWPass *pass, - int size); -DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, - DRWPass *pass, - struct GPUBatch *geom, - struct GPUVertFormat *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 GPUVertFormat *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 GPUVertBuf *tf_target); @@ -409,66 +393,57 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, /* return final visibility */ typedef bool(DRWCallVisibilityFn)(bool vis_in, void *user_data); -void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct GPUBatch *batch); - -void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct GPUBatch *geom, float (*obmat)[4]); -void DRW_shgroup_call_range_add( - DRWShadingGroup *shgroup, struct GPUBatch *geom, float (*obmat)[4], uint v_sta, uint v_count); -void DRW_shgroup_call_procedural_points_add(DRWShadingGroup *shgroup, - uint point_len, - float (*obmat)[4]); -void DRW_shgroup_call_procedural_lines_add(DRWShadingGroup *shgroup, - uint line_count, - float (*obmat)[4]); -void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup, - uint tria_count, - float (*obmat)[4]); -void DRW_shgroup_call_object_add_ex(DRWShadingGroup *shgroup, - struct GPUBatch *geom, - struct Object *ob, - struct Material *ma, - bool bypass_culling); -#define DRW_shgroup_call_object_add(shgroup, geom, ob) \ - DRW_shgroup_call_object_add_ex(shgroup, geom, ob, NULL, false) -#define DRW_shgroup_call_object_add_no_cull(shgroup, geom, ob) \ - DRW_shgroup_call_object_add_ex(shgroup, geom, ob, NULL, true) -void DRW_shgroup_call_object_add_with_callback(DRWShadingGroup *shgroup, - struct GPUBatch *geom, - struct Object *ob, - struct Material *ma, - DRWCallVisibilityFn *callback, - void *user_data); - -void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shading_group, - Object *object, - bool use_wire, - bool use_mask, - bool use_vert_color); -void DRW_shgroup_call_sculpt_with_materials_add(DRWShadingGroup **shgroups, - Material **materials, - Object *ob, - bool use_vcol); - -/* Used for drawing a batch with instancing without instance attributes. */ -void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup, - struct GPUBatch *geom, - float (*obmat)[4], - uint *count); -void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup, +/* TODO(fclem): Remove the _add suffix. */ +void DRW_shgroup_call(DRWShadingGroup *sh, struct GPUBatch *geom, float (*obmat)[4]); +void DRW_shgroup_call_range( + DRWShadingGroup *sh, struct GPUBatch *geom, float (*obmat)[4], uint v_sta, uint v_ct); + +void DRW_shgroup_call_procedural_points(DRWShadingGroup *sh, uint point_ct, float (*obmat)[4]); +void DRW_shgroup_call_procedural_lines(DRWShadingGroup *sh, uint line_ct, float (*obmat)[4]); +void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *sh, uint tri_ct, float (*obmat)[4]); + +void DRW_shgroup_call_object_ex(DRWShadingGroup *shgroup, + struct GPUBatch *geom, + struct Object *ob, + bool bypass_culling); +#define DRW_shgroup_call_object(shgroup, geom, ob) \ + DRW_shgroup_call_object_ex(shgroup, geom, ob, false) +#define DRW_shgroup_call_object_no_cull(shgroup, geom, ob) \ + DRW_shgroup_call_object_ex(shgroup, geom, ob, true) + +void DRW_shgroup_call_object_with_callback(DRWShadingGroup *shgroup, struct GPUBatch *geom, struct Object *ob, - uint *count); -void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, - const void *attr[], - uint attr_len); -#define DRW_shgroup_call_dynamic_add(shgroup, ...) \ + DRWCallVisibilityFn *callback, + void *user_data); + +void DRW_shgroup_call_instances(DRWShadingGroup *shgroup, + struct GPUBatch *geom, + float (*obmat)[4], + uint count); +void DRW_shgroup_call_instances_with_attribs(DRWShadingGroup *shgroup, + struct GPUBatch *geom, + float (*obmat)[4], + struct GPUBatch *inst_attributes); + +void DRW_shgroup_call_sculpt(DRWShadingGroup *sh, Object *ob, bool wire, bool mask, bool vcol); +void DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup **sh, Object *ob, bool vcol); + +DRWCallBuffer *DRW_shgroup_call_buffer(DRWShadingGroup *shading_group, + struct GPUVertFormat *format, + GPUPrimType prim_type); +DRWCallBuffer *DRW_shgroup_call_buffer_instance(DRWShadingGroup *shading_group, + struct GPUVertFormat *format, + struct GPUBatch *geom); + +void DRW_buffer_add_entry_array(DRWCallBuffer *buffer, const void *attr[], uint attr_len); + +#define DRW_buffer_add_entry(buffer, ...) \ do { \ const void *array[] = {__VA_ARGS__}; \ - DRW_shgroup_call_dynamic_add_array(shgroup, array, (sizeof(array) / sizeof(*array))); \ + DRW_buffer_add_entry_array(buffer, array, (sizeof(array) / sizeof(*array))); \ } while (0) -uint DRW_shgroup_get_instance_count(const DRWShadingGroup *shgroup); - void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state); void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state); void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask); @@ -539,6 +514,7 @@ void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value); void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value); void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value); +void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, const float *value); bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup); @@ -636,6 +612,7 @@ DrawData *DRW_drawdata_ensure(ID *id, size_t size, DrawDataInitCb init_cb, DrawDataFreeCb free_cb); +void **DRW_duplidata_get(void *vedata); /* Settings */ bool DRW_object_is_renderable(const struct Object *ob); diff --git a/source/blender/draw/intern/draw_anim_viz.c b/source/blender/draw/intern/draw_anim_viz.c index a6026c9da3a..31d7a45ede9 100644 --- a/source/blender/draw/intern/draw_anim_viz.c +++ b/source/blender/draw/intern/draw_anim_viz.c @@ -215,7 +215,7 @@ static void MPATH_cache_motion_path(MPATH_PassList *psl, DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1); } /* Only draw the required range. */ - DRW_shgroup_call_range_add(shgrp, mpath_batch_line_get(mpath), NULL, start_index, len); + DRW_shgroup_call_range(shgrp, mpath_batch_line_get(mpath), NULL, start_index, len); } /* Draw points. */ @@ -231,7 +231,7 @@ static void MPATH_cache_motion_path(MPATH_PassList *psl, DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1); } /* Only draw the required range. */ - DRW_shgroup_call_range_add(shgrp, mpath_batch_points_get(mpath), NULL, start_index, len); + DRW_shgroup_call_range(shgrp, mpath_batch_points_get(mpath), NULL, start_index, len); /* Draw frame numbers at each framestep value */ bool show_kf_no = (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) != 0; diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index 9b52f282944..3f651b27dd0 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -37,6 +37,8 @@ #include "BKE_armature.h" +#include "DEG_depsgraph_query.h" + #include "ED_armature.h" #include "UI_resources.h" @@ -57,26 +59,26 @@ static struct { /* Current armature object */ Object *ob; /* Reset when changing current_armature */ - DRWShadingGroup *bone_octahedral_solid; - DRWShadingGroup *bone_octahedral_wire; - DRWShadingGroup *bone_octahedral_outline; - DRWShadingGroup *bone_box_solid; - DRWShadingGroup *bone_box_wire; - DRWShadingGroup *bone_box_outline; - DRWShadingGroup *bone_wire; - DRWShadingGroup *bone_stick; - DRWShadingGroup *bone_dof_sphere; - DRWShadingGroup *bone_dof_lines; - DRWShadingGroup *bone_envelope_solid; - DRWShadingGroup *bone_envelope_distance; - DRWShadingGroup *bone_envelope_wire; - DRWShadingGroup *bone_point_solid; - DRWShadingGroup *bone_point_wire; - DRWShadingGroup *bone_axes; - DRWShadingGroup *lines_relationship; - DRWShadingGroup *lines_ik; - DRWShadingGroup *lines_ik_no_target; - DRWShadingGroup *lines_ik_spline; + DRWCallBuffer *bone_octahedral_solid; + DRWCallBuffer *bone_octahedral_wire; + DRWCallBuffer *bone_octahedral_outline; + DRWCallBuffer *bone_box_solid; + DRWCallBuffer *bone_box_wire; + DRWCallBuffer *bone_box_outline; + DRWCallBuffer *bone_wire; + DRWCallBuffer *bone_stick; + DRWCallBuffer *bone_dof_sphere; + DRWCallBuffer *bone_dof_lines; + DRWCallBuffer *bone_envelope_solid; + DRWCallBuffer *bone_envelope_distance; + DRWCallBuffer *bone_envelope_wire; + DRWCallBuffer *bone_point_solid; + DRWCallBuffer *bone_point_wire; + DRWCallBuffer *bone_axes; + DRWCallBuffer *lines_relationship; + DRWCallBuffer *lines_ik; + DRWCallBuffer *lines_ik_no_target; + DRWCallBuffer *lines_ik_spline; DRWArmaturePasses passes; @@ -120,22 +122,21 @@ static void drw_shgroup_bone_octahedral(const float (*bone_mat)[4], { if (g_data.bone_octahedral_outline == NULL) { struct GPUBatch *geom = DRW_cache_bone_octahedral_wire_get(); - g_data.bone_octahedral_outline = shgroup_instance_bone_shape_outline( + g_data.bone_octahedral_outline = buffer_instance_bone_shape_outline( g_data.passes.bone_outline, geom, sh_cfg); } if (g_data.bone_octahedral_solid == NULL && g_data.passes.bone_solid != NULL) { struct GPUBatch *geom = DRW_cache_bone_octahedral_get(); - g_data.bone_octahedral_solid = shgroup_instance_bone_shape_solid( + g_data.bone_octahedral_solid = buffer_instance_bone_shape_solid( g_data.passes.bone_solid, geom, g_data.transparent, sh_cfg); } float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); if (g_data.bone_octahedral_solid != NULL) { - DRW_shgroup_call_dynamic_add( - g_data.bone_octahedral_solid, final_bonemat, bone_color, hint_color); + DRW_buffer_add_entry(g_data.bone_octahedral_solid, final_bonemat, bone_color, hint_color); } if (outline_color[3] > 0.0f) { - DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_outline, final_bonemat, outline_color); + DRW_buffer_add_entry(g_data.bone_octahedral_outline, final_bonemat, outline_color); } } @@ -148,21 +149,21 @@ static void drw_shgroup_bone_box(const float (*bone_mat)[4], { if (g_data.bone_box_wire == NULL) { struct GPUBatch *geom = DRW_cache_bone_box_wire_get(); - g_data.bone_box_outline = shgroup_instance_bone_shape_outline( + g_data.bone_box_outline = buffer_instance_bone_shape_outline( g_data.passes.bone_outline, geom, sh_cfg); } if (g_data.bone_box_solid == NULL && g_data.passes.bone_solid != NULL) { struct GPUBatch *geom = DRW_cache_bone_box_get(); - g_data.bone_box_solid = shgroup_instance_bone_shape_solid( + g_data.bone_box_solid = buffer_instance_bone_shape_solid( g_data.passes.bone_solid, geom, g_data.transparent, sh_cfg); } float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); if (g_data.bone_box_solid != NULL) { - DRW_shgroup_call_dynamic_add(g_data.bone_box_solid, final_bonemat, bone_color, hint_color); + DRW_buffer_add_entry(g_data.bone_box_solid, final_bonemat, bone_color, hint_color); } if (outline_color[3] > 0.0f) { - DRW_shgroup_call_dynamic_add(g_data.bone_box_outline, final_bonemat, outline_color); + DRW_buffer_add_entry(g_data.bone_box_outline, final_bonemat, outline_color); } } @@ -172,15 +173,15 @@ static void drw_shgroup_bone_wire(const float (*bone_mat)[4], const eGPUShaderConfig sh_cfg) { if (g_data.bone_wire == NULL) { - g_data.bone_wire = shgroup_dynlines_flat_color(g_data.passes.bone_wire, sh_cfg); + g_data.bone_wire = buffer_dynlines_flat_color(g_data.passes.bone_wire, sh_cfg); } float head[3], tail[3]; mul_v3_m4v3(head, g_data.ob->obmat, bone_mat[3]); - DRW_shgroup_call_dynamic_add(g_data.bone_wire, head, color); + DRW_buffer_add_entry(g_data.bone_wire, head, color); add_v3_v3v3(tail, bone_mat[3], bone_mat[1]); mul_m4_v3(g_data.ob->obmat, tail); - DRW_shgroup_call_dynamic_add(g_data.bone_wire, tail, color); + DRW_buffer_add_entry(g_data.bone_wire, tail, color); } /* Stick */ @@ -192,12 +193,12 @@ static void drw_shgroup_bone_stick(const float (*bone_mat)[4], const eGPUShaderConfig sh_cfg) { if (g_data.bone_stick == NULL) { - g_data.bone_stick = shgroup_instance_bone_stick(g_data.passes.bone_wire, sh_cfg); + g_data.bone_stick = buffer_instance_bone_stick(g_data.passes.bone_wire, sh_cfg); } float final_bonemat[4][4], tail[4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); add_v3_v3v3(tail, final_bonemat[3], final_bonemat[1]); - DRW_shgroup_call_dynamic_add( + DRW_buffer_add_entry( g_data.bone_stick, final_bonemat[3], tail, col_wire, col_bone, col_head, col_tail); } @@ -210,7 +211,7 @@ static void drw_shgroup_bone_envelope_distance(const float (*bone_mat)[4], { if (g_data.passes.bone_envelope != NULL) { if (g_data.bone_envelope_distance == NULL) { - g_data.bone_envelope_distance = shgroup_instance_bone_envelope_distance( + g_data.bone_envelope_distance = buffer_instance_bone_envelope_distance( g_data.passes.bone_envelope, sh_cfg); /* passes.bone_envelope should have the DRW_STATE_CULL_FRONT state enabled. */ } @@ -225,7 +226,7 @@ static void drw_shgroup_bone_envelope_distance(const float (*bone_mat)[4], head_sphere[3] += *distance; tail_sphere[3] = *radius_tail; tail_sphere[3] += *distance; - DRW_shgroup_call_dynamic_add( + DRW_buffer_add_entry( g_data.bone_envelope_distance, head_sphere, tail_sphere, final_bonemat[0]); } } @@ -239,22 +240,19 @@ static void drw_shgroup_bone_envelope(const float (*bone_mat)[4], const eGPUShaderConfig sh_cfg) { if (g_data.bone_point_wire == NULL) { - g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.passes.bone_wire, sh_cfg); + g_data.bone_point_wire = buffer_instance_bone_sphere_outline(g_data.passes.bone_wire, sh_cfg); } if (g_data.bone_point_solid == NULL && g_data.passes.bone_solid != NULL) { - g_data.bone_point_solid = shgroup_instance_bone_sphere_solid( + g_data.bone_point_solid = buffer_instance_bone_sphere_solid( g_data.passes.bone_solid, g_data.transparent, sh_cfg); } if (g_data.bone_envelope_wire == NULL) { - g_data.bone_envelope_wire = shgroup_instance_bone_envelope_outline(g_data.passes.bone_wire, - sh_cfg); + g_data.bone_envelope_wire = buffer_instance_bone_envelope_outline(g_data.passes.bone_wire, + sh_cfg); } if (g_data.bone_envelope_solid == NULL && g_data.passes.bone_solid != NULL) { - g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid( + g_data.bone_envelope_solid = buffer_instance_bone_envelope_solid( g_data.passes.bone_solid, g_data.transparent, sh_cfg); - /* We can have a lot of overdraw if we don't do this. Also envelope are not subject to - * inverted matrix. */ - DRW_shgroup_state_enable(g_data.bone_envelope_solid, DRW_STATE_CULL_BACK); } float head_sphere[4] = {0.0f, 0.0f, 0.0f, 1.0f}, tail_sphere[4] = {0.0f, 1.0f, 0.0f, 1.0f}; @@ -272,10 +270,10 @@ static void drw_shgroup_bone_envelope(const float (*bone_mat)[4], tmp[3][3] = 1.0f; copy_v3_v3(tmp[3], tail_sphere); if (g_data.bone_point_solid != NULL) { - DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, bone_color, hint_color); + DRW_buffer_add_entry(g_data.bone_point_solid, tmp, bone_color, hint_color); } if (outline_color[3] > 0.0f) { - DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, outline_color); + DRW_buffer_add_entry(g_data.bone_point_wire, tmp, outline_color); } } else if (tail_sphere[3] < 0.0f) { @@ -285,10 +283,10 @@ static void drw_shgroup_bone_envelope(const float (*bone_mat)[4], tmp[3][3] = 1.0f; copy_v3_v3(tmp[3], head_sphere); if (g_data.bone_point_solid != NULL) { - DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, bone_color, hint_color); + DRW_buffer_add_entry(g_data.bone_point_solid, tmp, bone_color, hint_color); } if (outline_color[3] > 0.0f) { - DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, outline_color); + DRW_buffer_add_entry(g_data.bone_point_wire, tmp, outline_color); } } else { @@ -305,15 +303,15 @@ static void drw_shgroup_bone_envelope(const float (*bone_mat)[4], interp_v4_v4v4(head_sphere, tail_sphere, head_sphere, fac_head); interp_v4_v4v4(tail_sphere, tmp_sphere, tail_sphere, fac_tail); if (g_data.bone_envelope_solid != NULL) { - DRW_shgroup_call_dynamic_add(g_data.bone_envelope_solid, - head_sphere, - tail_sphere, - bone_color, - hint_color, - final_bonemat[0]); + DRW_buffer_add_entry(g_data.bone_envelope_solid, + head_sphere, + tail_sphere, + bone_color, + hint_color, + final_bonemat[0]); } if (outline_color[3] > 0.0f) { - DRW_shgroup_call_dynamic_add( + DRW_buffer_add_entry( g_data.bone_envelope_wire, head_sphere, tail_sphere, outline_color, final_bonemat[0]); } } @@ -325,10 +323,10 @@ static void drw_shgroup_bone_envelope(const float (*bone_mat)[4], tmp[3][3] = 1.0f; copy_v3_v3(tmp[3], tmp_sphere); if (g_data.bone_point_solid != NULL) { - DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, bone_color, hint_color); + DRW_buffer_add_entry(g_data.bone_point_solid, tmp, bone_color, hint_color); } if (outline_color[3] > 0.0f) { - DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, outline_color); + DRW_buffer_add_entry(g_data.bone_point_wire, tmp, outline_color); } } } @@ -336,6 +334,7 @@ static void drw_shgroup_bone_envelope(const float (*bone_mat)[4], /* Custom (geometry) */ +extern void drw_batch_cache_validate(Object *custom); extern void drw_batch_cache_generate_requested(Object *custom); static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4], @@ -345,6 +344,10 @@ static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4], const eGPUShaderConfig sh_cfg, Object *custom) { + /* TODO(fclem) arg... less than ideal but we never iter on this object + * to assure batch cache is valid. */ + drw_batch_cache_validate(custom); + struct GPUBatch *surf = DRW_cache_object_surface_get(custom); struct GPUBatch *edges = DRW_cache_object_edge_detection_get(custom, NULL); struct GPUBatch *ledges = DRW_cache_object_loose_edges_get(custom); @@ -357,50 +360,50 @@ static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4], BLI_assert(g_data.passes.custom_shapes != NULL); if (surf && g_data.passes.bone_solid != NULL) { - DRWShadingGroup *shgrp_geom_solid = BLI_ghash_lookup(g_data.passes.custom_shapes, surf); + DRWCallBuffer *buf_geom_solid = BLI_ghash_lookup(g_data.passes.custom_shapes, surf); - if (shgrp_geom_solid == NULL) { + if (buf_geom_solid == NULL) { /* TODO(fclem) needs to be moved elsewhere. */ drw_batch_cache_generate_requested(custom); /* NOTE! g_data.transparent require a separate shading group if the * object is transparent. This is done by passing a different ghash * for transparent armature in pose mode. */ - shgrp_geom_solid = shgroup_instance_bone_shape_solid( + buf_geom_solid = buffer_instance_bone_shape_solid( g_data.passes.bone_solid, surf, g_data.transparent, sh_cfg); - BLI_ghash_insert(g_data.passes.custom_shapes, surf, shgrp_geom_solid); + BLI_ghash_insert(g_data.passes.custom_shapes, surf, buf_geom_solid); } - DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, bone_color, hint_color); + DRW_buffer_add_entry(buf_geom_solid, final_bonemat, bone_color, hint_color); } if (edges && outline_color[3] > 0.0f) { - DRWShadingGroup *shgrp_geom_wire = BLI_ghash_lookup(g_data.passes.custom_shapes, edges); + DRWCallBuffer *buf_geom_wire = BLI_ghash_lookup(g_data.passes.custom_shapes, edges); - if (shgrp_geom_wire == NULL) { + if (buf_geom_wire == NULL) { /* TODO(fclem) needs to be moved elsewhere. */ drw_batch_cache_generate_requested(custom); - shgrp_geom_wire = shgroup_instance_bone_shape_outline( + buf_geom_wire = buffer_instance_bone_shape_outline( g_data.passes.bone_outline, edges, sh_cfg); - BLI_ghash_insert(g_data.passes.custom_shapes, edges, shgrp_geom_wire); + BLI_ghash_insert(g_data.passes.custom_shapes, edges, buf_geom_wire); } - DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, outline_color); + DRW_buffer_add_entry(buf_geom_wire, final_bonemat, outline_color); } if (ledges) { - DRWShadingGroup *shgrp_geom_ledges = BLI_ghash_lookup(g_data.passes.custom_shapes, ledges); + DRWCallBuffer *buf_geom_ledges = BLI_ghash_lookup(g_data.passes.custom_shapes, ledges); - if (shgrp_geom_ledges == NULL) { + if (buf_geom_ledges == NULL) { /* TODO(fclem) needs to be moved elsewhere. */ drw_batch_cache_generate_requested(custom); - shgrp_geom_ledges = shgroup_instance_wire(g_data.passes.bone_wire, ledges); + buf_geom_ledges = buffer_instance_wire(g_data.passes.bone_wire, ledges); - BLI_ghash_insert(g_data.passes.custom_shapes, ledges, shgrp_geom_ledges); + BLI_ghash_insert(g_data.passes.custom_shapes, ledges, buf_geom_ledges); } float final_color[4] = {outline_color[0], outline_color[1], outline_color[2], 1.0f}; - DRW_shgroup_call_dynamic_add(shgrp_geom_ledges, final_bonemat, final_color); + DRW_buffer_add_entry(buf_geom_ledges, final_bonemat, final_color); } } @@ -408,23 +411,27 @@ static void drw_shgroup_bone_custom_wire(const float (*bone_mat)[4], const float color[4], Object *custom) { + /* TODO(fclem) arg... less than ideal but we never iter on this object + * to assure batch cache is valid. */ + drw_batch_cache_validate(custom); + struct GPUBatch *geom = DRW_cache_object_all_edges_get(custom); if (geom) { - DRWShadingGroup *shgrp_geom_wire = BLI_ghash_lookup(g_data.passes.custom_shapes, geom); + DRWCallBuffer *buf_geom_wire = BLI_ghash_lookup(g_data.passes.custom_shapes, geom); - if (shgrp_geom_wire == NULL) { + if (buf_geom_wire == NULL) { /* TODO(fclem) needs to be moved elsewhere. */ drw_batch_cache_generate_requested(custom); - shgrp_geom_wire = shgroup_instance_wire(g_data.passes.bone_wire, geom); + buf_geom_wire = buffer_instance_wire(g_data.passes.bone_wire, geom); - BLI_ghash_insert(g_data.passes.custom_shapes, geom, shgrp_geom_wire); + BLI_ghash_insert(g_data.passes.custom_shapes, geom, buf_geom_wire); } float final_color[4] = {color[0], color[1], color[2], 1.0f}; float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); - DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, final_color); + DRW_buffer_add_entry(buf_geom_wire, final_bonemat, final_color); } } @@ -436,19 +443,19 @@ static void drw_shgroup_bone_point(const float (*bone_mat)[4], const eGPUShaderConfig sh_cfg) { if (g_data.bone_point_wire == NULL) { - g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.passes.bone_wire, sh_cfg); + g_data.bone_point_wire = buffer_instance_bone_sphere_outline(g_data.passes.bone_wire, sh_cfg); } if (g_data.bone_point_solid == NULL && g_data.passes.bone_solid != NULL) { - g_data.bone_point_solid = shgroup_instance_bone_sphere_solid( + g_data.bone_point_solid = buffer_instance_bone_sphere_solid( g_data.passes.bone_solid, g_data.transparent, sh_cfg); } float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); if (g_data.bone_point_solid != NULL) { - DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, final_bonemat, bone_color, hint_color); + DRW_buffer_add_entry(g_data.bone_point_solid, final_bonemat, bone_color, hint_color); } if (outline_color[3] > 0.0f) { - DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, final_bonemat, outline_color); + DRW_buffer_add_entry(g_data.bone_point_wire, final_bonemat, outline_color); } } @@ -458,11 +465,11 @@ static void drw_shgroup_bone_axes(const float (*bone_mat)[4], const eGPUShaderConfig sh_cfg) { if (g_data.bone_axes == NULL) { - g_data.bone_axes = shgroup_instance_bone_axes(g_data.passes.bone_axes, sh_cfg); + g_data.bone_axes = buffer_instance_bone_axes(g_data.passes.bone_axes, sh_cfg); } float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); - DRW_shgroup_call_dynamic_add(g_data.bone_axes, final_bonemat, color); + DRW_buffer_add_entry(g_data.bone_axes, final_bonemat, color); } /* Relationship lines */ @@ -471,15 +478,15 @@ static void drw_shgroup_bone_relationship_lines(const float start[3], const eGPUShaderConfig sh_cfg) { if (g_data.lines_relationship == NULL) { - g_data.lines_relationship = shgroup_dynlines_dashed_uniform_color( + g_data.lines_relationship = buffer_dynlines_dashed_uniform_color( g_data.passes.relationship_lines, g_theme.wire_color, sh_cfg); } /* reverse order to have less stipple overlap */ float v[3]; mul_v3_m4v3(v, g_data.ob->obmat, end); - DRW_shgroup_call_dynamic_add(g_data.lines_relationship, v); + DRW_buffer_add_entry(g_data.lines_relationship, v); mul_v3_m4v3(v, g_data.ob->obmat, start); - DRW_shgroup_call_dynamic_add(g_data.lines_relationship, v); + DRW_buffer_add_entry(g_data.lines_relationship, v); } static void drw_shgroup_bone_ik_lines(const float start[3], @@ -488,15 +495,15 @@ static void drw_shgroup_bone_ik_lines(const float start[3], { if (g_data.lines_ik == NULL) { static float fcolor[4] = {0.8f, 0.5f, 0.0f, 1.0f}; /* add theme! */ - g_data.lines_ik = shgroup_dynlines_dashed_uniform_color( + g_data.lines_ik = buffer_dynlines_dashed_uniform_color( g_data.passes.relationship_lines, fcolor, sh_cfg); } /* reverse order to have less stipple overlap */ float v[3]; mul_v3_m4v3(v, g_data.ob->obmat, end); - DRW_shgroup_call_dynamic_add(g_data.lines_ik, v); + DRW_buffer_add_entry(g_data.lines_ik, v); mul_v3_m4v3(v, g_data.ob->obmat, start); - DRW_shgroup_call_dynamic_add(g_data.lines_ik, v); + DRW_buffer_add_entry(g_data.lines_ik, v); } static void drw_shgroup_bone_ik_no_target_lines(const float start[3], @@ -505,15 +512,15 @@ static void drw_shgroup_bone_ik_no_target_lines(const float start[3], { if (g_data.lines_ik_no_target == NULL) { static float fcolor[4] = {0.8f, 0.8f, 0.2f, 1.0f}; /* add theme! */ - g_data.lines_ik_no_target = shgroup_dynlines_dashed_uniform_color( + g_data.lines_ik_no_target = buffer_dynlines_dashed_uniform_color( g_data.passes.relationship_lines, fcolor, sh_cfg); } /* reverse order to have less stipple overlap */ float v[3]; mul_v3_m4v3(v, g_data.ob->obmat, end); - DRW_shgroup_call_dynamic_add(g_data.lines_ik_no_target, v); + DRW_buffer_add_entry(g_data.lines_ik_no_target, v); mul_v3_m4v3(v, g_data.ob->obmat, start); - DRW_shgroup_call_dynamic_add(g_data.lines_ik_no_target, v); + DRW_buffer_add_entry(g_data.lines_ik_no_target, v); } static void drw_shgroup_bone_ik_spline_lines(const float start[3], @@ -522,15 +529,15 @@ static void drw_shgroup_bone_ik_spline_lines(const float start[3], { if (g_data.lines_ik_spline == NULL) { static float fcolor[4] = {0.8f, 0.8f, 0.2f, 1.0f}; /* add theme! */ - g_data.lines_ik_spline = shgroup_dynlines_dashed_uniform_color( + g_data.lines_ik_spline = buffer_dynlines_dashed_uniform_color( g_data.passes.relationship_lines, fcolor, sh_cfg); } /* reverse order to have less stipple overlap */ float v[3]; mul_v3_m4v3(v, g_data.ob->obmat, end); - DRW_shgroup_call_dynamic_add(g_data.lines_ik_spline, v); + DRW_buffer_add_entry(g_data.lines_ik_spline, v); mul_v3_m4v3(v, g_data.ob->obmat, start); - DRW_shgroup_call_dynamic_add(g_data.lines_ik_spline, v); + DRW_buffer_add_entry(g_data.lines_ik_spline, v); } /** \} */ @@ -1634,12 +1641,10 @@ static void draw_bone_dofs(bPoseChannel *pchan) } if (g_data.bone_dof_sphere == NULL) { - g_data.bone_dof_lines = shgroup_instance_bone_dof(g_data.passes.bone_wire, - DRW_cache_bone_dof_lines_get()); - g_data.bone_dof_sphere = shgroup_instance_bone_dof(g_data.passes.bone_envelope, - DRW_cache_bone_dof_sphere_get()); - DRW_shgroup_state_enable(g_data.bone_dof_sphere, DRW_STATE_BLEND); - DRW_shgroup_state_disable(g_data.bone_dof_sphere, DRW_STATE_CULL_FRONT); + g_data.bone_dof_lines = buffer_instance_bone_dof( + g_data.passes.bone_wire, DRW_cache_bone_dof_lines_get(), false); + g_data.bone_dof_sphere = buffer_instance_bone_dof( + g_data.passes.bone_envelope, DRW_cache_bone_dof_sphere_get(), true); } /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */ @@ -1672,20 +1677,20 @@ static void draw_bone_dofs(bPoseChannel *pchan) amax[0] = xminmax[1]; amin[1] = zminmax[0]; amax[1] = zminmax[1]; - DRW_shgroup_call_dynamic_add(g_data.bone_dof_sphere, final_bonemat, col_sphere, amin, amax); - DRW_shgroup_call_dynamic_add(g_data.bone_dof_lines, final_bonemat, col_lines, amin, amax); + DRW_buffer_add_entry(g_data.bone_dof_sphere, final_bonemat, col_sphere, amin, amax); + DRW_buffer_add_entry(g_data.bone_dof_lines, final_bonemat, col_lines, amin, amax); } if (pchan->ikflag & BONE_IK_XLIMIT) { amin[0] = xminmax[0]; amax[0] = xminmax[1]; amin[1] = amax[1] = 0.0f; - DRW_shgroup_call_dynamic_add(g_data.bone_dof_lines, final_bonemat, col_xaxis, amin, amax); + DRW_buffer_add_entry(g_data.bone_dof_lines, final_bonemat, col_xaxis, amin, amax); } if (pchan->ikflag & BONE_IK_ZLIMIT) { amin[1] = zminmax[0]; amax[1] = zminmax[1]; amin[0] = amax[0] = 0.0f; - DRW_shgroup_call_dynamic_add(g_data.bone_dof_lines, final_bonemat, col_zaxis, amin, amax); + DRW_buffer_add_entry(g_data.bone_dof_lines, final_bonemat, col_zaxis, amin, amax); } } @@ -1839,7 +1844,9 @@ static void draw_armature_edit(Object *ob) const bool show_text = DRW_state_show_text(); const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0); - for (eBone = arm->edbo->first, index = ob->select_id; eBone; + const Object *orig_object = DEG_get_original_object(ob); + + for (eBone = arm->edbo->first, index = orig_object->runtime.select_id; eBone; eBone = eBone->next, index += 0x10000) { if (eBone->layer & arm->layer) { if ((eBone->flag & BONE_HIDDEN_A) == 0) { @@ -1934,7 +1941,8 @@ static void draw_armature_pose(Object *ob, const float const_color[4]) } if (arm->flag & ARM_POSEMODE) { - index = ob->select_id; + const Object *orig_object = DEG_get_original_object(ob); + index = orig_object->runtime.select_id; } } diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 08cf56982ea..c40e9772340 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -46,6 +46,9 @@ /* Batch's only (free'd as an array) */ static struct DRWShapeCache { + GPUBatch *drw_procedural_verts; + GPUBatch *drw_procedural_lines; + GPUBatch *drw_procedural_tris; GPUBatch *drw_single_vertice; GPUBatch *drw_cursor; GPUBatch *drw_cursor_only_circle; @@ -138,6 +141,54 @@ void DRW_shape_cache_reset(void) } /* -------------------------------------------------------------------- */ +/** \name Procedural Batches + * \{ */ + +GPUBatch *drw_cache_procedural_points_get(void) +{ + if (!SHC.drw_procedural_verts) { + /* TODO(fclem) get rid of this dummy VBO. */ + GPUVertFormat format = {0}; + GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, 1); + + SHC.drw_procedural_verts = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO); + } + return SHC.drw_procedural_verts; +} + +GPUBatch *drw_cache_procedural_lines_get(void) +{ + if (!SHC.drw_procedural_lines) { + /* TODO(fclem) get rid of this dummy VBO. */ + GPUVertFormat format = {0}; + GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, 1); + + SHC.drw_procedural_lines = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO); + } + return SHC.drw_procedural_lines; +} + +GPUBatch *drw_cache_procedural_triangles_get(void) +{ + if (!SHC.drw_procedural_tris) { + /* TODO(fclem) get rid of this dummy VBO. */ + GPUVertFormat format = {0}; + GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, 1); + + SHC.drw_procedural_tris = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO); + } + return SHC.drw_procedural_tris; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Helper functions * \{ */ @@ -3953,68 +4004,32 @@ GPUBatch *DRW_cache_cursor_get(bool crosshair_lines) /** \name Batch Cache Impl. common * \{ */ -GPUBatch *DRW_batch_request(GPUBatch **batch) +void drw_batch_cache_validate(Object *ob) { - /* XXX TODO(fclem): We are writting to batch cache here. Need to make this thread safe. */ - if (*batch == NULL) { - *batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch"); - } - return *batch; -} - -bool DRW_batch_requested(GPUBatch *batch, int prim_type) -{ - /* Batch has been requested if it has been created but not initialized. */ - if (batch != NULL && batch->verts[0] == NULL) { - /* HACK. We init without a valid VBO and let the first vbo binding - * fill verts[0]. */ - GPU_batch_init_ex(batch, prim_type, (GPUVertBuf *)1, NULL, 0); - batch->verts[0] = NULL; - return true; - } - return false; -} - -void DRW_ibo_request(GPUBatch *batch, GPUIndexBuf **ibo) -{ - if (*ibo == NULL) { - *ibo = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf"); - } - GPU_batch_vao_cache_clear(batch); - batch->elem = *ibo; -} - -bool DRW_ibo_requested(GPUIndexBuf *ibo) -{ - /* TODO do not rely on data uploaded. This prevents multithreading. - * (need access to a gl context) */ - return (ibo != NULL && ibo->ibo_id == 0 && ibo->data == NULL); -} - -void DRW_vbo_request(GPUBatch *batch, GPUVertBuf **vbo) -{ - if (*vbo == NULL) { - *vbo = MEM_callocN(sizeof(GPUVertBuf), "GPUVertBuf"); - } - /* HACK set first vbo if not init. */ - if (batch->verts[0] == NULL) { - GPU_batch_vao_cache_clear(batch); - batch->verts[0] = *vbo; - } - else { - /* HACK: bypass assert */ - int vbo_vert_len = (*vbo)->vertex_len; - (*vbo)->vertex_len = batch->verts[0]->vertex_len; - GPU_batch_vertbuf_add(batch, *vbo); - (*vbo)->vertex_len = vbo_vert_len; + struct Mesh *mesh_eval = ob->runtime.mesh_eval; + switch (ob->type) { + case OB_MESH: + DRW_mesh_batch_cache_validate((Mesh *)ob->data); + break; + case OB_CURVE: + case OB_FONT: + case OB_SURF: + if (mesh_eval != NULL) { + DRW_mesh_batch_cache_validate(mesh_eval); + } + DRW_curve_batch_cache_validate((Curve *)ob->data); + break; + case OB_MBALL: + DRW_mball_batch_cache_validate((MetaBall *)ob->data); + break; + case OB_LATTICE: + DRW_lattice_batch_cache_validate((Lattice *)ob->data); + break; + default: + break; } } -bool DRW_vbo_requested(GPUVertBuf *vbo) -{ - return (vbo != NULL && vbo->format.attr_len == 0); -} - void drw_batch_cache_generate_requested(Object *ob) { const DRWContextState *draw_ctx = DRW_context_state_get(); diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 508ae678778..4dc58972ce6 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -44,15 +44,19 @@ struct bGPdata; /* Expose via BKE callbacks */ void DRW_mball_batch_cache_dirty_tag(struct MetaBall *mb, int mode); +void DRW_mball_batch_cache_validate(struct MetaBall *mb); void DRW_mball_batch_cache_free(struct MetaBall *mb); void DRW_curve_batch_cache_dirty_tag(struct Curve *cu, int mode); +void DRW_curve_batch_cache_validate(struct Curve *cu); void DRW_curve_batch_cache_free(struct Curve *cu); void DRW_mesh_batch_cache_dirty_tag(struct Mesh *me, int mode); +void DRW_mesh_batch_cache_validate(struct Mesh *me); void DRW_mesh_batch_cache_free(struct Mesh *me); void DRW_lattice_batch_cache_dirty_tag(struct Lattice *lt, int mode); +void DRW_lattice_batch_cache_validate(struct Lattice *lt); void DRW_lattice_batch_cache_free(struct Lattice *lt); void DRW_particle_batch_cache_dirty_tag(struct ParticleSystem *psys, int mode); @@ -202,30 +206,4 @@ struct GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(struct Object *ob struct ParticleSystem *psys, struct PTCacheEdit *edit); -/* Common */ -// #define DRW_DEBUG_MESH_CACHE_REQUEST - -#ifdef DRW_DEBUG_MESH_CACHE_REQUEST -# define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value) \ - (flag |= DRW_vbo_requested(vbo) ? (printf(" VBO requested " #vbo "\n") ? value : value) : 0) -# define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value) \ - (flag |= DRW_ibo_requested(ibo) ? (printf(" IBO requested " #ibo "\n") ? value : value) : 0) -#else -# define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value) \ - (flag |= DRW_vbo_requested(vbo) ? (value) : 0) -# define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value) \ - (flag |= DRW_ibo_requested(ibo) ? (value) : 0) -#endif - -/* Test and assign NULL if test fails */ -#define DRW_TEST_ASSIGN_VBO(v) (v = (DRW_vbo_requested(v) ? (v) : NULL)) -#define DRW_TEST_ASSIGN_IBO(v) (v = (DRW_ibo_requested(v) ? (v) : NULL)) - -struct GPUBatch *DRW_batch_request(struct GPUBatch **batch); -bool DRW_batch_requested(struct GPUBatch *batch, int prim_type); -void DRW_ibo_request(struct GPUBatch *batch, struct GPUIndexBuf **ibo); -bool DRW_ibo_requested(struct GPUIndexBuf *ibo); -void DRW_vbo_request(struct GPUBatch *batch, struct GPUVertBuf **vbo); -bool DRW_vbo_requested(struct GPUVertBuf *vbo); - #endif /* __DRAW_CACHE_IMPL_H__ */ diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c index 33b872109a5..663fbf647a6 100644 --- a/source/blender/draw/intern/draw_cache_impl_curve.c +++ b/source/blender/draw/intern/draw_cache_impl_curve.c @@ -42,6 +42,8 @@ #include "DRW_render.h" +#include "draw_cache_inline.h" + #include "draw_cache_impl.h" /* own include */ #define SELECT 1 @@ -472,12 +474,16 @@ static void curve_batch_cache_init(Curve *cu) cache->is_dirty = false; } -static CurveBatchCache *curve_batch_cache_get(Curve *cu) +void DRW_curve_batch_cache_validate(Curve *cu) { if (!curve_batch_cache_valid(cu)) { curve_batch_cache_clear(cu); curve_batch_cache_init(cu); } +} + +static CurveBatchCache *curve_batch_cache_get(Curve *cu) +{ return cu->batch_cache; } diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c index ea394359b05..d1c214c2aa6 100644 --- a/source/blender/draw/intern/draw_cache_impl_displist.c +++ b/source/blender/draw/intern/draw_cache_impl_displist.c @@ -37,6 +37,8 @@ #include "GPU_batch.h" #include "GPU_extensions.h" +#include "draw_cache_inline.h" + #include "draw_cache_impl.h" /* own include */ static int dl_vert_len(const DispList *dl) @@ -402,7 +404,6 @@ void DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv(ListBase *lb, &format_pos_nor, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); attr_id.nor = GPU_vertformat_attr_add( &format_pos_nor, "nor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); - GPU_vertformat_triple_load(&format_pos_nor); /* UVs are in [0..1] range. We can compress them. */ attr_id.uv = GPU_vertformat_attr_add( &format_uv, "u", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT); diff --git a/source/blender/draw/intern/draw_cache_impl_lattice.c b/source/blender/draw/intern/draw_cache_impl_lattice.c index b5223bc047c..8b3864684b5 100644 --- a/source/blender/draw/intern/draw_cache_impl_lattice.c +++ b/source/blender/draw/intern/draw_cache_impl_lattice.c @@ -340,12 +340,16 @@ static void lattice_batch_cache_init(Lattice *lt) cache->is_dirty = false; } -static LatticeBatchCache *lattice_batch_cache_get(Lattice *lt) +void DRW_lattice_batch_cache_validate(Lattice *lt) { if (!lattice_batch_cache_valid(lt)) { lattice_batch_cache_clear(lt); lattice_batch_cache_init(lt); } +} + +static LatticeBatchCache *lattice_batch_cache_get(Lattice *lt) +{ return lt->batch_cache; } diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index f3b7e7adff0..eb626e2f954 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -61,6 +61,8 @@ #include "ED_mesh.h" #include "ED_uvedit.h" +#include "draw_cache_inline.h" + #include "draw_cache_impl.h" /* own include */ static void mesh_batch_cache_clear(Mesh *me); @@ -421,13 +423,13 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, const CustomData *cd_ldata = (me->edit_mesh) ? &me->edit_mesh->bm->ldata : &me->ldata; /* See: DM_vertex_attributes_from_gpu for similar logic */ - GPUVertAttrLayers gpu_attrs = {{{0}}}; DRW_MeshCDMask cd_used; mesh_cd_layers_type_clear(&cd_used); for (int i = 0; i < gpumat_array_len; i++) { GPUMaterial *gpumat = gpumat_array[i]; if (gpumat) { + GPUVertAttrLayers gpu_attrs; GPU_material_vertex_attrs(gpumat, &gpu_attrs); for (int j = 0; j < gpu_attrs.totlayer; j++) { const char *name = gpu_attrs.layer[j].name; @@ -1140,11 +1142,12 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me, rdata->cd.layers.tangent_len); int i_dst = 0; + int act_tan = rdata->cd.layers.tangent_active; for (int i_src = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) { if ((cd_used->tan & (1 << i_src)) == 0) { i_dst--; if (rdata->cd.layers.tangent_active >= i_src) { - rdata->cd.layers.tangent_active--; + act_tan--; } } else { @@ -1168,6 +1171,11 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me, } } } + if (rdata->cd.layers.tangent_active != -1) { + /* Actual active UV slot inside uv layers used for shading. */ + rdata->cd.layers.tangent_active = act_tan; + } + if (cd_used->tan_orco != 0) { const char *name = CustomData_get_layer_name(&rdata->cd.output.ldata, CD_TANGENT, i_dst); uint hash = BLI_ghashutil_strhash_p(name); @@ -1892,6 +1900,39 @@ static void drw_mesh_weight_state_extract(Object *ob, /** \name Mesh GPUBatch Cache * \{ */ +typedef enum DRWBatchFlag { + MBC_SURFACE = (1 << 0), + MBC_SURFACE_WEIGHTS = (1 << 1), + MBC_EDIT_TRIANGLES = (1 << 2), + MBC_EDIT_VERTICES = (1 << 3), + MBC_EDIT_EDGES = (1 << 4), + MBC_EDIT_LNOR = (1 << 5), + MBC_EDIT_FACEDOTS = (1 << 6), + MBC_EDIT_MESH_ANALYSIS = (1 << 7), + MBC_EDITUV_FACES_STRECH_AREA = (1 << 8), + MBC_EDITUV_FACES_STRECH_ANGLE = (1 << 9), + MBC_EDITUV_FACES = (1 << 10), + MBC_EDITUV_EDGES = (1 << 11), + MBC_EDITUV_VERTS = (1 << 12), + MBC_EDITUV_FACEDOTS = (1 << 13), + MBC_EDIT_SELECTION_VERTS = (1 << 14), + MBC_EDIT_SELECTION_EDGES = (1 << 15), + MBC_EDIT_SELECTION_FACES = (1 << 16), + MBC_EDIT_SELECTION_FACEDOTS = (1 << 17), + MBC_ALL_VERTS = (1 << 18), + MBC_ALL_EDGES = (1 << 19), + MBC_LOOSE_EDGES = (1 << 20), + MBC_EDGE_DETECTION = (1 << 21), + MBC_WIRE_EDGES = (1 << 22), + MBC_WIRE_LOOPS = (1 << 23), + MBC_WIRE_LOOPS_UVS = (1 << 24), + MBC_SURF_PER_MAT = (1 << 25), +} DRWBatchFlag; + +#define MBC_EDITUV \ + (MBC_EDITUV_FACES_STRECH_AREA | MBC_EDITUV_FACES_STRECH_ANGLE | MBC_EDITUV_FACES | \ + MBC_EDITUV_EDGES | MBC_EDITUV_VERTS | MBC_EDITUV_FACEDOTS) + typedef struct MeshBatchCache { /* In order buffers: All verts only specified once * or once per loop. To be used with a GPUIndexBuf. */ @@ -1997,14 +2038,16 @@ typedef struct MeshBatchCache { int *auto_layer_is_srgb; int auto_layer_len; + DRWBatchFlag batch_requested; + DRWBatchFlag batch_ready; + /* settings to determine if cache is invalid */ - bool is_maybe_dirty; - bool is_dirty; /* Instantly invalidates cache, skipping mesh check */ int edge_len; int tri_len; int poly_len; int vert_len; int mat_len; + bool is_dirty; /* Instantly invalidates cache, skipping mesh check */ bool is_editmode; bool is_uvsyncsel; @@ -2014,13 +2057,15 @@ typedef struct MeshBatchCache { int lastmatch; - /* XXX, only keep for as long as sculpt mode uses shaded drawing. */ - bool is_sculpt_points_tag; - /* Valid only if edge_detection is up to date. */ bool is_manifold; } MeshBatchCache; +BLI_INLINE void mesh_batch_cache_add_request(MeshBatchCache *cache, DRWBatchFlag new_flag) +{ + atomic_fetch_and_or_uint32((uint32_t *)(&cache->batch_requested), *(uint32_t *)&new_flag); +} + /* GPUBatch cache management. */ static bool mesh_batch_cache_valid(Mesh *me) @@ -2031,10 +2076,6 @@ static bool mesh_batch_cache_valid(Mesh *me) return false; } - if (cache->mat_len != mesh_render_mat_len_get(me)) { - return false; - } - if (cache->is_editmode != (me->edit_mesh != NULL)) { return false; } @@ -2043,20 +2084,8 @@ static bool mesh_batch_cache_valid(Mesh *me) return false; } - if (cache->is_maybe_dirty == false) { - return true; - } - else { - if (cache->is_editmode) { - return false; - } - else if ((cache->vert_len != mesh_render_verts_len_get(me)) || - (cache->edge_len != mesh_render_edges_len_get(me)) || - (cache->tri_len != mesh_render_looptri_len_get(me)) || - (cache->poly_len != mesh_render_polys_len_get(me)) || - (cache->mat_len != mesh_render_mat_len_get(me))) { - return false; - } + if (cache->mat_len != mesh_render_mat_len_get(me)) { + return false; } return true; @@ -2087,18 +2116,23 @@ static void mesh_batch_cache_init(Mesh *me) __func__); cache->surf_per_mat = MEM_callocN(sizeof(*cache->surf_per_mat) * cache->mat_len, __func__); - cache->is_maybe_dirty = false; cache->is_dirty = false; + cache->batch_ready = 0; + cache->batch_requested = 0; drw_mesh_weight_state_clear(&cache->weight_state); } -static MeshBatchCache *mesh_batch_cache_get(Mesh *me) +void DRW_mesh_batch_cache_validate(Mesh *me) { if (!mesh_batch_cache_valid(me)) { mesh_batch_cache_clear(me); mesh_batch_cache_init(me); } +} + +static MeshBatchCache *mesh_batch_cache_get(Mesh *me) +{ return me->runtime.batch_cache; } @@ -2109,6 +2143,8 @@ static void mesh_batch_cache_check_vertex_group(MeshBatchCache *cache, GPU_BATCH_CLEAR_SAFE(cache->batch.surface_weights); GPU_VERTBUF_DISCARD_SAFE(cache->ordered.weights); + cache->batch_ready &= ~MBC_SURFACE_WEIGHTS; + drw_mesh_weight_state_clear(&cache->weight_state); } } @@ -2133,6 +2169,8 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache) } MEM_SAFE_FREE(cache->surf_per_mat); + cache->batch_ready &= ~MBC_SURF_PER_MAT; + MEM_SAFE_FREE(cache->auto_layer_names); MEM_SAFE_FREE(cache->auto_layer_is_srgb); @@ -2158,6 +2196,8 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache) GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_edges); GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_verts); GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_facedots); + + cache->batch_ready &= ~MBC_EDITUV; } void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) @@ -2167,9 +2207,6 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) return; } switch (mode) { - case BKE_MESH_BATCH_DIRTY_MAYBE_ALL: - cache->is_maybe_dirty = true; - break; case BKE_MESH_BATCH_DIRTY_SELECT: GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_data); GPU_VERTBUF_DISCARD_SAFE(cache->edit.facedots_pos_nor_data); @@ -2178,6 +2215,8 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) GPU_BATCH_DISCARD_SAFE(cache->batch.edit_edges); GPU_BATCH_DISCARD_SAFE(cache->batch.edit_facedots); GPU_BATCH_DISCARD_SAFE(cache->batch.edit_mesh_analysis); + cache->batch_ready &= ~(MBC_EDIT_TRIANGLES | MBC_EDIT_VERTICES | MBC_EDIT_EDGES | + MBC_EDIT_FACEDOTS | MBC_EDIT_MESH_ANALYSIS); /* Because visible UVs depends on edit mode selection, discard everything. */ mesh_batch_cache_discard_uvedit(cache); break; @@ -2192,6 +2231,7 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) GPU_BATCH_DISCARD_SAFE(cache->surf_per_mat[i]); } } + cache->batch_ready &= ~(MBC_SURFACE | MBC_WIRE_LOOPS | MBC_SURF_PER_MAT); break; case BKE_MESH_BATCH_DIRTY_ALL: cache->is_dirty = true; @@ -2200,9 +2240,6 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) mesh_batch_cache_discard_shaded_tri(cache); mesh_batch_cache_discard_uvedit(cache); break; - case BKE_MESH_BATCH_DIRTY_SCULPT_COORDS: - cache->is_sculpt_points_tag = true; - break; case BKE_MESH_BATCH_DIRTY_UVEDIT_ALL: mesh_batch_cache_discard_uvedit(cache); break; @@ -2215,6 +2252,7 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_edges); GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_verts); GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_facedots); + cache->batch_ready &= ~MBC_EDITUV; break; default: BLI_assert(0); @@ -2249,6 +2287,8 @@ static void mesh_batch_cache_clear(Mesh *me) mesh_batch_cache_discard_uvedit(cache); + cache->batch_ready = 0; + drw_mesh_weight_state_clear(&cache->weight_state); } @@ -4227,36 +4267,42 @@ static void texpaint_request_active_vcol(MeshBatchCache *cache, Mesh *me) GPUBatch *DRW_mesh_batch_cache_get_all_verts(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_ALL_VERTS); return DRW_batch_request(&cache->batch.all_verts); } GPUBatch *DRW_mesh_batch_cache_get_all_edges(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_ALL_EDGES); return DRW_batch_request(&cache->batch.all_edges); } GPUBatch *DRW_mesh_batch_cache_get_surface(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_SURFACE); return DRW_batch_request(&cache->batch.surface); } GPUBatch *DRW_mesh_batch_cache_get_loose_edges(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_LOOSE_EDGES); return DRW_batch_request(&cache->batch.loose_edges); } GPUBatch *DRW_mesh_batch_cache_get_surface_weights(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_SURFACE_WEIGHTS); return DRW_batch_request(&cache->batch.surface_weights); } GPUBatch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDGE_DETECTION); /* Even if is_manifold is not correct (not updated), * the default (not manifold) is just the worst case. */ if (r_is_manifold) { @@ -4268,12 +4314,14 @@ GPUBatch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold) GPUBatch *DRW_mesh_batch_cache_get_wireframes_face(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_WIRE_EDGES); return DRW_batch_request(&cache->batch.wire_edges); } GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDIT_MESH_ANALYSIS); return DRW_batch_request(&cache->batch.edit_mesh_analysis); } @@ -4299,6 +4347,8 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me, &cache->auto_layer_len); } + mesh_batch_cache_add_request(cache, MBC_SURF_PER_MAT); + if (auto_layer_names) { *auto_layer_names = cache->auto_layer_names; *auto_layer_is_srgb = cache->auto_layer_is_srgb; @@ -4313,6 +4363,7 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me, GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_SURF_PER_MAT); texpaint_request_active_uv(cache, me); for (int i = 0; i < cache->mat_len; ++i) { DRW_batch_request(&cache->surf_per_mat[i]); @@ -4324,6 +4375,7 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); texpaint_request_active_uv(cache, me); + mesh_batch_cache_add_request(cache, MBC_SURFACE); return DRW_batch_request(&cache->batch.surface); } @@ -4331,6 +4383,7 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); texpaint_request_active_vcol(cache, me); + mesh_batch_cache_add_request(cache, MBC_SURFACE); return DRW_batch_request(&cache->batch.surface); } @@ -4343,30 +4396,35 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Mesh *me) GPUBatch *DRW_mesh_batch_cache_get_edit_triangles(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDIT_TRIANGLES); return DRW_batch_request(&cache->batch.edit_triangles); } GPUBatch *DRW_mesh_batch_cache_get_edit_edges(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDIT_EDGES); return DRW_batch_request(&cache->batch.edit_edges); } GPUBatch *DRW_mesh_batch_cache_get_edit_vertices(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDIT_VERTICES); return DRW_batch_request(&cache->batch.edit_vertices); } GPUBatch *DRW_mesh_batch_cache_get_edit_lnors(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDIT_LNOR); return DRW_batch_request(&cache->batch.edit_lnor); } GPUBatch *DRW_mesh_batch_cache_get_edit_facedots(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDIT_FACEDOTS); return DRW_batch_request(&cache->batch.edit_facedots); } @@ -4379,24 +4437,28 @@ GPUBatch *DRW_mesh_batch_cache_get_edit_facedots(Mesh *me) GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDIT_SELECTION_FACES); return DRW_batch_request(&cache->batch.edit_selection_faces); } GPUBatch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDIT_SELECTION_FACEDOTS); return DRW_batch_request(&cache->batch.edit_selection_facedots); } GPUBatch *DRW_mesh_batch_cache_get_edges_with_select_id(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDIT_SELECTION_EDGES); return DRW_batch_request(&cache->batch.edit_selection_edges); } GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDIT_SELECTION_VERTS); return DRW_batch_request(&cache->batch.edit_selection_verts); } @@ -4409,36 +4471,42 @@ GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me) GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_strech_area(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRECH_AREA); return DRW_batch_request(&cache->batch.edituv_faces_strech_area); } GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_strech_angle(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRECH_ANGLE); return DRW_batch_request(&cache->batch.edituv_faces_strech_angle); } GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES); return DRW_batch_request(&cache->batch.edituv_faces); } GPUBatch *DRW_mesh_batch_cache_get_edituv_edges(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDITUV_EDGES); return DRW_batch_request(&cache->batch.edituv_edges); } GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDITUV_VERTS); return DRW_batch_request(&cache->batch.edituv_verts); } GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_EDITUV_FACEDOTS); return DRW_batch_request(&cache->batch.edituv_facedots); } @@ -4446,12 +4514,14 @@ GPUBatch *DRW_mesh_batch_cache_get_uv_edges(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); texpaint_request_active_uv(cache, me); + mesh_batch_cache_add_request(cache, MBC_WIRE_LOOPS_UVS); return DRW_batch_request(&cache->batch.wire_loops_uvs); } GPUBatch *DRW_mesh_batch_cache_get_surface_edges(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); + mesh_batch_cache_add_request(cache, MBC_WIRE_LOOPS); return DRW_batch_request(&cache->batch.wire_loops); } @@ -4669,14 +4739,18 @@ static void uvedit_fill_buffer_data(MeshRenderData *rdata, GPU_indexbuf_add_generic_vert(elb_face, vidx); GPU_indexbuf_add_primitive_restart(elb_face); } - if (elb_edge && e_origindex[l[i].e] != ORIGINDEX_NONE) { + if (elb_edge) { for (i = 0; i < mpoly->totloop; ++i) { - GPU_indexbuf_add_line_verts(elb_edge, vidx + i, vidx + (i + 1) % mpoly->totloop); + if (e_origindex[l[i].e] != ORIGINDEX_NONE) { + GPU_indexbuf_add_line_verts(elb_edge, vidx + i, vidx + (i + 1) % mpoly->totloop); + } } } - if (elb_vert && v_origindex[l[i].v] != ORIGINDEX_NONE) { + if (elb_vert) { for (i = 0; i < mpoly->totloop; ++i) { - GPU_indexbuf_add_generic_vert(elb_vert, vidx + i); + if (v_origindex[l[i].v] != ORIGINDEX_NONE) { + GPU_indexbuf_add_generic_vert(elb_vert, vidx + i); + } } } } @@ -4831,82 +4905,113 @@ void DRW_mesh_batch_cache_create_requested( { MeshBatchCache *cache = mesh_batch_cache_get(me); - /* Check vertex weights. */ - if ((cache->batch.surface_weights != 0) && (ts != NULL)) { - struct DRW_MeshWeightState wstate; - BLI_assert(ob->type == OB_MESH); - drw_mesh_weight_state_extract(ob, me, ts, is_paint_mode, &wstate); - mesh_batch_cache_check_vertex_group(cache, &wstate); - drw_mesh_weight_state_copy(&cache->weight_state, &wstate); - drw_mesh_weight_state_clear(&wstate); + /* Early out */ + if (cache->batch_requested == 0) { +#ifdef DEBUG + goto check; +#endif + return; } - /* Optimization : Only create orco layer if mesh is deformed. */ - if (cache->cd_needed.orco != 0) { - CustomData *cd_vdata = (me->edit_mesh) ? &me->edit_mesh->bm->vdata : &me->vdata; - if (CustomData_get_layer(cd_vdata, CD_ORCO) != NULL && ob->modifiers.first != NULL) { - /* Orco layer is needed. */ - } - else if (cache->cd_needed.tan_orco == 0) { - /* Skip orco calculation if not needed by tangent generation. */ - cache->cd_needed.orco = 0; + DRWBatchFlag batch_requested = cache->batch_requested; + cache->batch_requested = 0; + + if (batch_requested & MBC_SURFACE_WEIGHTS) { + /* Check vertex weights. */ + if ((cache->batch.surface_weights != NULL) && (ts != NULL)) { + struct DRW_MeshWeightState wstate; + BLI_assert(ob->type == OB_MESH); + drw_mesh_weight_state_extract(ob, me, ts, is_paint_mode, &wstate); + mesh_batch_cache_check_vertex_group(cache, &wstate); + drw_mesh_weight_state_copy(&cache->weight_state, &wstate); + drw_mesh_weight_state_clear(&wstate); } } - /* Verify that all surface batches have needed attribute layers. */ - /* TODO(fclem): We could be a bit smarter here and only do it per material. */ - bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_used, cache->cd_needed); - if (cd_overlap == false) { - if ((cache->cd_used.uv & cache->cd_needed.uv) != cache->cd_needed.uv || - (cache->cd_used.tan & cache->cd_needed.tan) != cache->cd_needed.tan || - cache->cd_used.tan_orco != cache->cd_needed.tan_orco) { - GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_uv_tan); - } - if (cache->cd_used.orco != cache->cd_needed.orco) { - GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_orco); + if (batch_requested & (MBC_SURFACE | MBC_SURF_PER_MAT | MBC_WIRE_LOOPS_UVS)) { + /* Optimization : Only create orco layer if mesh is deformed. */ + if (cache->cd_needed.orco != 0) { + CustomData *cd_vdata = (me->edit_mesh) ? &me->edit_mesh->bm->vdata : &me->vdata; + if (CustomData_get_layer(cd_vdata, CD_ORCO) != NULL && ob->modifiers.first != NULL) { + /* Orco layer is needed. */ + } + else if (cache->cd_needed.tan_orco == 0) { + /* Skip orco calculation if not needed by tangent generation. + */ + cache->cd_needed.orco = 0; + } } - if ((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) { - GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_vcol); + + /* Verify that all surface batches have needed attribute layers. + */ + /* TODO(fclem): We could be a bit smarter here and only do it per + * material. */ + bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_used, cache->cd_needed); + if (cd_overlap == false) { + if ((cache->cd_used.uv & cache->cd_needed.uv) != cache->cd_needed.uv || + (cache->cd_used.tan & cache->cd_needed.tan) != cache->cd_needed.tan || + cache->cd_used.tan_orco != cache->cd_needed.tan_orco) { + GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_uv_tan); + } + if (cache->cd_used.orco != cache->cd_needed.orco) { + GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_orco); + } + if ((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) { + GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_vcol); + } + /* We can't discard batches at this point as they have been + * referenced for drawing. Just clear them in place. */ + for (int i = 0; i < cache->mat_len; ++i) { + GPU_BATCH_CLEAR_SAFE(cache->surf_per_mat[i]); + } + GPU_BATCH_CLEAR_SAFE(cache->batch.surface); + cache->batch_ready &= ~(MBC_SURFACE | MBC_SURF_PER_MAT); + + mesh_cd_layers_type_merge(&cache->cd_used, cache->cd_needed); } - /* We can't discard batches at this point as they have been - * referenced for drawing. Just clear them in place. */ - for (int i = 0; i < cache->mat_len; ++i) { - GPU_BATCH_CLEAR_SAFE(cache->surf_per_mat[i]); + mesh_cd_layers_type_merge(&cache->cd_used_over_time, cache->cd_needed); + mesh_cd_layers_type_clear(&cache->cd_needed); + } + + if (batch_requested & MBC_EDITUV) { + /* Discard UV batches if sync_selection changes */ + if (ts != NULL) { + const bool is_uvsyncsel = (ts->uv_flag & UV_SYNC_SELECTION); + if (cache->is_uvsyncsel != is_uvsyncsel) { + cache->is_uvsyncsel = is_uvsyncsel; + GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_uv_data); + GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_stretch_angle); + GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_stretch_area); + GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_uv); + GPU_VERTBUF_DISCARD_SAFE(cache->edit.facedots_uv); + GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_tri_fans); + GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_line_strips); + GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_points); + /* We only clear the batches as they may already have been + * referenced. */ + GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_strech_area); + GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_strech_angle); + GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces); + GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_edges); + GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_verts); + GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_facedots); + cache->batch_ready &= ~MBC_EDITUV; + } } - GPU_BATCH_CLEAR_SAFE(cache->batch.surface); + } - mesh_cd_layers_type_merge(&cache->cd_used, cache->cd_needed); + /* Second chance to early out */ + if ((batch_requested & ~cache->batch_ready) == 0) { +#ifdef DEBUG + goto check; +#endif + return; } - mesh_cd_layers_type_merge(&cache->cd_used_over_time, cache->cd_needed); - mesh_cd_layers_type_clear(&cache->cd_needed); - /* Discard UV batches if sync_selection changes */ - if (ts != NULL) { - const bool is_uvsyncsel = (ts->uv_flag & UV_SYNC_SELECTION); - if (cache->is_uvsyncsel != is_uvsyncsel) { - cache->is_uvsyncsel = is_uvsyncsel; - GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_uv_data); - GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_stretch_angle); - GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_stretch_area); - GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_uv); - GPU_VERTBUF_DISCARD_SAFE(cache->edit.facedots_uv); - GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_tri_fans); - GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_line_strips); - GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_points); - /* We only clear the batches as they may already have been referenced. */ - GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_strech_area); - GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_strech_angle); - GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces); - GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_edges); - GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_verts); - GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_facedots); - } - } - - bool has_request = false; + cache->batch_ready |= batch_requested; + /* Init batches and request VBOs & IBOs */ if (DRW_batch_requested(cache->batch.surface, GPU_PRIM_TRIS)) { - has_request = true; DRW_ibo_request(cache->batch.surface, &cache->ibo.loops_tris); DRW_vbo_request(cache->batch.surface, &cache->ordered.loop_pos_nor); /* For paint overlay. Active layer should have been queried. */ @@ -4918,43 +5023,35 @@ void DRW_mesh_batch_cache_create_requested( } } if (DRW_batch_requested(cache->batch.all_verts, GPU_PRIM_POINTS)) { - has_request = true; DRW_vbo_request(cache->batch.all_verts, &cache->ordered.pos_nor); } if (DRW_batch_requested(cache->batch.all_edges, GPU_PRIM_LINES)) { - has_request = true; DRW_ibo_request(cache->batch.all_edges, &cache->ibo.edges_lines); DRW_vbo_request(cache->batch.all_edges, &cache->ordered.pos_nor); } if (DRW_batch_requested(cache->batch.loose_edges, GPU_PRIM_LINES)) { - has_request = true; DRW_ibo_request(cache->batch.loose_edges, &cache->ibo.loose_edges_lines); DRW_vbo_request(cache->batch.loose_edges, &cache->ordered.pos_nor); } if (DRW_batch_requested(cache->batch.edge_detection, GPU_PRIM_LINES_ADJ)) { - has_request = true; DRW_ibo_request(cache->batch.edge_detection, &cache->ibo.edges_adj_lines); DRW_vbo_request(cache->batch.edge_detection, &cache->ordered.pos_nor); } if (DRW_batch_requested(cache->batch.surface_weights, GPU_PRIM_TRIS)) { - has_request = true; DRW_ibo_request(cache->batch.surface_weights, &cache->ibo.surf_tris); DRW_vbo_request(cache->batch.surface_weights, &cache->ordered.pos_nor); DRW_vbo_request(cache->batch.surface_weights, &cache->ordered.weights); } if (DRW_batch_requested(cache->batch.wire_loops, GPU_PRIM_LINE_STRIP)) { - has_request = true; DRW_ibo_request(cache->batch.wire_loops, &cache->ibo.loops_line_strips); DRW_vbo_request(cache->batch.wire_loops, &cache->ordered.loop_pos_nor); } if (DRW_batch_requested(cache->batch.wire_edges, GPU_PRIM_LINES)) { - has_request = true; DRW_ibo_request(cache->batch.wire_edges, &cache->ibo.loops_lines); DRW_vbo_request(cache->batch.wire_edges, &cache->ordered.loop_pos_nor); DRW_vbo_request(cache->batch.wire_edges, &cache->ordered.loop_edge_fac); } if (DRW_batch_requested(cache->batch.wire_loops_uvs, GPU_PRIM_LINE_STRIP)) { - has_request = true; DRW_ibo_request(cache->batch.wire_loops_uvs, &cache->ibo.loops_line_strips); /* For paint overlay. Active layer should have been queried. */ if (cache->cd_used.uv != 0) { @@ -4964,37 +5061,31 @@ void DRW_mesh_batch_cache_create_requested( /* Edit Mesh */ if (DRW_batch_requested(cache->batch.edit_triangles, GPU_PRIM_TRIS)) { - has_request = true; DRW_ibo_request(cache->batch.edit_triangles, &cache->ibo.edit_loops_tris); DRW_vbo_request(cache->batch.edit_triangles, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_triangles, &cache->edit.loop_data); } if (DRW_batch_requested(cache->batch.edit_vertices, GPU_PRIM_POINTS)) { - has_request = true; DRW_ibo_request(cache->batch.edit_vertices, &cache->ibo.edit_loops_points); DRW_vbo_request(cache->batch.edit_vertices, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_vertices, &cache->edit.loop_data); } if (DRW_batch_requested(cache->batch.edit_edges, GPU_PRIM_LINES)) { - has_request = true; DRW_ibo_request(cache->batch.edit_edges, &cache->ibo.edit_loops_lines); DRW_vbo_request(cache->batch.edit_edges, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_edges, &cache->edit.loop_data); } if (DRW_batch_requested(cache->batch.edit_lnor, GPU_PRIM_POINTS)) { - has_request = true; DRW_ibo_request(cache->batch.edit_lnor, &cache->ibo.edit_loops_tris); DRW_vbo_request(cache->batch.edit_lnor, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_lnor, &cache->edit.loop_lnor); } if (DRW_batch_requested(cache->batch.edit_facedots, GPU_PRIM_POINTS)) { - has_request = true; DRW_vbo_request(cache->batch.edit_facedots, &cache->edit.facedots_pos_nor_data); } /* Mesh Analysis */ if (DRW_batch_requested(cache->batch.edit_mesh_analysis, GPU_PRIM_TRIS)) { - has_request = true; DRW_ibo_request(cache->batch.edit_mesh_analysis, &cache->ibo.edit_loops_tris); DRW_vbo_request(cache->batch.edit_mesh_analysis, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_mesh_analysis, &cache->edit.loop_mesh_analysis); @@ -5002,39 +5093,33 @@ void DRW_mesh_batch_cache_create_requested( /* Edit UV */ if (DRW_batch_requested(cache->batch.edituv_faces, GPU_PRIM_TRI_FAN)) { - has_request = true; DRW_ibo_request(cache->batch.edituv_faces, &cache->ibo.edituv_loops_tri_fans); DRW_vbo_request(cache->batch.edituv_faces, &cache->edit.loop_uv); DRW_vbo_request(cache->batch.edituv_faces, &cache->edit.loop_uv_data); } if (DRW_batch_requested(cache->batch.edituv_faces_strech_area, GPU_PRIM_TRI_FAN)) { - has_request = true; DRW_ibo_request(cache->batch.edituv_faces_strech_area, &cache->ibo.edituv_loops_tri_fans); DRW_vbo_request(cache->batch.edituv_faces_strech_area, &cache->edit.loop_uv); DRW_vbo_request(cache->batch.edituv_faces_strech_area, &cache->edit.loop_uv_data); DRW_vbo_request(cache->batch.edituv_faces_strech_area, &cache->edit.loop_stretch_area); } if (DRW_batch_requested(cache->batch.edituv_faces_strech_angle, GPU_PRIM_TRI_FAN)) { - has_request = true; DRW_ibo_request(cache->batch.edituv_faces_strech_angle, &cache->ibo.edituv_loops_tri_fans); DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &cache->edit.loop_uv); DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &cache->edit.loop_uv_data); DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &cache->edit.loop_stretch_angle); } if (DRW_batch_requested(cache->batch.edituv_edges, GPU_PRIM_LINES)) { - has_request = true; DRW_ibo_request(cache->batch.edituv_edges, &cache->ibo.edituv_loops_line_strips); DRW_vbo_request(cache->batch.edituv_edges, &cache->edit.loop_uv); DRW_vbo_request(cache->batch.edituv_edges, &cache->edit.loop_uv_data); } if (DRW_batch_requested(cache->batch.edituv_verts, GPU_PRIM_POINTS)) { - has_request = true; DRW_ibo_request(cache->batch.edituv_verts, &cache->ibo.edituv_loops_points); DRW_vbo_request(cache->batch.edituv_verts, &cache->edit.loop_uv); DRW_vbo_request(cache->batch.edituv_verts, &cache->edit.loop_uv_data); } if (DRW_batch_requested(cache->batch.edituv_facedots, GPU_PRIM_POINTS)) { - has_request = true; DRW_vbo_request(cache->batch.edituv_facedots, &cache->edit.facedots_uv); DRW_vbo_request(cache->batch.edituv_facedots, &cache->edit.facedots_uv_data); } @@ -5042,25 +5127,21 @@ void DRW_mesh_batch_cache_create_requested( /* Selection */ /* TODO reuse ordered.loop_pos_nor if possible. */ if (DRW_batch_requested(cache->batch.edit_selection_verts, GPU_PRIM_POINTS)) { - has_request = true; DRW_ibo_request(cache->batch.edit_selection_verts, &cache->ibo.edit_loops_points); DRW_vbo_request(cache->batch.edit_selection_verts, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_selection_verts, &cache->edit.loop_vert_idx); } if (DRW_batch_requested(cache->batch.edit_selection_edges, GPU_PRIM_LINES)) { - has_request = true; DRW_ibo_request(cache->batch.edit_selection_edges, &cache->ibo.edit_loops_lines); DRW_vbo_request(cache->batch.edit_selection_edges, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_selection_edges, &cache->edit.loop_edge_idx); } if (DRW_batch_requested(cache->batch.edit_selection_faces, GPU_PRIM_TRIS)) { - has_request = true; DRW_ibo_request(cache->batch.edit_selection_faces, &cache->ibo.edit_loops_tris); DRW_vbo_request(cache->batch.edit_selection_faces, &cache->edit.loop_pos_nor); DRW_vbo_request(cache->batch.edit_selection_faces, &cache->edit.loop_face_idx); } if (DRW_batch_requested(cache->batch.edit_selection_facedots, GPU_PRIM_POINTS)) { - has_request = true; DRW_vbo_request(cache->batch.edit_selection_facedots, &cache->edit.facedots_pos_nor_data); DRW_vbo_request(cache->batch.edit_selection_facedots, &cache->edit.facedots_idx); } @@ -5068,7 +5149,6 @@ void DRW_mesh_batch_cache_create_requested( /* Per Material */ for (int i = 0; i < cache->mat_len; ++i) { if (DRW_batch_requested(cache->surf_per_mat[i], GPU_PRIM_TRIS)) { - has_request = true; if (cache->mat_len > 1) { DRW_ibo_request(cache->surf_per_mat[i], &cache->surf_per_mat_tris[i]); } @@ -5089,11 +5169,6 @@ void DRW_mesh_batch_cache_create_requested( } } - /* Early out if no request. */ - if (!has_request) { - return; - } - #ifdef DRW_DEBUG_MESH_CACHE_REQUEST printf("-- %s %s --\n", __func__, ob->id.name + 2); #endif @@ -5325,6 +5400,7 @@ void DRW_mesh_batch_cache_create_requested( } #ifdef DEBUG +check: /* Make sure all requested batches have been setup. */ for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); ++i) { BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0)); diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c index 432c5092274..60f15338412 100644 --- a/source/blender/draw/intern/draw_cache_impl_metaball.c +++ b/source/blender/draw/intern/draw_cache_impl_metaball.c @@ -98,12 +98,16 @@ static void metaball_batch_cache_init(MetaBall *mb) cache->is_manifold = false; } -static MetaBallBatchCache *metaball_batch_cache_get(MetaBall *mb) +void DRW_mball_batch_cache_validate(MetaBall *mb) { if (!metaball_batch_cache_valid(mb)) { metaball_batch_cache_clear(mb); metaball_batch_cache_init(mb); } +} + +static MetaBallBatchCache *metaball_batch_cache_get(MetaBall *mb) +{ return mb->batch_cache; } diff --git a/source/blender/draw/intern/draw_cache_inline.h b/source/blender/draw/intern/draw_cache_inline.h new file mode 100644 index 00000000000..d94ef5b90d3 --- /dev/null +++ b/source/blender/draw/intern/draw_cache_inline.h @@ -0,0 +1,110 @@ +/* + * 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. + * + * Copyright 2016, Blender Foundation. + */ + +/** \file + * \ingroup draw + */ + +#ifndef __DRAW_CACHE_INLINE_H__ +#define __DRAW_CACHE_INLINE_H__ + +#include "MEM_guardedalloc.h" +#include "GPU_batch.h" + +/* Common */ +// #define DRW_DEBUG_MESH_CACHE_REQUEST + +#ifdef DRW_DEBUG_MESH_CACHE_REQUEST +# define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value) \ + (flag |= DRW_vbo_requested(vbo) ? (printf(" VBO requested " #vbo "\n") ? value : value) : 0) +# define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value) \ + (flag |= DRW_ibo_requested(ibo) ? (printf(" IBO requested " #ibo "\n") ? value : value) : 0) +#else +# define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value) \ + (flag |= DRW_vbo_requested(vbo) ? (value) : 0) +# define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value) \ + (flag |= DRW_ibo_requested(ibo) ? (value) : 0) +#endif + +/* Test and assign NULL if test fails */ +#define DRW_TEST_ASSIGN_VBO(v) (v = (DRW_vbo_requested(v) ? (v) : NULL)) +#define DRW_TEST_ASSIGN_IBO(v) (v = (DRW_ibo_requested(v) ? (v) : NULL)) + +BLI_INLINE GPUBatch *DRW_batch_request(GPUBatch **batch) +{ + /* XXX TODO(fclem): We are writting to batch cache here. Need to make this thread safe. */ + if (*batch == NULL) { + *batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch"); + } + return *batch; +} + +BLI_INLINE bool DRW_batch_requested(GPUBatch *batch, int prim_type) +{ + /* Batch has been requested if it has been created but not initialized. */ + if (batch != NULL && batch->verts[0] == NULL) { + /* HACK. We init without a valid VBO and let the first vbo binding + * fill verts[0]. */ + GPU_batch_init_ex(batch, prim_type, (GPUVertBuf *)1, NULL, 0); + batch->verts[0] = NULL; + return true; + } + return false; +} + +BLI_INLINE void DRW_ibo_request(GPUBatch *batch, GPUIndexBuf **ibo) +{ + if (*ibo == NULL) { + *ibo = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf"); + } + GPU_batch_vao_cache_clear(batch); + batch->elem = *ibo; +} + +BLI_INLINE bool DRW_ibo_requested(GPUIndexBuf *ibo) +{ + /* TODO do not rely on data uploaded. This prevents multithreading. + * (need access to a gl context) */ + return (ibo != NULL && ibo->ibo_id == 0 && ibo->data == NULL); +} + +BLI_INLINE void DRW_vbo_request(GPUBatch *batch, GPUVertBuf **vbo) +{ + if (*vbo == NULL) { + *vbo = MEM_callocN(sizeof(GPUVertBuf), "GPUVertBuf"); + } + /* HACK set first vbo if not init. */ + if (batch->verts[0] == NULL) { + GPU_batch_vao_cache_clear(batch); + batch->verts[0] = *vbo; + } + else { + /* HACK: bypass assert */ + int vbo_vert_len = (*vbo)->vertex_len; + (*vbo)->vertex_len = batch->verts[0]->vertex_len; + GPU_batch_vertbuf_add(batch, *vbo); + (*vbo)->vertex_len = vbo_vert_len; + } +} + +BLI_INLINE bool DRW_vbo_requested(GPUVertBuf *vbo) +{ + return (vbo != NULL && vbo->format.attr_len == 0); +} + +#endif /* __DRAW_CACHE_INLINE_H__ */ diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index b4eb354ec59..51f097e79d8 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -233,6 +233,7 @@ extern char datatoc_armature_stick_frag_glsl[]; extern char datatoc_armature_dof_vert_glsl[]; extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; extern char datatoc_gpu_shader_flat_color_frag_glsl[]; extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; @@ -284,7 +285,8 @@ static struct { struct GPUVertFormat *instance_bone_envelope_distance; struct GPUVertFormat *instance_bone_envelope_outline; struct GPUVertFormat *instance_mball_handles; - struct GPUVertFormat *dynlines_color; + struct GPUVertFormat *pos_color; + struct GPUVertFormat *pos; } g_formats = {NULL}; void DRW_globals_free(void) @@ -309,34 +311,36 @@ void DRW_shgroup_world_clip_planes_from_rv3d(DRWShadingGroup *shgrp, const Regio DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); } -DRWShadingGroup *shgroup_dynlines_flat_color(DRWPass *pass, eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_dynlines_flat_color(DRWPass *pass, eGPUShaderConfig sh_cfg) { GPUShader *sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_FLAT_COLOR, sh_cfg); - DRW_shgroup_instance_format(g_formats.dynlines_color, + DRW_shgroup_instance_format(g_formats.pos_color, { {"pos", DRW_ATTR_FLOAT, 3}, {"color", DRW_ATTR_FLOAT, 4}, }); - DRWShadingGroup *grp = DRW_shgroup_line_batch_create_with_format( - sh, pass, g_formats.dynlines_color); + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer(grp, g_formats.pos_color, GPU_PRIM_LINES); } -DRWShadingGroup *shgroup_dynlines_dashed_uniform_color(DRWPass *pass, - const float color[4], - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_dynlines_dashed_uniform_color(DRWPass *pass, + const float color[4], + eGPUShaderConfig sh_cfg) { GPUShader *sh = GPU_shader_get_builtin_shader_with_config( GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR, sh_cfg); static float dash_width = 6.0f; static float dash_factor = 0.5f; - DRWShadingGroup *grp = DRW_shgroup_line_batch_create(sh, pass); + + DRW_shgroup_instance_format(g_formats.pos, {{"pos", DRW_ATTR_FLOAT, 3}}); + + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_vec4(grp, "color", color, 1); DRW_shgroup_uniform_vec2(grp, "viewport_size", DRW_viewport_size_get(), 1); DRW_shgroup_uniform_float(grp, "dash_width", &dash_width, 1); @@ -345,60 +349,53 @@ DRWShadingGroup *shgroup_dynlines_dashed_uniform_color(DRWPass *pass, if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_LINES); } -DRWShadingGroup *shgroup_dynpoints_uniform_color(DRWPass *pass, - const float color[4], - const float *size, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_dynpoints_uniform_color(DRWShadingGroup *grp) { - GPUShader *sh = GPU_shader_get_builtin_shader_with_config( - GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, sh_cfg); + DRW_shgroup_instance_format(g_formats.pos, {{"pos", DRW_ATTR_FLOAT, 3}}); - DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); - DRW_shgroup_uniform_vec4(grp, "color", color, 1); - DRW_shgroup_uniform_float(grp, "size", size, 1); - DRW_shgroup_state_enable(grp, DRW_STATE_POINT); - if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); - } - return grp; + return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_POINTS); } -DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass, - const float color[4], - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_groundlines_uniform_color(DRWPass *pass, + const float color[4], + eGPUShaderConfig sh_cfg) { GPUShader *sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_GROUNDLINE, sh_cfg); - DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); + DRW_shgroup_instance_format(g_formats.pos, {{"pos", DRW_ATTR_FLOAT, 3}}); + + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_vec4(grp, "color", color, 1); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_POINTS); } -DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, - const float color[4], - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_groundpoints_uniform_color(DRWPass *pass, + const float color[4], + eGPUShaderConfig sh_cfg) { GPUShader *sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_GROUNDPOINT, sh_cfg); - DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass); + DRW_shgroup_instance_format(g_formats.pos, {{"pos", DRW_ATTR_FLOAT, 3}}); + + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_vec4(grp, "color", color, 1); DRW_shgroup_state_enable(grp, DRW_STATE_POINT); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_POINTS); } -DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, - struct GPUBatch *geom, - const float *size, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_screenspace(DRWPass *pass, + struct GPUBatch *geom, + const float *size, + eGPUShaderConfig sh_cfg) { GPUShader *sh = GPU_shader_get_builtin_shader_with_config( GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR, sh_cfg); @@ -409,18 +406,17 @@ DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, {"color", DRW_ATTR_FLOAT, 3}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh, pass, geom, g_formats.instance_screenspace); + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_float(grp, "size", size, 1); DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1); DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_screenspace, geom); } -DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct GPUBatch *geom) +struct DRWCallBuffer *buffer_instance_solid(DRWPass *pass, struct GPUBatch *geom) { static float light[3] = {0.0f, 0.0f, 1.0f}; GPUShader *sh = GPU_shader_get_builtin_shader( @@ -432,13 +428,13 @@ DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct GPUBatch *geom) {"color", DRW_ATTR_FLOAT, 4}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color); + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_vec3(grp, "light", light, 1); - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_color, geom); } -DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct GPUBatch *geom) +struct DRWCallBuffer *buffer_instance_wire(DRWPass *pass, struct GPUBatch *geom) { GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR); @@ -448,14 +444,14 @@ DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct GPUBatch *geom) {"color", DRW_ATTR_FLOAT, 4}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color); + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_color, geom); } -DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_screen_aligned(DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg) { GPUShader *sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED, sh_cfg); @@ -467,18 +463,17 @@ DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass, {"InstanceModelMatrix", DRW_ATTR_FLOAT, 16}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh, pass, geom, g_formats.instance_screen_aligned); + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_screen_aligned, geom); } -DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_scaled(DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg) { GPUShader *sh_inst = GPU_shader_get_builtin_shader_with_config( GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE, sh_cfg); @@ -490,15 +485,16 @@ DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass, {"InstanceModelMatrix", DRW_ATTR_FLOAT, 16}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_inst, pass, geom, g_formats.instance_scaled); + DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_scaled, geom); } -DRWShadingGroup *shgroup_instance(DRWPass *pass, struct GPUBatch *geom, eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance(DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg) { GPUShader *sh_inst = GPU_shader_get_builtin_shader_with_config( GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, sh_cfg); @@ -510,22 +506,16 @@ DRWShadingGroup *shgroup_instance(DRWPass *pass, struct GPUBatch *geom, eGPUShad {"InstanceModelMatrix", DRW_ATTR_FLOAT, 16}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_inst, pass, geom, g_formats.instance_sized); + DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass); DRW_shgroup_state_disable(grp, DRW_STATE_BLEND); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom); } -DRWShadingGroup *shgroup_instance_alpha(DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_alpha(DRWShadingGroup *grp, struct GPUBatch *geom) { - GPUShader *sh_inst = GPU_shader_get_builtin_shader_with_config( - GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, sh_cfg); - DRW_shgroup_instance_format(g_formats.instance_sized, { {"color", DRW_ATTR_FLOAT, 4}, @@ -533,17 +523,12 @@ DRWShadingGroup *shgroup_instance_alpha(DRWPass *pass, {"InstanceModelMatrix", DRW_ATTR_FLOAT, 16}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_inst, pass, geom, g_formats.instance_sized); - if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); - } - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom); } -DRWShadingGroup *shgroup_instance_empty_axes(DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_empty_axes(DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg) { COMMON_Shaders *sh_data = &g_shaders[sh_cfg]; if (sh_data->empty_axes_sh == NULL) { @@ -562,16 +547,15 @@ DRWShadingGroup *shgroup_instance_empty_axes(DRWPass *pass, {"InstanceModelMatrix", DRW_ATTR_FLOAT, 16}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_data->empty_axes_sh, pass, geom, g_formats.instance_sized); + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->empty_axes_sh, pass); DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom); } -DRWShadingGroup *shgroup_instance_outline(DRWPass *pass, struct GPUBatch *geom, int *baseid) +struct DRWCallBuffer *buffer_instance_outline(DRWPass *pass, struct GPUBatch *geom, int *baseid) { GPUShader *sh_inst = GPU_shader_get_builtin_shader( GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE); @@ -583,16 +567,15 @@ DRWShadingGroup *shgroup_instance_outline(DRWPass *pass, struct GPUBatch *geom, {"InstanceModelMatrix", DRW_ATTR_FLOAT, 16}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_inst, pass, geom, g_formats.instance_outline); + DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass); DRW_shgroup_uniform_int(grp, "baseId", baseid, 1); - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_outline, geom); } -DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_camera_instance(DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg) { GPUShader *sh_inst = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_CAMERA, sh_cfg); @@ -605,17 +588,16 @@ DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, {"InstanceModelMatrix", DRW_ATTR_FLOAT, 16}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_inst, pass, geom, g_formats.instance_camera); + DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_camera, geom); } -DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_distance_lines_instance(DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg) { GPUShader *sh_inst = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_DISTANCE_LINES, sh_cfg); @@ -629,18 +611,17 @@ DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, {"InstanceModelMatrix", DRW_ATTR_FLOAT, 16}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_inst, pass, geom, g_formats.instance_distance_lines); + DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass); DRW_shgroup_uniform_float(grp, "size", &point_size, 1); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_distance_lines, geom); } -DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_spot_instance(DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg) { GPUShader *sh_inst = GPU_shader_get_builtin_shader_with_config( GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR, sh_cfg); @@ -653,17 +634,17 @@ DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, {"InstanceModelMatrix", DRW_ATTR_FLOAT, 16}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_spot); + DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass); DRW_shgroup_uniform_bool(grp, "drawFront", &False, 1); DRW_shgroup_uniform_bool(grp, "drawBack", &False, 1); DRW_shgroup_uniform_bool(grp, "drawSilhouette", &True, 1); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_spot, geom); } -DRWShadingGroup *shgroup_instance_bone_axes(DRWPass *pass, eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_bone_axes(DRWPass *pass, eGPUShaderConfig sh_cfg) { COMMON_Shaders *sh_data = &g_shaders[sh_cfg]; if (sh_data->bone_axes == NULL) { @@ -681,16 +662,16 @@ DRWShadingGroup *shgroup_instance_bone_axes(DRWPass *pass, eGPUShaderConfig sh_c {"color", DRW_ATTR_FLOAT, 4}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_data->bone_axes, pass, DRW_cache_bone_arrows_get(), g_formats.instance_color); + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_axes, pass); DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance( + grp, g_formats.instance_color, DRW_cache_bone_arrows_get()); } -DRWShadingGroup *shgroup_instance_bone_envelope_outline(DRWPass *pass, eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_bone_envelope_outline(DRWPass *pass, eGPUShaderConfig sh_cfg) { COMMON_Shaders *sh_data = &g_shaders[sh_cfg]; if (sh_data->bone_envelope_outline == NULL) { @@ -711,18 +692,17 @@ DRWShadingGroup *shgroup_instance_bone_envelope_outline(DRWPass *pass, eGPUShade {"xAxis", DRW_ATTR_FLOAT, 3}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_data->bone_envelope_outline, - pass, - DRW_cache_bone_envelope_outline_get(), - g_formats.instance_bone_envelope_outline); + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_envelope_outline, pass); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance( + grp, g_formats.instance_bone_envelope_outline, DRW_cache_bone_envelope_outline_get()); } -DRWShadingGroup *shgroup_instance_bone_envelope_distance(DRWPass *pass, eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_bone_envelope_distance(DRWPass *pass, + eGPUShaderConfig sh_cfg) { COMMON_Shaders *sh_data = &g_shaders[sh_cfg]; if (sh_data->bone_envelope_distance == NULL) { @@ -742,19 +722,17 @@ DRWShadingGroup *shgroup_instance_bone_envelope_distance(DRWPass *pass, eGPUShad {"xAxis", DRW_ATTR_FLOAT, 3}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_data->bone_envelope_distance, - pass, - DRW_cache_bone_envelope_solid_get(), - g_formats.instance_bone_envelope_distance); + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_envelope_distance, pass); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance( + grp, g_formats.instance_bone_envelope_distance, DRW_cache_bone_envelope_solid_get()); } -DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, - bool transp, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_bone_envelope_solid(DRWPass *pass, + bool transp, + eGPUShaderConfig sh_cfg) { COMMON_Shaders *sh_data = &g_shaders[sh_cfg]; if (sh_data->bone_envelope == NULL) { @@ -776,18 +754,19 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, {"xAxis", DRW_ATTR_FLOAT, 3}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_data->bone_envelope, - pass, - DRW_cache_bone_envelope_solid_get(), - g_formats.instance_bone_envelope); + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_envelope, pass); + /* We can have a lot of overdraw if we don't do this. Also envelope are not subject to + * inverted matrix. */ + DRW_shgroup_state_enable(grp, DRW_STATE_CULL_BACK); DRW_shgroup_uniform_float_copy(grp, "alpha", transp ? 0.6f : 1.0f); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance( + grp, g_formats.instance_bone_envelope, DRW_cache_bone_envelope_solid_get()); } -DRWShadingGroup *shgroup_instance_mball_handles(DRWPass *pass, eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_mball_handles(DRWPass *pass, eGPUShaderConfig sh_cfg) { COMMON_Shaders *sh_data = &g_shaders[sh_cfg]; if (sh_data->mball_handles == NULL) { @@ -806,28 +785,32 @@ DRWShadingGroup *shgroup_instance_mball_handles(DRWPass *pass, eGPUShaderConfig {"color", DRW_ATTR_FLOAT, 3}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_data->mball_handles, - pass, - DRW_cache_screenspace_circle_get(), - g_formats.instance_mball_handles); + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->mball_handles, pass); DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance( + grp, g_formats.instance_mball_handles, DRW_cache_screenspace_circle_get()); } /* Only works with batches with adjacency infos. */ -DRWShadingGroup *shgroup_instance_bone_shape_outline(DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_bone_shape_outline(DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg) { COMMON_Shaders *sh_data = &g_shaders[sh_cfg]; if (sh_data->shape_outline == NULL) { const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; sh_data->shape_outline = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_armature_shape_outline_vert_glsl, NULL}, - .geom = (const char *[]){sh_cfg_data->lib, datatoc_armature_shape_outline_geom_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_armature_shape_outline_vert_glsl, + NULL}, + .geom = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_armature_shape_outline_geom_glsl, + NULL}, .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); @@ -839,25 +822,27 @@ DRWShadingGroup *shgroup_instance_bone_shape_outline(DRWPass *pass, {"outlineColorSize", DRW_ATTR_FLOAT, 4}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_data->shape_outline, pass, geom, g_formats.instance_bone_outline); + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->shape_outline, pass); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_bone_outline, geom); } -DRWShadingGroup *shgroup_instance_bone_shape_solid(DRWPass *pass, - struct GPUBatch *geom, - bool transp, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_bone_shape_solid(DRWPass *pass, + struct GPUBatch *geom, + bool transp, + eGPUShaderConfig sh_cfg) { COMMON_Shaders *sh_data = &g_shaders[sh_cfg]; if (sh_data->shape_solid == NULL) { const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; sh_data->shape_solid = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_armature_shape_solid_vert_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_armature_shape_solid_vert_glsl, + NULL}, .frag = (const char *[]){datatoc_armature_shape_solid_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); @@ -870,18 +855,17 @@ DRWShadingGroup *shgroup_instance_bone_shape_solid(DRWPass *pass, {"stateColor", DRW_ATTR_FLOAT, 3}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_data->shape_solid, pass, geom, g_formats.instance_bone); + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->shape_solid, pass); DRW_shgroup_uniform_float_copy(grp, "alpha", transp ? 0.6f : 1.0f); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_bone, geom); } -DRWShadingGroup *shgroup_instance_bone_sphere_solid(DRWPass *pass, - bool transp, - eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_bone_sphere_solid(DRWPass *pass, + bool transp, + eGPUShaderConfig sh_cfg) { COMMON_Shaders *sh_data = &g_shaders[sh_cfg]; if (sh_data->bone_sphere == NULL) { @@ -900,17 +884,17 @@ DRWShadingGroup *shgroup_instance_bone_sphere_solid(DRWPass *pass, {"stateColor", DRW_ATTR_FLOAT, 3}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_data->bone_sphere, pass, DRW_cache_bone_point_get(), g_formats.instance_bone); + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_sphere, pass); /* More transparent than the shape to be less distractive. */ DRW_shgroup_uniform_float_copy(grp, "alpha", transp ? 0.4f : 1.0f); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance( + grp, g_formats.instance_bone, DRW_cache_bone_point_get()); } -DRWShadingGroup *shgroup_instance_bone_sphere_outline(DRWPass *pass, eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_bone_sphere_outline(DRWPass *pass, eGPUShaderConfig sh_cfg) { COMMON_Shaders *sh_data = &g_shaders[sh_cfg]; if (sh_data->bone_sphere_outline == NULL) { @@ -929,18 +913,16 @@ DRWShadingGroup *shgroup_instance_bone_sphere_outline(DRWPass *pass, eGPUShaderC {"outlineColorSize", DRW_ATTR_FLOAT, 4}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_data->bone_sphere_outline, - pass, - DRW_cache_bone_point_wire_outline_get(), - g_formats.instance_bone_outline); + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_sphere_outline, pass); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance( + grp, g_formats.instance_bone_outline, DRW_cache_bone_point_wire_outline_get()); } -DRWShadingGroup *shgroup_instance_bone_stick(DRWPass *pass, eGPUShaderConfig sh_cfg) +struct DRWCallBuffer *buffer_instance_bone_stick(DRWPass *pass, eGPUShaderConfig sh_cfg) { COMMON_Shaders *sh_data = &g_shaders[sh_cfg]; if (sh_data->bone_stick == NULL) { @@ -963,17 +945,19 @@ DRWShadingGroup *shgroup_instance_bone_stick(DRWPass *pass, eGPUShaderConfig sh_ {"tailColor", DRW_ATTR_FLOAT, 4}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_data->bone_stick, pass, DRW_cache_bone_stick_get(), g_formats.instance_bone_stick); + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_stick, pass); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); DRW_shgroup_uniform_float_copy(grp, "stickSize", 5.0f * U.pixelsize); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - return grp; + return DRW_shgroup_call_buffer_instance( + grp, g_formats.instance_bone_stick, DRW_cache_bone_stick_get()); } -struct DRWShadingGroup *shgroup_instance_bone_dof(struct DRWPass *pass, struct GPUBatch *geom) +struct DRWCallBuffer *buffer_instance_bone_dof(struct DRWPass *pass, + struct GPUBatch *geom, + bool blend) { COMMON_Shaders *sh_data = &g_shaders[GPU_SHADER_CFG_DEFAULT]; if (sh_data->bone_dofs == NULL) { @@ -989,10 +973,12 @@ struct DRWShadingGroup *shgroup_instance_bone_dof(struct DRWPass *pass, struct G {"amax", DRW_ATTR_FLOAT, 2}, }); - DRWShadingGroup *grp = DRW_shgroup_instance_create( - sh_data->bone_dofs, pass, geom, g_formats.instance_bone_dof); - - return grp; + DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_dofs, pass); + if (blend) { + DRW_shgroup_state_enable(grp, DRW_STATE_BLEND); + DRW_shgroup_state_disable(grp, DRW_STATE_CULL_FRONT); + } + return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_bone_dof, geom); } struct GPUShader *mpath_line_shader_get(void) @@ -1028,18 +1014,23 @@ struct GPUShader *volume_velocity_shader_get(bool use_needle) COMMON_Shaders *sh_data = &g_shaders[GPU_SHADER_CFG_DEFAULT]; if (use_needle) { if (sh_data->volume_velocity_needle_sh == NULL) { - sh_data->volume_velocity_needle_sh = DRW_shader_create( + sh_data->volume_velocity_needle_sh = DRW_shader_create_with_lib( datatoc_volume_velocity_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl, + datatoc_common_view_lib_glsl, "#define USE_NEEDLE"); } return sh_data->volume_velocity_needle_sh; } else { if (sh_data->volume_velocity_sh == NULL) { - sh_data->volume_velocity_sh = DRW_shader_create( - datatoc_volume_velocity_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl, NULL); + sh_data->volume_velocity_sh = DRW_shader_create_with_lib( + datatoc_volume_velocity_vert_glsl, + NULL, + datatoc_gpu_shader_flat_color_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); } return sh_data->volume_velocity_sh; } @@ -1075,22 +1066,27 @@ int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color theme_id = (active) ? TH_ACTIVE : TH_SELECT; } else { - if (ob->type == OB_LAMP) { - theme_id = TH_LIGHT; - } - else if (ob->type == OB_SPEAKER) { - theme_id = TH_SPEAKER; - } - else if (ob->type == OB_CAMERA) { - theme_id = TH_CAMERA; - } - else if (ob->type == OB_EMPTY) { - theme_id = TH_EMPTY; + switch (ob->type) { + case OB_LAMP: + theme_id = TH_LIGHT; + break; + case OB_SPEAKER: + theme_id = TH_SPEAKER; + break; + case OB_CAMERA: + theme_id = TH_CAMERA; + break; + case OB_EMPTY: + theme_id = TH_EMPTY; + break; + case OB_LIGHTPROBE: + /* TODO add lightprobe color */ + theme_id = TH_EMPTY; + break; + default: + /* fallback to TH_WIRE */ + break; } - else if (ob->type == OB_LIGHTPROBE) { - theme_id = TH_EMPTY; - } /* TODO add lightprobe color */ - /* fallback to TH_WIRE */ } } diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 489bc7459df..df7220c0d2a 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -23,6 +23,7 @@ #ifndef __DRAW_COMMON_H__ #define __DRAW_COMMON_H__ +struct DRWCallBuffer; struct DRWPass; struct DRWShadingGroup; struct GPUBatch; @@ -125,77 +126,74 @@ void DRW_globals_free(void); void DRW_shgroup_world_clip_planes_from_rv3d(struct DRWShadingGroup *shgrp, const RegionView3D *rv3d); -struct DRWShadingGroup *shgroup_dynlines_flat_color(struct DRWPass *pass, eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_dynlines_dashed_uniform_color(struct DRWPass *pass, - const float color[4], - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_dynpoints_uniform_color(struct DRWPass *pass, - const float color[4], - const float *size, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_groundlines_uniform_color(struct DRWPass *pass, - const float color[4], - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_groundpoints_uniform_color(struct DRWPass *pass, +/* TODO(fclem) ideally, most of the DRWCallBuffer functions shouldn't create a shgroup. */ +struct DRWCallBuffer *buffer_dynlines_flat_color(struct DRWPass *pass, eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_dynlines_dashed_uniform_color(struct DRWPass *pass, const float color[4], eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_screenspace(struct DRWPass *pass, +struct DRWCallBuffer *buffer_dynpoints_uniform_color(struct DRWShadingGroup *grp); +struct DRWCallBuffer *buffer_groundlines_uniform_color(struct DRWPass *pass, + const float color[4], + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_groundpoints_uniform_color(struct DRWPass *pass, + const float color[4], + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_screenspace(struct DRWPass *pass, + struct GPUBatch *geom, + const float *size, + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_solid(struct DRWPass *pass, struct GPUBatch *geom); +struct DRWCallBuffer *buffer_instance_wire(struct DRWPass *pass, struct GPUBatch *geom); +struct DRWCallBuffer *buffer_instance_screen_aligned(struct DRWPass *pass, struct GPUBatch *geom, - const float *size, eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_solid(struct DRWPass *pass, struct GPUBatch *geom); -struct DRWShadingGroup *shgroup_instance_wire(struct DRWPass *pass, struct GPUBatch *geom); -struct DRWShadingGroup *shgroup_instance_screen_aligned(struct DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_empty_axes(struct DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_scaled(struct DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance(struct DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_alpha(struct DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_outline(struct DRWPass *pass, +struct DRWCallBuffer *buffer_instance_empty_axes(struct DRWPass *pass, struct GPUBatch *geom, - int *baseid); -struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, - struct GPUBatch *geom, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_scaled(struct DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance(struct DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_alpha(struct DRWShadingGroup *grp, struct GPUBatch *geom); +struct DRWCallBuffer *buffer_instance_outline(struct DRWPass *pass, struct GPUBatch *geom, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_mball_handles(struct DRWPass *pass, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_bone_axes(struct DRWPass *pass, eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_bone_envelope_distance(struct DRWPass *pass, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_bone_envelope_outline(struct DRWPass *pass, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass, - bool transp, + int *baseid); +struct DRWCallBuffer *buffer_camera_instance(struct DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_distance_lines_instance(struct DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_spot_instance(struct DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_mball_handles(struct DRWPass *pass, eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_bone_axes(struct DRWPass *pass, eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_bone_envelope_distance(struct DRWPass *pass, eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_bone_shape_outline(struct DRWPass *pass, - struct GPUBatch *geom, +struct DRWCallBuffer *buffer_instance_bone_envelope_outline(struct DRWPass *pass, eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_bone_shape_solid(struct DRWPass *pass, - struct GPUBatch *geom, +struct DRWCallBuffer *buffer_instance_bone_envelope_solid(struct DRWPass *pass, bool transp, eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_bone_sphere_outline(struct DRWPass *pass, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_bone_sphere_solid(struct DRWPass *pass, - bool transp, - eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_bone_stick(struct DRWPass *pass, eGPUShaderConfig sh_cfg); -struct DRWShadingGroup *shgroup_instance_bone_dof(struct DRWPass *pass, struct GPUBatch *geom); +struct DRWCallBuffer *buffer_instance_bone_shape_outline(struct DRWPass *pass, + struct GPUBatch *geom, + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_bone_shape_solid(struct DRWPass *pass, + struct GPUBatch *geom, + bool transp, + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_bone_sphere_outline(struct DRWPass *pass, + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_bone_sphere_solid(struct DRWPass *pass, + bool transp, + eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_bone_stick(struct DRWPass *pass, eGPUShaderConfig sh_cfg); +struct DRWCallBuffer *buffer_instance_bone_dof(struct DRWPass *pass, + struct GPUBatch *geom, + bool blend); struct GPUShader *mpath_line_shader_get(void); struct GPUShader *mpath_points_shader_get(void); diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index cb83265195a..6dee25fabae 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -195,7 +195,7 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object, shgrp, "hairCloseTip", (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0); /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass culling * test. */ - DRW_shgroup_call_object_add_no_cull( + DRW_shgroup_call_object_no_cull( shgrp, hair_cache->final[subdiv].proc_hairs[thickness_res - 1], object); /* Transform Feedback subdiv. */ @@ -224,7 +224,7 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object, DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", hair_cache->strand_tex); DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", hair_cache->strand_seg_tex); DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1); - DRW_shgroup_call_procedural_points_add(tf_shgrp, final_points_len, NULL); + DRW_shgroup_call_procedural_points(tf_shgrp, final_points_len, NULL); } return shgrp; diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c index e8d91309e06..b88ad936c28 100644 --- a/source/blender/draw/intern/draw_instance_data.c +++ b/source/blender/draw/intern/draw_instance_data.c @@ -36,33 +36,9 @@ #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" #include "BLI_mempool.h" +#include "BLI_memblock.h" -#define BUFFER_CHUNK_SIZE 32 -#define BUFFER_VERTS_CHUNK 32 - -typedef struct DRWBatchingBuffer { - struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */ - GPUVertFormat *format; /* Identifier. */ - GPUVertBuf *vert; /* GPUVertBuf contained in the GPUBatch. */ - GPUBatch *batch; /* GPUBatch containing the GPUVertBuf. */ -} DRWBatchingBuffer; - -typedef struct DRWInstancingBuffer { - struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */ - GPUVertFormat *format; /* Identifier. */ - GPUBatch *instance; /* Identifier. */ - GPUVertBuf *vert; /* GPUVertBuf contained in the GPUBatch. */ - GPUBatch *batch; /* GPUBatch containing the GPUVertBuf. */ -} DRWInstancingBuffer; - -typedef struct DRWInstanceChunk { - size_t cursor; /* Offset to the next instance data. */ - size_t alloc_size; /* Number of DRWBatchingBuffer/Batches alloc'd in ibufs/btchs. */ - union { - DRWBatchingBuffer *bbufs; - DRWInstancingBuffer *ibufs; - }; -} DRWInstanceChunk; +#include "intern/gpu_primitive_private.h" struct DRWInstanceData { struct DRWInstanceData *next; @@ -77,212 +53,167 @@ struct DRWInstanceDataList { DRWInstanceData *idata_head[MAX_INSTANCE_DATA_SIZE]; DRWInstanceData *idata_tail[MAX_INSTANCE_DATA_SIZE]; - DRWInstanceChunk instancing; - DRWInstanceChunk batching; + BLI_memblock *pool_instancing; + BLI_memblock *pool_batching; + BLI_memblock *pool_buffers; }; +typedef struct DRWTempBufferHandle { + /** Must be first for casting. */ + GPUVertBuf buf; + /** Format pointer for reuse. */ + GPUVertFormat *format; + /** Touched vertex length for resize. */ + uint *vert_len; +} DRWTempBufferHandle; + static ListBase g_idatalists = {NULL, NULL}; /* -------------------------------------------------------------------- */ /** \name Instance Buffer Management * \{ */ -/** - * This manager allows to distribute existing batches for instancing - * attributes. This reduce the number of batches creation. - * Querying a batch is done with a vertex format. This format should - * be static so that it's pointer never changes (because we are using - * this pointer as identifier [we don't want to check the full format - * that would be too slow]). - */ -static void instance_batch_free(GPUBatch *batch, void *UNUSED(user_data)) +static void instance_batch_free(GPUBatch *geom, void *UNUSED(user_data)) { - if (batch->verts[0] == NULL) { + if (geom->verts[0] == NULL) { /** XXX This is a false positive case. * The batch has been requested but not init yet * and there is a chance that it might become init. */ return; } - /* Free all batches that have the same key before they are reused. */ + + /* Free all batches that use the same vbos before they are reused. */ /* TODO: Make it thread safe! Batch freeing can happen from another thread. */ - /* XXX we need to iterate over all idatalists unless we make some smart - * data structure to store the locations to update. */ - for (DRWInstanceDataList *idatalist = g_idatalists.first; idatalist; - idatalist = idatalist->next) { - DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs; - for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) { - if (ibuf->instance == batch) { - BLI_assert(ibuf->shgroup == NULL); /* Make sure it has no other users. */ - GPU_VERTBUF_DISCARD_SAFE(ibuf->vert); - GPU_BATCH_DISCARD_SAFE(ibuf->batch); - /* Tag as non alloced. */ - ibuf->format = NULL; + /* FIXME: This is not really correct. The correct way would be to check based on + * the vertex buffers. We assume the batch containing the VBO is being when it should. */ + /* PERF: This is doing a linear search. This can be very costly. */ + LISTBASE_FOREACH (DRWInstanceDataList *, data_list, &g_idatalists) { + BLI_memblock *memblock = data_list->pool_instancing; + BLI_memblock_iter iter; + BLI_memblock_iternew(memblock, &iter); + GPUBatch *batch; + while ((batch = (GPUBatch *)BLI_memblock_iterstep(&iter))) { + /* Only check verts[0] that's enough. */ + if (batch->verts[0] == geom->verts[0]) { + GPU_batch_clear(batch); } } } } -void DRW_batching_buffer_request(DRWInstanceDataList *idatalist, - GPUVertFormat *format, - GPUPrimType type, - struct DRWShadingGroup *shgroup, - GPUBatch **r_batch, - GPUVertBuf **r_vert) +/** + * This manager allows to distribute existing batches for instancing + * attributes. This reduce the number of batches creation. + * Querying a batch is done with a vertex format. This format should + * be static so that it's pointer never changes (because we are using + * this pointer as identifier [we don't want to check the full format + * that would be too slow]). + */ +GPUVertBuf *DRW_temp_buffer_request(DRWInstanceDataList *idatalist, + GPUVertFormat *format, + uint *vert_len) { - DRWInstanceChunk *chunk = &idatalist->batching; - DRWBatchingBuffer *bbuf = idatalist->batching.bbufs; - BLI_assert(format); - /* Search for an unused batch. */ - for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) { - if (bbuf->shgroup == NULL) { - if (bbuf->format == format) { - bbuf->shgroup = shgroup; - *r_batch = bbuf->batch; - *r_vert = bbuf->vert; - return; - } - } - } - int new_id = 0; /* Find insertion point. */ - for (; new_id < chunk->alloc_size; ++new_id) { - if (chunk->bbufs[new_id].format == NULL) { - break; - } + BLI_assert(format != NULL); + BLI_assert(vert_len != NULL); + + DRWTempBufferHandle *handle = BLI_memblock_alloc(idatalist->pool_buffers); + GPUVertBuf *vert = &handle->buf; + handle->vert_len = vert_len; + + if (handle->format != format) { + handle->format = format; + /* TODO/PERF: Save the allocated data from freeing to avoid reallocation. */ + GPU_vertbuf_clear(vert); + GPU_vertbuf_init_with_format_ex(vert, format, GPU_USAGE_DYNAMIC); + GPU_vertbuf_data_alloc(vert, DRW_BUFFER_VERTS_CHUNK); } - /* If there is no batch left. Allocate more. */ - if (new_id == chunk->alloc_size) { - new_id = chunk->alloc_size; - chunk->alloc_size += BUFFER_CHUNK_SIZE; - chunk->bbufs = MEM_reallocN(chunk->bbufs, chunk->alloc_size * sizeof(DRWBatchingBuffer)); - memset(chunk->bbufs + new_id, 0, sizeof(DRWBatchingBuffer) * BUFFER_CHUNK_SIZE); - } - /* Create the batch. */ - bbuf = chunk->bbufs + new_id; - bbuf->vert = *r_vert = GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_DYNAMIC); - bbuf->batch = *r_batch = GPU_batch_create_ex(type, bbuf->vert, NULL, 0); - bbuf->format = format; - bbuf->shgroup = shgroup; - GPU_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK); + return vert; } -void DRW_instancing_buffer_request(DRWInstanceDataList *idatalist, - GPUVertFormat *format, - GPUBatch *instance, - struct DRWShadingGroup *shgroup, - GPUBatch **r_batch, - GPUVertBuf **r_vert) +/* NOTE: Does not return a valid drawable batch until DRW_instance_buffer_finish has run. */ +GPUBatch *DRW_temp_batch_instance_request(DRWInstanceDataList *idatalist, + GPUVertBuf *buf, + GPUBatch *geom) { - DRWInstanceChunk *chunk = &idatalist->instancing; - DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs; - BLI_assert(format); - /* Search for an unused batch. */ - for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) { - if (ibuf->shgroup == NULL) { - if (ibuf->format == format) { - if (ibuf->instance == instance) { - ibuf->shgroup = shgroup; - *r_batch = ibuf->batch; - *r_vert = ibuf->vert; - return; - } - } + /* Do not call this with a batch that is already an instancing batch. */ + BLI_assert(geom->inst == NULL); + + GPUBatch *batch = BLI_memblock_alloc(idatalist->pool_instancing); + bool is_compatible = (batch->gl_prim_type == geom->gl_prim_type) && (batch->inst == buf) && + (batch->phase == GPU_BATCH_READY_TO_DRAW); + for (int i = 0; i < GPU_BATCH_VBO_MAX_LEN && is_compatible; i++) { + if (batch->verts[i] != geom->verts[i]) { + is_compatible = false; } } - int new_id = 0; /* Find insertion point. */ - for (; new_id < chunk->alloc_size; ++new_id) { - if (chunk->ibufs[new_id].format == NULL) { - break; - } + + if (!is_compatible) { + GPU_batch_clear(batch); + /* Save args and init later */ + batch->inst = buf; + batch->phase = GPU_BATCH_READY_TO_BUILD; + batch->verts[0] = (void *)geom; /* HACK to save the pointer without other alloc. */ + + /* Make sure to free this batch if the instance geom gets free. */ + GPU_batch_callback_free_set(geom, &instance_batch_free, NULL); } - /* If there is no batch left. Allocate more. */ - if (new_id == chunk->alloc_size) { - new_id = chunk->alloc_size; - chunk->alloc_size += BUFFER_CHUNK_SIZE; - chunk->ibufs = MEM_reallocN(chunk->ibufs, chunk->alloc_size * sizeof(DRWInstancingBuffer)); - memset(chunk->ibufs + new_id, 0, sizeof(DRWInstancingBuffer) * BUFFER_CHUNK_SIZE); + return batch; +} + +/* NOTE: Use only with buf allocated via DRW_temp_buffer_request. */ +GPUBatch *DRW_temp_batch_request(DRWInstanceDataList *idatalist, + GPUVertBuf *buf, + GPUPrimType prim_type) +{ + GPUBatch *batch = BLI_memblock_alloc(idatalist->pool_batching); + bool is_compatible = (batch->verts[0] == buf) && + (batch->gl_prim_type == convert_prim_type_to_gl(prim_type)); + if (!is_compatible) { + GPU_batch_clear(batch); + GPU_batch_init(batch, prim_type, buf, NULL); } - /* Create the batch. */ - ibuf = chunk->ibufs + new_id; - ibuf->vert = *r_vert = GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_DYNAMIC); - ibuf->batch = *r_batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch"); - ibuf->format = format; - ibuf->shgroup = shgroup; - ibuf->instance = instance; - GPU_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK); - /* Make sure to free this ibuf if the instance batch gets free. */ - GPU_batch_callback_free_set(instance, &instance_batch_free, NULL); + return batch; +} + +static void temp_buffer_handle_free(DRWTempBufferHandle *handle) +{ + handle->format = NULL; + GPU_vertbuf_clear(&handle->buf); } void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist) { - size_t realloc_size = 1; /* Avoid 0 size realloc. */ - /* Resize down buffers in use and send data to GPU & free unused buffers. */ - DRWInstanceChunk *batching = &idatalist->batching; - DRWBatchingBuffer *bbuf = batching->bbufs; - for (int i = 0; i < batching->alloc_size; i++, bbuf++) { - if (bbuf->shgroup != NULL) { - realloc_size = i + 1; - uint vert_len = DRW_shgroup_get_instance_count(bbuf->shgroup); - vert_len += (vert_len == 0) ? 1 : 0; /* Do not realloc to 0 size buffer */ - if (vert_len + BUFFER_VERTS_CHUNK <= bbuf->vert->vertex_len) { - uint size = vert_len + BUFFER_VERTS_CHUNK - 1; - size = size - size % BUFFER_VERTS_CHUNK; - GPU_vertbuf_data_resize(bbuf->vert, size); + /* Resize down buffers in use and send data to GPU. */ + BLI_memblock_iter iter; + DRWTempBufferHandle *handle; + BLI_memblock_iternew(idatalist->pool_buffers, &iter); + while ((handle = BLI_memblock_iterstep(&iter))) { + if (handle->vert_len != NULL) { + uint vert_len = *(handle->vert_len); + uint target_buf_size = ((vert_len / DRW_BUFFER_VERTS_CHUNK) + 1) * DRW_BUFFER_VERTS_CHUNK; + if (target_buf_size < handle->buf.vertex_alloc) { + GPU_vertbuf_data_resize(&handle->buf, target_buf_size); } - GPU_vertbuf_use(bbuf->vert); /* Send data. */ - bbuf->shgroup = NULL; /* Set as non used for the next round. */ - } - else { - GPU_VERTBUF_DISCARD_SAFE(bbuf->vert); - GPU_BATCH_DISCARD_SAFE(bbuf->batch); - bbuf->format = NULL; /* Tag as non alloced. */ + GPU_vertbuf_data_len_set(&handle->buf, vert_len); + GPU_vertbuf_use(&handle->buf); /* Send data. */ } } - /* Rounding up to nearest chunk size. */ - realloc_size += BUFFER_CHUNK_SIZE - 1; - realloc_size -= realloc_size % BUFFER_CHUNK_SIZE; - /* Resize down if necessary. */ - if (realloc_size < batching->alloc_size) { - batching->alloc_size = realloc_size; - batching->ibufs = MEM_reallocN(batching->ibufs, realloc_size * sizeof(DRWBatchingBuffer)); - } - - realloc_size = 1; - /* Resize down buffers in use and send data to GPU & free unused buffers. */ - DRWInstanceChunk *instancing = &idatalist->instancing; - DRWInstancingBuffer *ibuf = instancing->ibufs; - for (int i = 0; i < instancing->alloc_size; i++, ibuf++) { - if (ibuf->shgroup != NULL) { - realloc_size = i + 1; - uint vert_len = DRW_shgroup_get_instance_count(ibuf->shgroup); - vert_len += (vert_len == 0) ? 1 : 0; /* Do not realloc to 0 size buffer */ - if (vert_len + BUFFER_VERTS_CHUNK <= ibuf->vert->vertex_len) { - uint size = vert_len + BUFFER_VERTS_CHUNK - 1; - size = size - size % BUFFER_VERTS_CHUNK; - GPU_vertbuf_data_resize(ibuf->vert, size); - } - GPU_vertbuf_use(ibuf->vert); /* Send data. */ - /* Setup batch now that we are sure ibuf->instance is setup. */ - GPU_batch_copy(ibuf->batch, ibuf->instance); - GPU_batch_instbuf_set(ibuf->batch, ibuf->vert, false); - ibuf->shgroup = NULL; /* Set as non used for the next round. */ - } - else { - GPU_VERTBUF_DISCARD_SAFE(ibuf->vert); - GPU_BATCH_DISCARD_SAFE(ibuf->batch); - ibuf->format = NULL; /* Tag as non alloced. */ + /* Finish pending instancing batches. */ + GPUBatch *batch; + BLI_memblock_iternew(idatalist->pool_instancing, &iter); + while ((batch = BLI_memblock_iterstep(&iter))) { + if (batch->phase == GPU_BATCH_READY_TO_BUILD) { + GPUVertBuf *inst = batch->inst; + GPUBatch *geom = (void *)batch->verts[0]; /* HACK see DRW_temp_batch_instance_request. */ + GPU_batch_copy(batch, geom); + GPU_batch_instbuf_set(batch, inst, false); } } - /* Rounding up to nearest chunk size. */ - realloc_size += BUFFER_CHUNK_SIZE - 1; - realloc_size -= realloc_size % BUFFER_CHUNK_SIZE; - /* Resize down if necessary. */ - if (realloc_size < instancing->alloc_size) { - instancing->alloc_size = realloc_size; - instancing->ibufs = MEM_reallocN(instancing->ibufs, - realloc_size * sizeof(DRWInstancingBuffer)); - } + /* Resize pools and free unused. */ + BLI_memblock_clear(idatalist->pool_buffers, (MemblockValFreeFP)temp_buffer_handle_free); + BLI_memblock_clear(idatalist->pool_instancing, (MemblockValFreeFP)GPU_batch_clear); + BLI_memblock_clear(idatalist->pool_batching, (MemblockValFreeFP)GPU_batch_clear); } /** \} */ @@ -352,12 +283,10 @@ DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint DRWInstanceDataList *DRW_instance_data_list_create(void) { DRWInstanceDataList *idatalist = MEM_callocN(sizeof(DRWInstanceDataList), "DRWInstanceDataList"); - idatalist->batching.bbufs = MEM_callocN(sizeof(DRWBatchingBuffer) * BUFFER_CHUNK_SIZE, - "DRWBatchingBuffers"); - idatalist->batching.alloc_size = BUFFER_CHUNK_SIZE; - idatalist->instancing.ibufs = MEM_callocN(sizeof(DRWInstancingBuffer) * BUFFER_CHUNK_SIZE, - "DRWInstancingBuffers"); - idatalist->instancing.alloc_size = BUFFER_CHUNK_SIZE; + + idatalist->pool_batching = BLI_memblock_create(sizeof(GPUBatch), true); + idatalist->pool_instancing = BLI_memblock_create(sizeof(GPUBatch), true); + idatalist->pool_buffers = BLI_memblock_create(sizeof(DRWTempBufferHandle), true); BLI_addtail(&g_idatalists, idatalist); @@ -378,19 +307,9 @@ void DRW_instance_data_list_free(DRWInstanceDataList *idatalist) idatalist->idata_tail[i] = NULL; } - DRWBatchingBuffer *bbuf = idatalist->batching.bbufs; - for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) { - GPU_VERTBUF_DISCARD_SAFE(bbuf->vert); - GPU_BATCH_DISCARD_SAFE(bbuf->batch); - } - MEM_freeN(idatalist->batching.bbufs); - - DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs; - for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) { - GPU_VERTBUF_DISCARD_SAFE(ibuf->vert); - GPU_BATCH_DISCARD_SAFE(ibuf->batch); - } - MEM_freeN(idatalist->instancing.ibufs); + BLI_memblock_destroy(idatalist->pool_buffers, (MemblockValFreeFP)temp_buffer_handle_free); + BLI_memblock_destroy(idatalist->pool_instancing, (MemblockValFreeFP)GPU_batch_clear); + BLI_memblock_destroy(idatalist->pool_batching, (MemblockValFreeFP)GPU_batch_clear); BLI_remlink(&g_idatalists, idatalist); } diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h index ea5c6ac7bb2..d88de1a58e2 100644 --- a/source/blender/draw/intern/draw_instance_data.h +++ b/source/blender/draw/intern/draw_instance_data.h @@ -30,6 +30,8 @@ #define MAX_INSTANCE_DATA_SIZE 64 /* Can be adjusted for more */ +#define DRW_BUFFER_VERTS_CHUNK 128 + typedef struct DRWInstanceData DRWInstanceData; typedef struct DRWInstanceDataList DRWInstanceDataList; @@ -38,18 +40,15 @@ struct DRWShadingGroup; void *DRW_instance_data_next(DRWInstanceData *idata); DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint attr_size); -void DRW_batching_buffer_request(DRWInstanceDataList *idatalist, - GPUVertFormat *format, - GPUPrimType type, - struct DRWShadingGroup *shgroup, - GPUBatch **r_batch, - GPUVertBuf **r_vert); -void DRW_instancing_buffer_request(DRWInstanceDataList *idatalist, - GPUVertFormat *format, - GPUBatch *instance, - struct DRWShadingGroup *shgroup, - GPUBatch **r_batch, - GPUVertBuf **r_vert); +GPUVertBuf *DRW_temp_buffer_request(DRWInstanceDataList *idatalist, + GPUVertFormat *format, + uint *vert_len); +GPUBatch *DRW_temp_batch_instance_request(DRWInstanceDataList *idatalist, + GPUVertBuf *buf, + GPUBatch *geom); +GPUBatch *DRW_temp_batch_request(DRWInstanceDataList *idatalist, + GPUVertBuf *buf, + GPUPrimType type); /* Upload all instance data to the GPU as soon as possible. */ void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 3161528be79..cb4fc826324 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -22,16 +22,19 @@ #include <stdio.h> +#include "BLI_alloca.h" #include "BLI_listbase.h" -#include "BLI_mempool.h" +#include "BLI_memblock.h" #include "BLI_rect.h" #include "BLI_string.h" #include "BLI_threads.h" #include "BLF_api.h" +#include "BKE_anim.h" #include "BKE_colortools.h" #include "BKE_curve.h" +#include "BKE_editmesh.h" #include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_lattice.h" @@ -527,19 +530,19 @@ static void drw_viewport_cache_resize(void) if (DST.vmempool != NULL) { /* Release Image textures. */ - BLI_mempool_iter iter; + BLI_memblock_iter iter; GPUTexture **tex; - BLI_mempool_iternew(DST.vmempool->images, &iter); - while ((tex = BLI_mempool_iterstep(&iter))) { + BLI_memblock_iternew(DST.vmempool->images, &iter); + while ((tex = BLI_memblock_iterstep(&iter))) { GPU_texture_free(*tex); } - BLI_mempool_clear_ex(DST.vmempool->calls, BLI_mempool_len(DST.vmempool->calls)); - BLI_mempool_clear_ex(DST.vmempool->states, BLI_mempool_len(DST.vmempool->states)); - BLI_mempool_clear_ex(DST.vmempool->shgroups, BLI_mempool_len(DST.vmempool->shgroups)); - BLI_mempool_clear_ex(DST.vmempool->uniforms, BLI_mempool_len(DST.vmempool->uniforms)); - BLI_mempool_clear_ex(DST.vmempool->passes, BLI_mempool_len(DST.vmempool->passes)); - BLI_mempool_clear_ex(DST.vmempool->images, BLI_mempool_len(DST.vmempool->images)); + BLI_memblock_clear(DST.vmempool->calls, NULL); + BLI_memblock_clear(DST.vmempool->states, NULL); + BLI_memblock_clear(DST.vmempool->shgroups, NULL); + BLI_memblock_clear(DST.vmempool->uniforms, NULL); + BLI_memblock_clear(DST.vmempool->passes, NULL); + BLI_memblock_clear(DST.vmempool->images, NULL); } DRW_instance_data_list_free_unused(DST.idatalist); @@ -604,24 +607,22 @@ static void drw_viewport_var_init(void) DST.vmempool = GPU_viewport_mempool_get(DST.viewport); if (DST.vmempool->calls == NULL) { - DST.vmempool->calls = BLI_mempool_create(sizeof(DRWCall), 0, 512, 0); + DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall), false); } if (DST.vmempool->states == NULL) { - DST.vmempool->states = BLI_mempool_create( - sizeof(DRWCallState), 0, 512, BLI_MEMPOOL_ALLOW_ITER); + DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState), false); } if (DST.vmempool->shgroups == NULL) { - DST.vmempool->shgroups = BLI_mempool_create(sizeof(DRWShadingGroup), 0, 256, 0); + DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup), false); } if (DST.vmempool->uniforms == NULL) { - DST.vmempool->uniforms = BLI_mempool_create(sizeof(DRWUniform), 0, 512, 0); + DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniform), false); } if (DST.vmempool->passes == NULL) { - DST.vmempool->passes = BLI_mempool_create(sizeof(DRWPass), 0, 64, 0); + DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass), false); } if (DST.vmempool->images == NULL) { - DST.vmempool->images = BLI_mempool_create( - sizeof(GPUTexture *), 0, 512, BLI_MEMPOOL_ALLOW_ITER); + DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *), false); } DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport); @@ -791,6 +792,75 @@ void DRW_viewport_request_redraw(void) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Duplis + * \{ */ + +static void drw_duplidata_load(DupliObject *dupli) +{ + if (dupli == NULL) { + return; + } + + if (DST.dupli_origin != dupli->ob) { + DST.dupli_origin = dupli->ob; + } + else { + /* Same data as previous iter. No need to poll ghash for this. */ + return; + } + + if (DST.dupli_ghash == NULL) { + DST.dupli_ghash = BLI_ghash_ptr_new(__func__); + } + + void **value; + if (!BLI_ghash_ensure_p(DST.dupli_ghash, DST.dupli_origin, &value)) { + *value = MEM_callocN(sizeof(void *) * DST.enabled_engine_count, __func__); + + /* TODO: Meh a bit out of place but this is nice as it is + * only done once per "original" object. */ + drw_batch_cache_validate(DST.dupli_origin); + } + DST.dupli_datas = *(void ***)value; +} + +static void duplidata_value_free(void *val) +{ + void **dupli_datas = val; + for (int i = 0; i < DST.enabled_engine_count; i++) { + MEM_SAFE_FREE(dupli_datas[i]); + } + MEM_freeN(val); +} + +static void drw_duplidata_free(void) +{ + if (DST.dupli_ghash != NULL) { + BLI_ghash_free(DST.dupli_ghash, + (void (*)(void *key))drw_batch_cache_generate_requested, + duplidata_value_free); + DST.dupli_ghash = NULL; + } +} + +/* Return NULL if not a dupli or a pointer of pointer to the engine data */ +void **DRW_duplidata_get(void *vedata) +{ + if (DST.dupli_source == NULL) { + return NULL; + } + /* XXX Search engine index by using vedata array */ + for (int i = 0; i < DST.enabled_engine_count; i++) { + if (DST.vedata_array[i] == vedata) { + return &DST.dupli_datas[i]; + } + } + return NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name ViewLayers (DRW_scenelayer) * \{ */ @@ -1046,9 +1116,14 @@ static void drw_engines_init(void) static void drw_engines_cache_init(void) { - for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DST.enabled_engine_count = BLI_listbase_count(&DST.enabled_engines); + DST.vedata_array = MEM_mallocN(sizeof(void *) * DST.enabled_engine_count, __func__); + + int i = 0; + for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) { DrawEngineType *engine = link->data; ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + DST.vedata_array[i] = data; if (data->text_draw_cache) { DRW_text_cache_destroy(data->text_draw_cache); @@ -1090,9 +1165,15 @@ static void drw_engines_cache_populate(Object *ob) * ourselves here. */ drw_drawdata_unlink_dupli((ID *)ob); - for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + /* Validation for dupli objects happen elsewhere. */ + if (!DST.dupli_source) { + drw_batch_cache_validate(ob); + } + + int i = 0; + for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) { DrawEngineType *engine = link->data; - ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + ViewportEngineData *data = DST.vedata_array[i]; if (engine->id_update) { engine->id_update(data, &ob->id); @@ -1105,7 +1186,9 @@ static void drw_engines_cache_populate(Object *ob) /* TODO: in the future it would be nice to generate once for all viewports. * But we need threaded DRW manager first. */ - drw_batch_cache_generate_requested(ob); + if (!DST.dupli_source) { + drw_batch_cache_generate_requested(ob); + } /* ... and clearing it here too because theses draw data are * from a mempool and must not be free individually by depsgraph. */ @@ -1114,14 +1197,16 @@ static void drw_engines_cache_populate(Object *ob) static void drw_engines_cache_finish(void) { - for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + int i = 0; + for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) { DrawEngineType *engine = link->data; - ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + ViewportEngineData *data = DST.vedata_array[i]; if (engine->cache_finish) { engine->cache_finish(data); } } + MEM_freeN(DST.vedata_array); } static void drw_engines_draw_background(void) @@ -1397,17 +1482,19 @@ static void drw_engines_disable(void) BLI_freelistN(&DST.enabled_engines); } -static uint DRW_engines_get_hash(void) +static void drw_engines_data_validate(void) { - uint hash = 0; - /* The cache depends on enabled engines */ - /* FIXME : if collision occurs ... segfault */ + int enabled_engines = BLI_listbase_count(&DST.enabled_engines); + void **engine_handle_array = BLI_array_alloca(engine_handle_array, enabled_engines + 1); + int i = 0; + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { DrawEngineType *engine = link->data; - hash += BLI_ghashutil_strhash_p(engine->idname); + engine_handle_array[i++] = engine; } + engine_handle_array[i] = NULL; - return hash; + GPU_viewport_engines_data_validate(DST.viewport, engine_handle_array); } /* -------------------------------------------------------------------- */ @@ -1520,8 +1607,6 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, DST.viewport = viewport; /* Setup viewport */ - GPU_viewport_engines_data_validate(DST.viewport, DRW_engines_get_hash()); - DST.draw_ctx = (DRWContextState){ .ar = ar, .rv3d = rv3d, @@ -1541,6 +1626,8 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, /* Get list of enabled engines */ drw_engines_enable(view_layer, engine_type); + drw_engines_data_validate(); + /* Update ubos */ DRW_globals_update(); @@ -1559,23 +1646,31 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, drw_engines_cache_init(); drw_engines_world_update(scene); - const int object_type_exclude_viewport = v3d->object_type_exclude_viewport; - const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | - DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | - DEG_ITER_OBJECT_FLAG_DUPLI; - DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) { - if ((object_type_exclude_viewport & (1 << ob->type)) != 0) { - continue; - } - if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) { - continue; + /* Only iterate over objects for internal engines or when overlays are enabled */ + const bool internal_engine = (engine_type->flag & RE_INTERNAL) != 0; + const bool draw_type_render = v3d->shading.type == OB_RENDER; + const bool overlays_on = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0; + if (internal_engine || overlays_on || !draw_type_render) { + const int object_type_exclude_viewport = v3d->object_type_exclude_viewport; + const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | + DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE | + DEG_ITER_OBJECT_FLAG_DUPLI; + DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) { + if ((object_type_exclude_viewport & (1 << ob->type)) != 0) { + continue; + } + if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) { + continue; + } + DST.dupli_parent = data_.dupli_parent; + DST.dupli_source = data_.dupli_object_current; + drw_duplidata_load(DST.dupli_source); + drw_engines_cache_populate(ob); } - DST.dupli_parent = data_.dupli_parent; - DST.dupli_source = data_.dupli_object_current; - drw_engines_cache_populate(ob); + DEG_OBJECT_ITER_END; } - DEG_OBJECT_ITER_END; + drw_duplidata_free(); drw_engines_cache_finish(); DRW_render_instance_buffer_finish(); @@ -1622,10 +1717,8 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, drw_engines_draw_scene(); -#ifdef __APPLE__ - /* Fix 3D view being "laggy" on macos. (See T56996) */ + /* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */ GPU_flush(); -#endif /* annotations - temporary drawing buffer (3d space) */ /* XXX: Or should we use a proper draw/overlay engine for this case? */ @@ -1792,9 +1885,9 @@ static void DRW_render_gpencil_to_image(RenderEngine *engine, void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph) { - /* This function is only valid for Cycles - * Eevee done all work in the Eevee render directly. - * Maybe it can be done equal for both engines? + /* This function is only valid for Cycles & Workbench + * Eevee does all work in the Eevee render directly. + * Maybe it can be done equal for all engines? */ if (STREQ(engine->type->name, "Eevee")) { return; @@ -1861,7 +1954,7 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph } RenderResult *render_result = RE_engine_get_result(engine); - RenderLayer *render_layer = render_result->layers.first; + RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name); DRW_render_gpencil_to_image(engine, render_layer, &render_rect); @@ -2018,12 +2111,20 @@ void DRW_render_object_iter( DST.dupli_parent = data_.dupli_parent; DST.dupli_source = data_.dupli_object_current; DST.ob_state = NULL; - callback(vedata, ob, engine, depsgraph); + drw_duplidata_load(DST.dupli_source); - drw_batch_cache_generate_requested(ob); + if (!DST.dupli_source) { + drw_batch_cache_validate(ob); + } + callback(vedata, ob, engine, depsgraph); + if (!DST.dupli_source) { + drw_batch_cache_generate_requested(ob); + } } } DEG_OBJECT_ITER_END; + + drw_duplidata_free(); } /* Assume a valid gl context is bound (and that the gl_context_mutex has been acquired). @@ -2253,14 +2354,10 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, drw_engines_world_update(scene); if (use_obedit) { -# if 0 - drw_engines_cache_populate(obact); -# else FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) { drw_engines_cache_populate(ob_iter); } FOREACH_OBJECT_IN_MODE_END; -# endif } else { const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | @@ -2291,16 +2388,18 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, /* This relies on dupli instances being after their instancing object. */ if ((ob->base_flag & BASE_FROM_DUPLI) == 0) { Object *ob_orig = DEG_get_original_object(ob); - DRW_select_load_id(ob_orig->select_id); + DRW_select_load_id(ob_orig->runtime.select_id); } DST.dupli_parent = data_.dupli_parent; DST.dupli_source = data_.dupli_object_current; + drw_duplidata_load(DST.dupli_source); drw_engines_cache_populate(ob); } } DEG_OBJECT_ITER_END; } + drw_duplidata_free(); drw_engines_cache_finish(); DRW_render_instance_buffer_finish(); @@ -2356,8 +2455,6 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, */ static void drw_draw_depth_loop_imp(void) { - DRW_opengl_context_enable(); - /* Setup framebuffer */ DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get( DST.viewport); @@ -2395,10 +2492,12 @@ static void drw_draw_depth_loop_imp(void) DST.dupli_parent = data_.dupli_parent; DST.dupli_source = data_.dupli_object_current; + drw_duplidata_load(DST.dupli_source); drw_engines_cache_populate(ob); } DEG_OBJECT_ITER_END; + drw_duplidata_free(); drw_engines_cache_finish(); DRW_render_instance_buffer_finish(); @@ -2418,9 +2517,6 @@ static void drw_draw_depth_loop_imp(void) /* TODO: Reading depth for operators should be done here. */ GPU_framebuffer_restore(); - - /* Changin context */ - DRW_opengl_context_disable(); } /** @@ -2436,6 +2532,8 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph, ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); RegionView3D *rv3d = ar->regiondata; + DRW_opengl_context_enable(); + /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); @@ -2470,6 +2568,9 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph, /* Avoid accidental reuse. */ drw_state_ensure_not_reused(&DST); #endif + + /* Changin context */ + DRW_opengl_context_disable(); } /** @@ -2484,6 +2585,8 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); RegionView3D *rv3d = ar->regiondata; + DRW_opengl_context_enable(); + /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); @@ -2509,6 +2612,15 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, /* Avoid accidental reuse. */ drw_state_ensure_not_reused(&DST); #endif + + /* Changin context */ + DRW_opengl_context_disable(); +} + +/** See #DRW_shgroup_world_clip_planes_from_rv3d. */ +static void draw_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4]) +{ + GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]); } /** @@ -2554,7 +2666,7 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object) GPU_SHADER_CFG_DEFAULT; GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg); if (world_clip_planes != NULL) { - GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]); + draw_world_clip_planes_from_rv3d(batch, world_clip_planes); } GPU_batch_draw(batch); @@ -2574,6 +2686,203 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object) DRW_opengl_context_disable(); } +static void draw_mesh_verts(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) +{ + GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "offset", offset); + if (world_clip_planes != NULL) { + draw_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); +} + +static void draw_mesh_edges(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) +{ + GPU_line_width(1.0f); + glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); + + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "offset", offset); + if (world_clip_planes != NULL) { + draw_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); + + glProvokingVertex(GL_LAST_VERTEX_CONVENTION); +} + +/* two options, facecolors or black */ +static void draw_mesh_face(GPUBatch *batch, + int offset, + const bool use_select, + const float world_clip_planes[6][4]) +{ + if (use_select) { + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "offset", offset); + if (world_clip_planes != NULL) { + draw_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); + } + else { + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "id", 0); + if (world_clip_planes != NULL) { + draw_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); + } +} + +static void draw_mesh_face_dot(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) +{ + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "offset", offset); + if (world_clip_planes != NULL) { + draw_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); +} + +void DRW_draw_select_id_object(Scene *scene, + RegionView3D *rv3d, + Object *ob, + short select_mode, + bool draw_facedot, + uint initial_offset, + uint *r_vert_offset, + uint *r_edge_offset, + uint *r_face_offset) +{ + ToolSettings *ts = scene->toolsettings; + if (select_mode == -1) { + select_mode = ts->selectmode; + } + + GPU_matrix_mul(ob->obmat); + GPU_depth_test(true); + + const float(*world_clip_planes)[4] = NULL; + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_local(rv3d, ob->obmat); + world_clip_planes = rv3d->clip_local; + } + + initial_offset += 1; + + switch (ob->type) { + case OB_MESH: + if (ob->mode & OB_MODE_EDIT) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_mesh; + const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0; + + DRW_mesh_batch_cache_validate(me); + + BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); + + GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots; + geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + if (select_mode & SCE_SELECT_EDGE) { + geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); + } + if (select_mode & SCE_SELECT_VERTEX) { + geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); + } + if (draw_facedot) { + geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); + } + DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); + + draw_mesh_face(geom_faces, initial_offset, use_faceselect, world_clip_planes); + + if (use_faceselect && draw_facedot) { + draw_mesh_face_dot(geom_facedots, initial_offset, world_clip_planes); + } + + if (select_mode & SCE_SELECT_FACE) { + *r_face_offset = initial_offset + em->bm->totface; + } + else { + *r_face_offset = initial_offset; + } + + ED_view3d_polygon_offset(rv3d, 1.0); + + /* Unlike faces, only draw edges if edge select mode. */ + if (select_mode & SCE_SELECT_EDGE) { + draw_mesh_edges(geom_edges, *r_face_offset, world_clip_planes); + *r_edge_offset = *r_face_offset + em->bm->totedge; + } + else { + /* Note that `r_vert_offset` is calculated from `r_edge_offset`. + * Otherwise the first vertex is never selected, see: T53512. */ + *r_edge_offset = *r_face_offset; + } + + ED_view3d_polygon_offset(rv3d, 1.1); + + /* Unlike faces, only verts if vert select mode. */ + if (select_mode & SCE_SELECT_VERTEX) { + draw_mesh_verts(geom_verts, *r_edge_offset, world_clip_planes); + *r_vert_offset = *r_edge_offset + em->bm->totvert; + } + else { + *r_vert_offset = *r_edge_offset; + } + + ED_view3d_polygon_offset(rv3d, 0.0); + } + else { + Mesh *me_orig = DEG_get_original_object(ob)->data; + Mesh *me_eval = ob->data; + + DRW_mesh_batch_cache_validate(me_eval); + GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval); + if ((me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) && + /* Currently vertex select supports weight paint and vertex paint. */ + ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) { + + GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval); + DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true); + + /* Only draw faces to mask out verts, we don't want their selection ID's. */ + draw_mesh_face(geom_faces, 0, false, world_clip_planes); + draw_mesh_verts(geom_verts, 1, world_clip_planes); + + *r_vert_offset = me_eval->totvert + 1; + } + else { + const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL); + DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide); + + draw_mesh_face(geom_faces, initial_offset, true, world_clip_planes); + + *r_face_offset = initial_offset + me_eval->totface; + } + } + break; + case OB_CURVE: + case OB_SURF: + break; + } + + GPU_matrix_set(rv3d->viewmat); +} + /* Set an opengl context to be used with shaders that draw on U32 colors. */ void DRW_framebuffer_select_id_setup(ARegion *ar, const bool clear) { @@ -2661,7 +2970,8 @@ void DRW_state_dfdy_factors_get(float dfdyfac[2]) */ bool DRW_state_is_fbo(void) { - return ((DST.default_framebuffer != NULL) || DST.options.is_image_render); + return ((DST.default_framebuffer != NULL) || DST.options.is_image_render) && + !DRW_state_is_depth() && !DRW_state_is_select(); } /** @@ -2849,7 +3159,6 @@ void DRW_engines_free(void) DRW_UBO_FREE_SAFE(G_draw.view_ubo); DRW_TEXTURE_FREE_SAFE(G_draw.ramp); DRW_TEXTURE_FREE_SAFE(G_draw.weight_ramp); - MEM_SAFE_FREE(g_pos_format); MEM_SAFE_FREE(DST.uniform_names.buffer); diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 77cf6d20117..b5dc88205db 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -100,15 +100,9 @@ enum { /* Used by DRWCallState.matflag */ enum { DRW_CALL_MODELINVERSE = (1 << 0), - DRW_CALL_MODELVIEW = (1 << 1), - DRW_CALL_MODELVIEWINVERSE = (1 << 2), - DRW_CALL_MODELVIEWPROJECTION = (1 << 3), - DRW_CALL_NORMALVIEW = (1 << 4), - DRW_CALL_NORMALVIEWINVERSE = (1 << 5), - DRW_CALL_NORMALWORLD = (1 << 6), - DRW_CALL_ORCOTEXFAC = (1 << 7), - DRW_CALL_EYEVEC = (1 << 8), - DRW_CALL_OBJECTINFO = (1 << 9), + DRW_CALL_MODELVIEWPROJECTION = (1 << 1), + DRW_CALL_ORCOTEXFAC = (1 << 2), + DRW_CALL_OBJECTINFO = (1 << 3), }; typedef struct DRWCallState { @@ -116,72 +110,38 @@ typedef struct DRWCallState { void *user_data; uchar flag; - uchar cache_id; /* Compared with DST.state_cache_id to see if matrices are still valid. */ - uint16_t matflag; /* Which matrices to compute. */ + uchar cache_id; /* Compared with DST.state_cache_id to see if matrices are still valid. */ + uchar matflag; /* Which matrices to compute. */ + short ob_index; /* Culling: Using Bounding Sphere for now for faster culling. * Not ideal for planes. */ BoundSphere bsphere; /* Matrices */ float model[4][4]; float modelinverse[4][4]; - float modelview[4][4]; - float modelviewinverse[4][4]; float modelviewprojection[4][4]; - float normalview[3][3]; - float normalviewinverse[3][3]; - float normalworld[3][3]; /* Not view dependent */ - float orcotexfac[2][3]; /* Not view dependent */ - float objectinfo[2]; - float eyevec[3]; + float orcotexfac[2][3]; /* Not view dependent */ + float ob_random; } DRWCallState; -typedef enum { - /** A single batch. */ - DRW_CALL_SINGLE, - /** Like single but only draw a range of vertices/indices. */ - DRW_CALL_RANGE, - /** Draw instances without any instancing attributes. */ - DRW_CALL_INSTANCES, - /** Generate a drawcall without any #GPUBatch. */ - DRW_CALL_PROCEDURAL, -} DRWCallType; - typedef struct DRWCall { struct DRWCall *next; DRWCallState *state; - union { - struct { /* type == DRW_CALL_SINGLE */ - GPUBatch *geometry; - short ma_index; - } single; - struct { /* type == DRW_CALL_RANGE */ - GPUBatch *geometry; - uint start, count; - } range; - struct { /* type == DRW_CALL_INSTANCES */ - GPUBatch *geometry; - /* Count can be adjusted between redraw. If needed, we can add fixed count. */ - uint *count; - } instances; - struct { /* type == DRW_CALL_PROCEDURAL */ - uint vert_count; - GPUPrimType prim_type; - } procedural; - }; + GPUBatch *batch; + uint vert_first; + uint vert_count; + uint inst_count; - DRWCallType type; #ifdef USE_GPU_SELECT + /* TODO(fclem) remove once we have a dedicated selection engine. */ int select_id; + GPUVertBuf *inst_selectid; #endif } DRWCall; /* Used by DRWUniform.type */ typedef enum { - DRW_UNIFORM_BOOL, - DRW_UNIFORM_BOOL_COPY, - DRW_UNIFORM_SHORT_TO_INT, - DRW_UNIFORM_SHORT_TO_FLOAT, DRW_UNIFORM_INT, DRW_UNIFORM_INT_COPY, DRW_UNIFORM_FLOAT, @@ -199,8 +159,8 @@ struct DRWUniform { /* For reference or array/vector types. */ const void *pvalue; /* Single values. */ - float fvalue; - int ivalue; + float fvalue[2]; + int ivalue[2]; }; int name_ofs; /* name offset in name buffer. */ int location; @@ -209,43 +169,18 @@ struct DRWUniform { char arraysize; /* cannot be more than 16 too */ }; -typedef enum { - DRW_SHG_NORMAL, - DRW_SHG_POINT_BATCH, - DRW_SHG_LINE_BATCH, - DRW_SHG_TRIANGLE_BATCH, - DRW_SHG_INSTANCE, - DRW_SHG_INSTANCE_EXTERNAL, - DRW_SHG_FEEDBACK_TRANSFORM, -} DRWShadingGroupType; - struct DRWShadingGroup { DRWShadingGroup *next; GPUShader *shader; /* Shader to bind */ DRWUniform *uniforms; /* Uniforms pointers */ - /* Watch this! Can be nasty for debugging. */ - union { - struct { /* DRW_SHG_NORMAL */ - DRWCall *first, *last; /* Linked list of DRWCall or DRWCallDynamic depending of type */ - } calls; - struct { /* DRW_SHG_FEEDBACK_TRANSFORM */ - DRWCall *first, *last; /* Linked list of DRWCall or DRWCallDynamic depending of type */ - struct GPUVertBuf *tfeedback_target; /* Transform Feedback target. */ - }; - struct { /* DRW_SHG_***_BATCH */ - struct GPUBatch *batch_geom; /* Result of call batching */ - struct GPUVertBuf *batch_vbo; - uint primitive_count; - }; - struct { /* DRW_SHG_INSTANCE[_EXTERNAL] */ - struct GPUBatch *instance_geom; - struct GPUVertBuf *instance_vbo; - uint instance_count; - float instance_orcofac[2][3]; /* TODO find a better place. */ - }; - }; + struct { + DRWCall *first, *last; /* Linked list of DRWCall */ + } calls; + + /** TODO Maybe remove from here */ + struct GPUVertBuf *tfeedback_target; /** State changes for this batch only (or'd with the pass's state) */ DRWState state_extra; @@ -253,31 +188,17 @@ struct DRWShadingGroup { DRWState state_extra_disable; /** Stencil mask to use for stencil test / write operations */ uint stencil_mask; - DRWShadingGroupType type; /* Builtin matrices locations */ int model; int modelinverse; - int modelview; - int modelviewinverse; int modelviewprojection; - int normalview; - int normalviewinverse; - int normalworld; int orcotexfac; - int eye; int callid; int objectinfo; - uint16_t matflag; /* Matrices needed, same as DRWCall.flag */ + uchar matflag; /* Matrices needed, same as DRWCall.flag */ DRWPass *pass_parent; /* backlink to pass we're in */ -#ifndef NDEBUG - char attrs_count; -#endif -#ifdef USE_GPU_SELECT - GPUVertBuf *inst_selectid; - int override_selectid; /* Override for single object instances. */ -#endif }; #define MAX_PASS_NAME 32 @@ -293,6 +214,18 @@ struct DRWPass { char name[MAX_PASS_NAME]; }; +/* TODO(fclem): Future awaits */ +#if 0 +typedef struct DRWView { + /* Culling function, culling result etc...*/ +} DRWView; + +typedef struct ModelUboStorage { + float model[4][4]; + float modelinverse[4][4]; +} ModelUboStorage; +#endif + typedef struct ViewUboStorage { DRWMatrixState matstate; float viewcamtexcofac[4]; @@ -329,6 +262,9 @@ typedef struct DRWManager { uchar state_cache_id; /* Could be larger but 254 view changes is already a lot! */ struct DupliObject *dupli_source; struct Object *dupli_parent; + struct Object *dupli_origin; + struct GHash *dupli_ghash; + void **dupli_datas; /* Array of dupli_data (one for each enabled engine) to handle duplis. */ /* Rendering state */ GPUShader *shader; @@ -364,6 +300,8 @@ typedef struct DRWManager { struct DRWTextStore **text_store_p; ListBase enabled_engines; /* RenderEngineType */ + void **vedata_array; /* ViewportEngineData */ + int enabled_engine_count; /* Length of enabled_engines list. */ bool buffer_finish_called; /* Avoid bad usage of DRW_render_instance_buffer_finish */ @@ -437,8 +375,12 @@ void drw_state_set(DRWState state); void drw_debug_draw(void); void drw_debug_init(void); +void drw_batch_cache_validate(Object *ob); void drw_batch_cache_generate_requested(struct Object *ob); -extern struct GPUVertFormat *g_pos_format; +/* Procedural Drawing */ +GPUBatch *drw_cache_procedural_points_get(void); +GPUBatch *drw_cache_procedural_lines_get(void); +GPUBatch *drw_cache_procedural_triangles_get(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 8f324cf08cb..e47433e60ab 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -37,13 +37,12 @@ #include "BLI_hash.h" #include "BLI_link_utils.h" #include "BLI_mempool.h" +#include "BLI_memblock.h" #include "GPU_buffers.h" #include "intern/gpu_codegen.h" -struct GPUVertFormat *g_pos_format = NULL; - /* -------------------------------------------------------------------- */ /** \name Uniform Buffer Object (DRW_uniformbuffer) * \{ */ @@ -76,7 +75,7 @@ static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, int length, int arraysize) { - DRWUniform *uni = BLI_mempool_alloc(DST.vmempool->uniforms); + DRWUniform *uni = BLI_memblock_alloc(DST.vmempool->uniforms); uni->location = loc; uni->type = type; uni->length = length; @@ -84,16 +83,15 @@ static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, switch (type) { case DRW_UNIFORM_INT_COPY: - uni->ivalue = *((int *)value); - break; - case DRW_UNIFORM_BOOL_COPY: - uni->ivalue = (int)*((bool *)value); + BLI_assert(length <= 2); + memcpy(uni->ivalue, value, sizeof(int) * length); break; case DRW_UNIFORM_FLOAT_COPY: - uni->fvalue = *((float *)value); + BLI_assert(length <= 2); + memcpy(uni->fvalue, value, sizeof(float) * length); break; default: - uni->pvalue = value; + uni->pvalue = (const float *)value; break; } @@ -201,7 +199,7 @@ void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const int *value, int arraysize) { - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BOOL, value, 1, arraysize); + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 1, arraysize); } void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, @@ -236,22 +234,6 @@ void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 4, arraysize); } -void DRW_shgroup_uniform_short_to_int(DRWShadingGroup *shgroup, - const char *name, - const short *value, - int arraysize) -{ - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_SHORT_TO_INT, value, 1, arraysize); -} - -void DRW_shgroup_uniform_short_to_float(DRWShadingGroup *shgroup, - const char *name, - const short *value, - int arraysize) -{ - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_SHORT_TO_FLOAT, value, 1, arraysize); -} - void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, @@ -302,7 +284,8 @@ void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, co void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value) { - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BOOL_COPY, &value, 1, 1); + int ival = value; + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT_COPY, &ival, 1, 1); } void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value) @@ -310,6 +293,11 @@ void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, &value, 1, 1); } +void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, const float *value) +{ + drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, value, 2, 1); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -370,13 +358,22 @@ static void drw_call_state_update_matflag(DRWCallState *state, * This is the opposite of what draw_matrices_model_prepare() does. */ state->matflag |= shgroup->matflag; + if (new_flags & DRW_CALL_MODELINVERSE) { + if (ob) { + copy_m4_m4(state->modelinverse, ob->imat); + } + else { + invert_m4_m4(state->modelinverse, state->model); + } + } + /* Orco factors: We compute this at creation to not have to save the *ob_data */ - if ((new_flags & DRW_CALL_ORCOTEXFAC) != 0) { + if (new_flags & DRW_CALL_ORCOTEXFAC) { drw_call_calc_orco(ob, state->orcotexfac); } - if ((new_flags & DRW_CALL_OBJECTINFO) != 0) { - state->objectinfo[0] = ob ? ob->index : 0; + if (new_flags & DRW_CALL_OBJECTINFO) { + state->ob_index = ob ? ob->index : 0; uint random; if (DST.dupli_source) { random = DST.dupli_source->random_id; @@ -384,23 +381,25 @@ static void drw_call_state_update_matflag(DRWCallState *state, else { random = BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0); } - state->objectinfo[1] = random * (1.0f / (float)0xFFFFFFFF); + state->ob_random = random * (1.0f / (float)0xFFFFFFFF); } } static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obmat)[4], Object *ob) { - DRWCallState *state = BLI_mempool_alloc(DST.vmempool->states); + DRWCallState *state = BLI_memblock_alloc(DST.vmempool->states); state->flag = 0; state->cache_id = 0; state->visibility_cb = NULL; state->matflag = 0; + drw_call_state_update_matflag(state, shgroup, ob); + /* Matrices */ if (obmat != NULL) { copy_m4_m4(state->model, obmat); - if (is_negative_m4(state->model)) { + if (ob && (ob->transflag & OB_NEG_SCALE)) { state->flag |= DRW_CALL_NEGSCALE; } } @@ -422,8 +421,6 @@ static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obm state->bsphere.radius = -1.0f; } - drw_call_state_update_matflag(state, shgroup, ob); - return state; } @@ -440,173 +437,179 @@ static DRWCallState *drw_call_state_object(DRWShadingGroup *shgroup, float (*obm return DST.ob_state; } -void DRW_shgroup_call_add(DRWShadingGroup *shgroup, GPUBatch *geom, float (*obmat)[4]) +void DRW_shgroup_call(DRWShadingGroup *shgroup, GPUBatch *geom, float (*obmat)[4]) { BLI_assert(geom != NULL); - BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)); - DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + call->state = drw_call_state_create(shgroup, obmat, NULL); - call->type = DRW_CALL_SINGLE; - call->single.geometry = geom; + call->batch = geom; + call->vert_first = 0; + call->vert_count = 0; /* Auto from batch. */ + call->inst_count = 0; #ifdef USE_GPU_SELECT call->select_id = DST.select_id; + call->inst_selectid = NULL; #endif - - BLI_LINKS_APPEND(&shgroup->calls, call); } -void DRW_shgroup_call_range_add( +void DRW_shgroup_call_range( DRWShadingGroup *shgroup, GPUBatch *geom, float (*obmat)[4], uint v_sta, uint v_count) { BLI_assert(geom != NULL); - BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)); BLI_assert(v_count); - DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + call->state = drw_call_state_create(shgroup, obmat, NULL); - call->type = DRW_CALL_RANGE; - call->range.geometry = geom; - call->range.start = v_sta; - call->range.count = v_count; + call->batch = geom; + call->vert_first = v_sta; + call->vert_count = v_count; + call->inst_count = 0; #ifdef USE_GPU_SELECT call->select_id = DST.select_id; + call->inst_selectid = NULL; #endif - - BLI_LINKS_APPEND(&shgroup->calls, call); } static void drw_shgroup_call_procedural_add_ex(DRWShadingGroup *shgroup, - GPUPrimType prim_type, + GPUBatch *geom, uint vert_count, - float (*obmat)[4], - Object *ob) + float (*obmat)[4]) { - BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)); - DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); - if (ob) { - call->state = drw_call_state_object(shgroup, ob->obmat, ob); - } - else { - call->state = drw_call_state_create(shgroup, obmat, NULL); - } - call->type = DRW_CALL_PROCEDURAL; - call->procedural.prim_type = prim_type; - call->procedural.vert_count = vert_count; + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + + call->state = drw_call_state_object(shgroup, obmat, NULL); + call->batch = geom; + call->vert_first = 0; + call->vert_count = vert_count; + call->inst_count = 0; #ifdef USE_GPU_SELECT call->select_id = DST.select_id; + call->inst_selectid = NULL; #endif - - BLI_LINKS_APPEND(&shgroup->calls, call); } -void DRW_shgroup_call_procedural_points_add(DRWShadingGroup *shgroup, - uint point_len, - float (*obmat)[4]) +void DRW_shgroup_call_procedural_points(DRWShadingGroup *shgroup, + uint point_len, + float (*obmat)[4]) { - drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_POINTS, point_len, obmat, NULL); + struct GPUBatch *geom = drw_cache_procedural_points_get(); + drw_shgroup_call_procedural_add_ex(shgroup, geom, point_len, obmat); } -void DRW_shgroup_call_procedural_lines_add(DRWShadingGroup *shgroup, - uint line_count, - float (*obmat)[4]) +void DRW_shgroup_call_procedural_lines(DRWShadingGroup *shgroup, + uint line_count, + float (*obmat)[4]) { - drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_LINES, line_count * 2, obmat, NULL); + struct GPUBatch *geom = drw_cache_procedural_lines_get(); + drw_shgroup_call_procedural_add_ex(shgroup, geom, line_count * 2, obmat); } -void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup, - uint tria_count, - float (*obmat)[4]) +void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *shgroup, + uint tria_count, + float (*obmat)[4]) { - drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_TRIS, tria_count * 3, obmat, NULL); + struct GPUBatch *geom = drw_cache_procedural_triangles_get(); + drw_shgroup_call_procedural_add_ex(shgroup, geom, tria_count * 3, obmat); } /* These calls can be culled and are optimized for redraw */ -void DRW_shgroup_call_object_add_ex( - DRWShadingGroup *shgroup, GPUBatch *geom, Object *ob, Material *ma, bool bypass_culling) +void DRW_shgroup_call_object_ex(DRWShadingGroup *shgroup, + GPUBatch *geom, + Object *ob, + bool bypass_culling) { BLI_assert(geom != NULL); - BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)); - DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + call->state = drw_call_state_object(shgroup, ob->obmat, ob); - call->type = DRW_CALL_SINGLE; - call->single.geometry = geom; - call->single.ma_index = ma ? ma->index : 0; + /* NOTE this will disable culling for the whole object. */ + call->state->flag |= (bypass_culling) ? DRW_CALL_BYPASS_CULLING : 0; + call->batch = geom; + call->vert_first = 0; + call->vert_count = 0; /* Auto from batch. */ + call->inst_count = 0; #ifdef USE_GPU_SELECT call->select_id = DST.select_id; + call->inst_selectid = NULL; #endif - - /* NOTE this will disable culling for the whole object. */ - call->state->flag |= (bypass_culling) ? DRW_CALL_BYPASS_CULLING : 0; - - BLI_LINKS_APPEND(&shgroup->calls, call); } -void DRW_shgroup_call_object_add_with_callback(DRWShadingGroup *shgroup, - GPUBatch *geom, - Object *ob, - Material *ma, - DRWCallVisibilityFn *callback, - void *user_data) +void DRW_shgroup_call_object_with_callback(DRWShadingGroup *shgroup, + GPUBatch *geom, + Object *ob, + DRWCallVisibilityFn *callback, + void *user_data) { BLI_assert(geom != NULL); - BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)); - DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + call->state = drw_call_state_object(shgroup, ob->obmat, ob); call->state->visibility_cb = callback; call->state->user_data = user_data; - call->type = DRW_CALL_SINGLE; - call->single.geometry = geom; - call->single.ma_index = ma ? ma->index : 0; + call->batch = geom; + call->vert_first = 0; + call->vert_count = 0; /* Auto from batch. */ + call->inst_count = 0; #ifdef USE_GPU_SELECT call->select_id = DST.select_id; + call->inst_selectid = NULL; #endif - - BLI_LINKS_APPEND(&shgroup->calls, call); } -void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup, - GPUBatch *geom, - float (*obmat)[4], - uint *count) +void DRW_shgroup_call_instances(DRWShadingGroup *shgroup, + GPUBatch *geom, + float (*obmat)[4], + uint count) { BLI_assert(geom != NULL); - BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)); - DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + call->state = drw_call_state_create(shgroup, obmat, NULL); - call->type = DRW_CALL_INSTANCES; - call->instances.geometry = geom; - call->instances.count = count; + call->batch = geom; + call->vert_first = 0; + call->vert_count = 0; /* Auto from batch. */ + call->inst_count = count; #ifdef USE_GPU_SELECT call->select_id = DST.select_id; + call->inst_selectid = NULL; #endif - - BLI_LINKS_APPEND(&shgroup->calls, call); } -/* These calls can be culled and are optimized for redraw */ -void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup, - GPUBatch *geom, - Object *ob, - uint *count) +void DRW_shgroup_call_instances_with_attribs(DRWShadingGroup *shgroup, + struct GPUBatch *geom, + float (*obmat)[4], + struct GPUBatch *inst_attributes) { BLI_assert(geom != NULL); - BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)); + BLI_assert(inst_attributes->verts[0] != NULL); - DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls); - call->state = drw_call_state_object(shgroup, ob->obmat, ob); - call->type = DRW_CALL_INSTANCES; - call->instances.geometry = geom; - call->instances.count = count; + GPUVertBuf *buf_inst = inst_attributes->verts[0]; + + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + + call->state = drw_call_state_create(shgroup, obmat, NULL); + call->batch = DRW_temp_batch_instance_request(DST.idatalist, buf_inst, geom); + call->vert_first = 0; + call->vert_count = 0; /* Auto from batch. */ + call->inst_count = buf_inst->vertex_len; #ifdef USE_GPU_SELECT call->select_id = DST.select_id; + call->inst_selectid = NULL; #endif - - BLI_LINKS_APPEND(&shgroup->calls, call); } // #define SCULPT_DEBUG_BUFFERS @@ -614,7 +617,6 @@ void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup, typedef struct DRWSculptCallbackData { Object *ob; DRWShadingGroup **shading_groups; - Material **materials; bool use_wire; bool use_mats; bool use_mask; @@ -642,7 +644,6 @@ static float sculpt_debug_colors[9][4] = { static void sculpt_draw_cb(DRWSculptCallbackData *scd, GPU_PBVH_Buffers *buffers) { GPUBatch *geom = GPU_pbvh_buffers_batch_get(buffers, scd->fast_mode, scd->use_wire); - Material *ma = NULL; short index = 0; /* Meh... use_mask is a bit misleading here. */ @@ -652,7 +653,6 @@ static void sculpt_draw_cb(DRWSculptCallbackData *scd, GPU_PBVH_Buffers *buffers if (scd->use_mats) { index = GPU_pbvh_buffers_material_index_get(buffers); - ma = scd->materials[index]; } DRWShadingGroup *shgrp = scd->shading_groups[index]; @@ -662,9 +662,9 @@ static void sculpt_draw_cb(DRWSculptCallbackData *scd, GPU_PBVH_Buffers *buffers shgrp = DRW_shgroup_create_sub(shgrp); DRW_shgroup_uniform_vec3(shgrp, "materialDiffuseColor", SCULPT_DEBUG_COLOR(scd->node_nr++), 1); #endif - /* DRW_shgroup_call_object_add_ex reuses matrices calculations for all the drawcalls of this + /* DRW_shgroup_call_object_ex reuses matrices calculations for all the drawcalls of this * object. */ - DRW_shgroup_call_object_add_ex(shgrp, geom, scd->ob, ma, true); + DRW_shgroup_call_object_ex(shgrp, geom, scd->ob, true); } } @@ -725,13 +725,12 @@ static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd, bool use_vcol) #endif } -void DRW_shgroup_call_sculpt_add( +void DRW_shgroup_call_sculpt( DRWShadingGroup *shgroup, Object *ob, bool use_wire, bool use_mask, bool use_vcol) { DRWSculptCallbackData scd = { .ob = ob, .shading_groups = &shgroup, - .materials = NULL, .use_wire = use_wire, .use_mats = false, .use_mask = use_mask, @@ -739,15 +738,11 @@ void DRW_shgroup_call_sculpt_add( drw_sculpt_generate_calls(&scd, use_vcol); } -void DRW_shgroup_call_sculpt_with_materials_add(DRWShadingGroup **shgroups, - Material **materials, - Object *ob, - bool use_vcol) +void DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup **shgroups, Object *ob, bool use_vcol) { DRWSculptCallbackData scd = { .ob = ob, .shading_groups = shgroups, - .materials = materials, .use_wire = false, .use_mats = true, .use_mask = false, @@ -755,30 +750,95 @@ void DRW_shgroup_call_sculpt_with_materials_add(DRWShadingGroup **shgroups, drw_sculpt_generate_calls(&scd, use_vcol); } -void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, - const void *attr[], - uint attr_len) +static GPUVertFormat inst_select_format = {0}; + +DRWCallBuffer *DRW_shgroup_call_buffer(DRWShadingGroup *shgroup, + struct GPUVertFormat *format, + GPUPrimType prim_type) { + BLI_assert(ELEM(prim_type, GPU_PRIM_POINTS, GPU_PRIM_LINES, GPU_PRIM_TRI_FAN)); + BLI_assert(format != NULL); + + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + + call->state = drw_call_state_create(shgroup, NULL, NULL); + GPUVertBuf *buf = DRW_temp_buffer_request(DST.idatalist, format, &call->vert_count); + call->batch = DRW_temp_batch_request(DST.idatalist, buf, prim_type); + call->vert_first = 0; + call->vert_count = 0; + call->inst_count = 0; + +#ifdef USE_GPU_SELECT + if (G.f & G_FLAG_PICKSEL) { + /* Not actually used for rendering but alloced in one chunk. */ + if (inst_select_format.attr_len == 0) { + GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT); + } + call->inst_selectid = DRW_temp_buffer_request( + DST.idatalist, &inst_select_format, &call->vert_count); + } +#endif + return (DRWCallBuffer *)call; +} + +DRWCallBuffer *DRW_shgroup_call_buffer_instance(DRWShadingGroup *shgroup, + struct GPUVertFormat *format, + GPUBatch *geom) +{ + BLI_assert(geom != NULL); + BLI_assert(format != NULL); + + DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls); + BLI_LINKS_APPEND(&shgroup->calls, call); + + call->state = drw_call_state_create(shgroup, NULL, NULL); + GPUVertBuf *buf = DRW_temp_buffer_request(DST.idatalist, format, &call->inst_count); + call->batch = DRW_temp_batch_instance_request(DST.idatalist, buf, geom); + call->vert_first = 0; + call->vert_count = 0; /* Auto from batch. */ + call->inst_count = 0; + #ifdef USE_GPU_SELECT if (G.f & G_FLAG_PICKSEL) { - if (shgroup->instance_count == shgroup->inst_selectid->vertex_len) { - GPU_vertbuf_data_resize(shgroup->inst_selectid, shgroup->instance_count + 32); + /* Not actually used for rendering but alloced in one chunk. */ + if (inst_select_format.attr_len == 0) { + GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT); } - GPU_vertbuf_attr_set(shgroup->inst_selectid, 0, shgroup->instance_count, &DST.select_id); + call->inst_selectid = DRW_temp_buffer_request( + DST.idatalist, &inst_select_format, &call->inst_count); } #endif + return (DRWCallBuffer *)call; +} + +void DRW_buffer_add_entry_array(DRWCallBuffer *callbuf, const void *attr[], uint attr_len) +{ + DRWCall *call = (DRWCall *)callbuf; + const bool is_instance = call->batch->inst != NULL; + GPUVertBuf *buf = is_instance ? call->batch->inst : call->batch->verts[0]; + uint count = is_instance ? call->inst_count++ : call->vert_count++; + const bool resize = (count == buf->vertex_alloc); - BLI_assert(attr_len == shgroup->attrs_count); + BLI_assert(attr_len == buf->format.attr_len); UNUSED_VARS_NDEBUG(attr_len); + if (UNLIKELY(resize)) { + GPU_vertbuf_data_resize(buf, count + DRW_BUFFER_VERTS_CHUNK); + } + for (int i = 0; i < attr_len; ++i) { - if (shgroup->instance_count == shgroup->instance_vbo->vertex_len) { - GPU_vertbuf_data_resize(shgroup->instance_vbo, shgroup->instance_count + 32); - } - GPU_vertbuf_attr_set(shgroup->instance_vbo, i, shgroup->instance_count, attr[i]); + GPU_vertbuf_attr_set(buf, i, count, attr[i]); } - shgroup->instance_count += 1; +#ifdef USE_GPU_SELECT + if (G.f & G_FLAG_PICKSEL) { + if (UNLIKELY(resize)) { + GPU_vertbuf_data_resize(call->inst_selectid, count + DRW_BUFFER_VERTS_CHUNK); + } + GPU_vertbuf_attr_set(call->inst_selectid, 0, count, &DST.select_id); + } +#endif } /** \} */ @@ -789,17 +849,7 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) { - shgroup->instance_geom = NULL; - shgroup->instance_vbo = NULL; - shgroup->instance_count = 0; shgroup->uniforms = NULL; -#ifdef USE_GPU_SELECT - shgroup->inst_selectid = NULL; - shgroup->override_selectid = -1; -#endif -#ifndef NDEBUG - shgroup->attrs_count = 0; -#endif int view_ubo_location = GPU_shader_get_uniform_block(shader, "viewBlock"); @@ -828,159 +878,46 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) shgroup, GPU_UNIFORM_CAMERATEXCO, DST.view_data.viewcamtexcofac, 3, 2); } + /* Not supported. */ + BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV) == -1); + BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW) == -1); + BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL) == -1); + shgroup->model = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL); shgroup->modelinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL_INV); - shgroup->modelview = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW); - shgroup->modelviewinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV); shgroup->modelviewprojection = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP); - shgroup->normalview = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL); - shgroup->normalviewinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL_INV); - shgroup->normalworld = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_WORLDNORMAL); shgroup->orcotexfac = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_ORCO); shgroup->objectinfo = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_OBJECT_INFO); - shgroup->eye = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_EYE); shgroup->callid = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CALLID); shgroup->matflag = 0; if (shgroup->modelinverse > -1) { shgroup->matflag |= DRW_CALL_MODELINVERSE; } - if (shgroup->modelview > -1) { - shgroup->matflag |= DRW_CALL_MODELVIEW; - } - if (shgroup->modelviewinverse > -1) { - shgroup->matflag |= DRW_CALL_MODELVIEWINVERSE; - } if (shgroup->modelviewprojection > -1) { shgroup->matflag |= DRW_CALL_MODELVIEWPROJECTION; } - if (shgroup->normalview > -1) { - shgroup->matflag |= DRW_CALL_NORMALVIEW; - } - if (shgroup->normalviewinverse > -1) { - shgroup->matflag |= DRW_CALL_NORMALVIEWINVERSE; - } - if (shgroup->normalworld > -1) { - shgroup->matflag |= DRW_CALL_NORMALWORLD; - } if (shgroup->orcotexfac > -1) { shgroup->matflag |= DRW_CALL_ORCOTEXFAC; } if (shgroup->objectinfo > -1) { shgroup->matflag |= DRW_CALL_OBJECTINFO; } - if (shgroup->eye > -1) { - shgroup->matflag |= DRW_CALL_EYEVEC; - } -} - -static void drw_shgroup_instance_init(DRWShadingGroup *shgroup, - GPUShader *shader, - GPUBatch *batch, - GPUVertFormat *format) -{ - BLI_assert(shgroup->type == DRW_SHG_INSTANCE); - BLI_assert(batch != NULL); - BLI_assert(format != NULL); - - drw_shgroup_init(shgroup, shader); - - shgroup->instance_geom = batch; -#ifndef NDEBUG - shgroup->attrs_count = format->attr_len; -#endif - - DRW_instancing_buffer_request( - DST.idatalist, format, batch, shgroup, &shgroup->instance_geom, &shgroup->instance_vbo); - -#ifdef USE_GPU_SELECT - if (G.f & G_FLAG_PICKSEL) { - /* Not actually used for rendering but alloced in one chunk. - * Plus we don't have to care about ownership. */ - static GPUVertFormat inst_select_format = {0}; - if (inst_select_format.attr_len == 0) { - GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT); - } - GPUBatch *batch_dummy; /* Not used */ - DRW_batching_buffer_request(DST.idatalist, - &inst_select_format, - GPU_PRIM_POINTS, - shgroup, - &batch_dummy, - &shgroup->inst_selectid); - } -#endif -} - -static void drw_shgroup_batching_init(DRWShadingGroup *shgroup, - GPUShader *shader, - GPUVertFormat *format) -{ - drw_shgroup_init(shgroup, shader); - -#ifndef NDEBUG - shgroup->attrs_count = (format != NULL) ? format->attr_len : 0; -#endif - BLI_assert(format != NULL); - - GPUPrimType type; - switch (shgroup->type) { - case DRW_SHG_POINT_BATCH: - type = GPU_PRIM_POINTS; - break; - case DRW_SHG_LINE_BATCH: - type = GPU_PRIM_LINES; - break; - case DRW_SHG_TRIANGLE_BATCH: - type = GPU_PRIM_TRIS; - break; - default: - type = GPU_PRIM_NONE; - BLI_assert(0); - break; - } - - DRW_batching_buffer_request( - DST.idatalist, format, type, shgroup, &shgroup->batch_geom, &shgroup->batch_vbo); - -#ifdef USE_GPU_SELECT - if (G.f & G_FLAG_PICKSEL) { - /* Not actually used for rendering but alloced in one chunk. */ - static GPUVertFormat inst_select_format = {0}; - if (inst_select_format.attr_len == 0) { - GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT); - } - GPUBatch *batch; /* Not used */ - DRW_batching_buffer_request(DST.idatalist, - &inst_select_format, - GPU_PRIM_POINTS, - shgroup, - &batch, - &shgroup->inst_selectid); - } -#endif } static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass) { - DRWShadingGroup *shgroup = BLI_mempool_alloc(DST.vmempool->shgroups); + DRWShadingGroup *shgroup = BLI_memblock_alloc(DST.vmempool->shgroups); BLI_LINKS_APPEND(&pass->shgroups, shgroup); - shgroup->type = DRW_SHG_NORMAL; shgroup->shader = shader; shgroup->state_extra = 0; shgroup->state_extra_disable = ~0x0; shgroup->stencil_mask = 0; shgroup->calls.first = NULL; shgroup->calls.last = NULL; -#if 0 /* All the same in the union! */ - shgroup->batch_geom = NULL; - shgroup->batch_vbo = NULL; - - shgroup->instance_geom = NULL; - shgroup->instance_vbo = NULL; -#endif + shgroup->tfeedback_target = NULL; shgroup->pass_parent = pass; return shgroup; @@ -1016,10 +953,9 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, GPUTexture *tex = NULL; if (input->ima) { - GPUTexture **tex_ref = BLI_mempool_alloc(DST.vmempool->images); + GPUTexture **tex_ref = BLI_memblock_alloc(DST.vmempool->images); - *tex_ref = tex = GPU_texture_from_blender( - input->ima, input->iuser, GL_TEXTURE_2D, input->image_isdata); + *tex_ref = tex = GPU_texture_from_blender(input->ima, input->iuser, GL_TEXTURE_2D); GPU_texture_ref(tex); } @@ -1066,45 +1002,6 @@ DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPa drw_shgroup_init(shgroup, GPU_pass_shader_get(gpupass)); drw_shgroup_material_inputs(shgroup, material); } - - return shgroup; -} - -DRWShadingGroup *DRW_shgroup_material_instance_create( - struct GPUMaterial *material, DRWPass *pass, GPUBatch *geom, Object *ob, GPUVertFormat *format) -{ - GPUPass *gpupass = GPU_material_get_pass(material); - DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass); - - if (shgroup) { - shgroup->type = DRW_SHG_INSTANCE; - shgroup->instance_geom = geom; - drw_call_calc_orco(ob, shgroup->instance_orcofac); - drw_shgroup_instance_init(shgroup, GPU_pass_shader_get(gpupass), geom, format); - drw_shgroup_material_inputs(shgroup, material); - } - - return shgroup; -} - -DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(struct GPUMaterial *material, - DRWPass *pass, - int tri_count) -{ -#ifdef USE_GPU_SELECT - BLI_assert((G.f & G_FLAG_PICKSEL) == 0); -#endif - GPUPass *gpupass = GPU_material_get_pass(material); - DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass); - - if (shgroup) { - /* Calling drw_shgroup_init will cause it to call GPU_draw_primitive(). */ - drw_shgroup_init(shgroup, GPU_pass_shader_get(gpupass)); - shgroup->type = DRW_SHG_TRIANGLE_BATCH; - shgroup->instance_count = tri_count * 3; - drw_shgroup_material_inputs(shgroup, material); - } - return shgroup; } @@ -1115,118 +1012,18 @@ DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass) return shgroup; } -DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, - DRWPass *pass, - GPUBatch *geom, - GPUVertFormat *format) -{ - DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); - shgroup->type = DRW_SHG_INSTANCE; - shgroup->instance_geom = geom; - drw_call_calc_orco(NULL, shgroup->instance_orcofac); - drw_shgroup_instance_init(shgroup, shader, geom, format); - - return shgroup; -} - -DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass) -{ - DRW_shgroup_instance_format(g_pos_format, {{"pos", DRW_ATTR_FLOAT, 3}}); - - DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); - shgroup->type = DRW_SHG_POINT_BATCH; - - drw_shgroup_batching_init(shgroup, shader, g_pos_format); - - return shgroup; -} - -DRWShadingGroup *DRW_shgroup_line_batch_create_with_format(struct GPUShader *shader, - DRWPass *pass, - GPUVertFormat *format) -{ - DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); - shgroup->type = DRW_SHG_LINE_BATCH; - - drw_shgroup_batching_init(shgroup, shader, format); - - return shgroup; -} - -DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass) -{ - DRW_shgroup_instance_format(g_pos_format, {{"pos", DRW_ATTR_FLOAT, 3}}); - - return DRW_shgroup_line_batch_create_with_format(shader, pass, g_pos_format); -} - -/** - * Very special batch. Use this if you position - * your vertices with the vertex shader - * and dont need any VBO attribute. - */ -DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, - DRWPass *pass, - int tri_count) -{ -#ifdef USE_GPU_SELECT - BLI_assert((G.f & G_FLAG_PICKSEL) == 0); -#endif - DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); - - /* Calling drw_shgroup_init will cause it to call GPU_draw_primitive(). */ - drw_shgroup_init(shgroup, shader); - - shgroup->type = DRW_SHG_TRIANGLE_BATCH; - shgroup->instance_count = tri_count * 3; - - return shgroup; -} - DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, DRWPass *pass, GPUVertBuf *tf_target) { BLI_assert(tf_target != NULL); DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); - shgroup->type = DRW_SHG_FEEDBACK_TRANSFORM; - drw_shgroup_init(shgroup, shader); - shgroup->tfeedback_target = tf_target; - return shgroup; } /** - * Specify an external batch instead of adding each attribute one by one. - */ -void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct GPUBatch *batch) -{ - BLI_assert(shgroup->type == DRW_SHG_INSTANCE); - BLI_assert(shgroup->instance_count == 0); - /* You cannot use external instancing batch without a dummy format. */ - BLI_assert(shgroup->attrs_count != 0); - - shgroup->type = DRW_SHG_INSTANCE_EXTERNAL; - drw_call_calc_orco(NULL, shgroup->instance_orcofac); - /* PERF : This destroys the vaos cache so better check if it's necessary. */ - /* Note: This WILL break if batch->verts[0] is destroyed and reallocated - * at the same address. Bindings/VAOs would remain obsolete. */ - // if (shgroup->instancing_geom->inst != batch->verts[0]) - GPU_batch_instbuf_set(shgroup->instance_geom, batch->verts[0], false); - -#ifdef USE_GPU_SELECT - shgroup->override_selectid = DST.select_id; -#endif -} - -uint DRW_shgroup_get_instance_count(const DRWShadingGroup *shgroup) -{ - return shgroup->instance_count; -} - -/** * State is added to #Pass.state while drawing. * Use to temporarily enable draw options. */ @@ -1248,27 +1045,13 @@ void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask) bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup) { - switch (shgroup->type) { - case DRW_SHG_NORMAL: - case DRW_SHG_FEEDBACK_TRANSFORM: - return shgroup->calls.first == NULL; - case DRW_SHG_POINT_BATCH: - case DRW_SHG_LINE_BATCH: - case DRW_SHG_TRIANGLE_BATCH: - case DRW_SHG_INSTANCE: - case DRW_SHG_INSTANCE_EXTERNAL: - return shgroup->instance_count == 0; - } - BLI_assert(!"Shading Group type not supported"); - return true; + return shgroup->calls.first == NULL; } DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup) { /* Remove this assertion if needed but implement the other cases first! */ - BLI_assert(shgroup->type == DRW_SHG_NORMAL); - - DRWShadingGroup *shgroup_new = BLI_mempool_alloc(DST.vmempool->shgroups); + DRWShadingGroup *shgroup_new = BLI_memblock_alloc(DST.vmempool->shgroups); *shgroup_new = *shgroup; shgroup_new->uniforms = NULL; @@ -1288,7 +1071,7 @@ DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup) DRWPass *DRW_pass_create(const char *name, DRWState state) { - DRWPass *pass = BLI_mempool_alloc(DST.vmempool->passes); + DRWPass *pass = BLI_memblock_alloc(DST.vmempool->passes); pass->state = state; if (((G.debug_value > 20) && (G.debug_value < 30)) || (G.debug & G_DEBUG)) { BLI_strncpy(pass->name, name, MAX_PASS_NAME); @@ -1325,12 +1108,6 @@ void DRW_pass_state_remove(DRWPass *pass, DRWState state) pass->state &= ~state; } -void DRW_pass_free(DRWPass *pass) -{ - pass->shgroups.first = NULL; - pass->shgroups.last = NULL; -} - void DRW_pass_foreach_shgroup(DRWPass *pass, void (*callback)(void *userData, DRWShadingGroup *shgrp), void *userData) diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 46f4d0620c8..f76c46a9146 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -23,13 +23,14 @@ #include "draw_manager.h" #include "BLI_math_bits.h" -#include "BLI_mempool.h" +#include "BLI_memblock.h" #include "BKE_global.h" #include "GPU_draw.h" #include "GPU_extensions.h" #include "intern/gpu_shader_private.h" +#include "intern/gpu_primitive_private.h" #ifdef USE_GPU_SELECT # include "GPU_select.h" @@ -791,43 +792,10 @@ static void draw_matrices_model_prepare(DRWCallState *st) if ((st->flag & DRW_CALL_CULLED) != 0 && (st->flag & DRW_CALL_BYPASS_CULLING) == 0) { return; } - /* Order matters */ - if (st->matflag & - (DRW_CALL_MODELVIEW | DRW_CALL_MODELVIEWINVERSE | DRW_CALL_NORMALVIEW | DRW_CALL_EYEVEC)) { - mul_m4_m4m4(st->modelview, DST.view_data.matstate.mat[DRW_MAT_VIEW], st->model); - } - if (st->matflag & DRW_CALL_MODELVIEWINVERSE) { - invert_m4_m4(st->modelviewinverse, st->modelview); - } + if (st->matflag & DRW_CALL_MODELVIEWPROJECTION) { mul_m4_m4m4(st->modelviewprojection, DST.view_data.matstate.mat[DRW_MAT_PERS], st->model); } - if (st->matflag & (DRW_CALL_NORMALVIEW | DRW_CALL_NORMALVIEWINVERSE | DRW_CALL_EYEVEC)) { - copy_m3_m4(st->normalview, st->modelview); - invert_m3(st->normalview); - transpose_m3(st->normalview); - } - if (st->matflag & (DRW_CALL_NORMALVIEWINVERSE | DRW_CALL_EYEVEC)) { - invert_m3_m3(st->normalviewinverse, st->normalview); - } - /* TODO remove eye vec (unused) */ - if (st->matflag & DRW_CALL_EYEVEC) { - /* Used by orthographic wires */ - copy_v3_fl3(st->eyevec, 0.0f, 0.0f, 1.0f); - /* set eye vector, transformed to object coords */ - mul_m3_v3(st->normalviewinverse, st->eyevec); - } - /* Non view dependent */ - if (st->matflag & DRW_CALL_MODELINVERSE) { - invert_m4_m4(st->modelinverse, st->model); - st->matflag &= ~DRW_CALL_MODELINVERSE; - } - if (st->matflag & DRW_CALL_NORMALWORLD) { - copy_m3_m4(st->normalworld, st->model); - invert_m3(st->normalworld); - transpose_m3(st->normalworld); - st->matflag &= ~DRW_CALL_NORMALWORLD; - } } static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call) @@ -835,73 +803,65 @@ static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call) /* step 1 : bind object dependent matrices */ if (call != NULL) { DRWCallState *state = call->state; - float objectinfo[4]; - objectinfo[0] = state->objectinfo[0]; - objectinfo[1] = call->single.ma_index; /* WATCH this is only valid for single drawcalls. */ - objectinfo[2] = state->objectinfo[1]; - objectinfo[3] = (state->flag & DRW_CALL_NEGSCALE) ? -1.0f : 1.0f; - - GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)state->model); - GPU_shader_uniform_vector( - shgroup->shader, shgroup->modelinverse, 16, 1, (float *)state->modelinverse); - GPU_shader_uniform_vector( - shgroup->shader, shgroup->modelview, 16, 1, (float *)state->modelview); - GPU_shader_uniform_vector( - shgroup->shader, shgroup->modelviewinverse, 16, 1, (float *)state->modelviewinverse); - GPU_shader_uniform_vector( - shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)state->modelviewprojection); - GPU_shader_uniform_vector( - shgroup->shader, shgroup->normalview, 9, 1, (float *)state->normalview); - GPU_shader_uniform_vector( - shgroup->shader, shgroup->normalviewinverse, 9, 1, (float *)state->normalviewinverse); - GPU_shader_uniform_vector( - shgroup->shader, shgroup->normalworld, 9, 1, (float *)state->normalworld); - GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)objectinfo); - GPU_shader_uniform_vector( - shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac); - GPU_shader_uniform_vector(shgroup->shader, shgroup->eye, 3, 1, (float *)state->eyevec); + + if (shgroup->model != -1) { + GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)state->model); + } + if (shgroup->modelinverse != -1) { + GPU_shader_uniform_vector( + shgroup->shader, shgroup->modelinverse, 16, 1, (float *)state->modelinverse); + } + if (shgroup->modelviewprojection != -1) { + GPU_shader_uniform_vector(shgroup->shader, + shgroup->modelviewprojection, + 16, + 1, + (float *)state->modelviewprojection); + } + if (shgroup->objectinfo != -1) { + float infos[4]; + infos[0] = state->ob_index; + // infos[1]; /* UNUSED. */ + infos[2] = state->ob_random; + infos[3] = (state->flag & DRW_CALL_NEGSCALE) ? -1.0f : 1.0f; + GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)infos); + } + if (shgroup->orcotexfac != -1) { + GPU_shader_uniform_vector( + shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac); + } } else { - BLI_assert((shgroup->normalview == -1) && (shgroup->normalworld == -1) && - (shgroup->eye == -1)); /* For instancing and batching. */ float unitmat[4][4]; unit_m4(unitmat); - GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)unitmat); - GPU_shader_uniform_vector(shgroup->shader, shgroup->modelinverse, 16, 1, (float *)unitmat); - GPU_shader_uniform_vector(shgroup->shader, - shgroup->modelview, - 16, - 1, - (float *)DST.view_data.matstate.mat[DRW_MAT_VIEW]); - GPU_shader_uniform_vector(shgroup->shader, - shgroup->modelviewinverse, - 16, - 1, - (float *)DST.view_data.matstate.mat[DRW_MAT_VIEWINV]); - GPU_shader_uniform_vector(shgroup->shader, - shgroup->modelviewprojection, - 16, - 1, - (float *)DST.view_data.matstate.mat[DRW_MAT_PERS]); - GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)unitmat); - GPU_shader_uniform_vector( - shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)shgroup->instance_orcofac); + + if (shgroup->model != -1) { + GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)unitmat); + } + if (shgroup->modelinverse != -1) { + GPU_shader_uniform_vector(shgroup->shader, shgroup->modelinverse, 16, 1, (float *)unitmat); + } + if (shgroup->modelviewprojection != -1) { + GPU_shader_uniform_vector(shgroup->shader, + shgroup->modelviewprojection, + 16, + 1, + (float *)DST.view_data.matstate.mat[DRW_MAT_PERS]); + } + if (shgroup->objectinfo != -1) { + GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)unitmat); + } + if (shgroup->orcotexfac != -1) { + float orcofacs[2][3] = {{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}}; + GPU_shader_uniform_vector(shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)orcofacs); + } } } -static void draw_geometry_execute_ex( +static void draw_geometry_execute( DRWShadingGroup *shgroup, GPUBatch *geom, uint start, uint count, bool draw_instance) { - /* Special case: empty drawcall, placement is done via shader, don't bind anything. */ - /* TODO use DRW_CALL_PROCEDURAL instead */ - if (geom == NULL) { - BLI_assert(shgroup->type == DRW_SHG_TRIANGLE_BATCH); /* Add other type if needed. */ - /* Shader is already bound. */ - GPU_draw_primitive(GPU_PRIM_TRIS, count); - return; - } - /* step 2 : bind vertex array & draw */ GPU_batch_program_set_no_use( geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader)); @@ -913,11 +873,6 @@ static void draw_geometry_execute_ex( geom->program_in_use = false; /* XXX hacking gawain */ } -static void draw_geometry_execute(DRWShadingGroup *shgroup, GPUBatch *geom) -{ - draw_geometry_execute_ex(shgroup, geom, 0, 0, false); -} - enum { BIND_NONE = 0, BIND_TEMP = 1, /* Release slot after this shading group. */ @@ -1086,14 +1041,55 @@ static void release_ubo_slots(bool with_persist) } } +BLI_INLINE bool draw_select_do_call(DRWShadingGroup *shgroup, DRWCall *call) +{ +#ifdef USE_GPU_SELECT + if ((G.f & G_FLAG_PICKSEL) == 0) { + return false; + } + if (call->inst_selectid != NULL) { + const bool is_instancing = (call->inst_count != 0); + uint start = 0; + uint count = 1; + uint tot = is_instancing ? call->inst_count : call->vert_count; + /* Hack : get vbo data without actually drawing. */ + GPUVertBufRaw raw; + GPU_vertbuf_attr_get_raw_data(call->inst_selectid, 0, &raw); + int *select_id = GPU_vertbuf_raw_step(&raw); + + /* Batching */ + if (!is_instancing) { + /* FIXME: Meh a bit nasty. */ + if (call->batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_TRIS)) { + count = 3; + } + else if (call->batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_LINES)) { + count = 2; + } + } + + while (start < tot) { + GPU_select_load_id(select_id[start]); + draw_geometry_execute(shgroup, call->batch, start, count, is_instancing); + start += count; + } + return true; + } + else { + GPU_select_load_id(call->select_id); + return false; + } +#else + return false; +#endif +} + static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) { BLI_assert(shgroup->shader); GPUTexture *tex; GPUUniformBuffer *ubo; - int val; - float fval; const bool shader_changed = (DST.shader != shgroup->shader); bool use_tfeedback = false; @@ -1105,8 +1101,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) DST.shader = shgroup->shader; } - if ((pass_state & DRW_STATE_TRANS_FEEDBACK) != 0 && - (shgroup->type == DRW_SHG_FEEDBACK_TRANSFORM)) { + if ((pass_state & DRW_STATE_TRANS_FEEDBACK) != 0 && (shgroup->tfeedback_target != NULL)) { use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader, shgroup->tfeedback_target->vbo_id); } @@ -1126,34 +1121,20 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) continue; } } + const void *data = uni->pvalue; + if (ELEM(uni->type, DRW_UNIFORM_INT_COPY, DRW_UNIFORM_FLOAT_COPY)) { + data = uni->fvalue; + } switch (uni->type) { - case DRW_UNIFORM_SHORT_TO_INT: - val = (int)*((short *)uni->pvalue); - GPU_shader_uniform_vector_int( - shgroup->shader, uni->location, uni->length, uni->arraysize, &val); - break; - case DRW_UNIFORM_SHORT_TO_FLOAT: - fval = (float)*((short *)uni->pvalue); - GPU_shader_uniform_vector( - shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)&fval); - break; - case DRW_UNIFORM_BOOL_COPY: case DRW_UNIFORM_INT_COPY: - GPU_shader_uniform_vector_int( - shgroup->shader, uni->location, uni->length, uni->arraysize, &uni->ivalue); - break; - case DRW_UNIFORM_BOOL: case DRW_UNIFORM_INT: GPU_shader_uniform_vector_int( - shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)uni->pvalue); + shgroup->shader, uni->location, uni->length, uni->arraysize, data); break; case DRW_UNIFORM_FLOAT_COPY: - GPU_shader_uniform_vector( - shgroup->shader, uni->location, uni->length, uni->arraysize, &uni->fvalue); - break; case DRW_UNIFORM_FLOAT: GPU_shader_uniform_vector( - shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)uni->pvalue); + shgroup->shader, uni->location, uni->length, uni->arraysize, data); break; case DRW_UNIFORM_TEXTURE: tex = (GPUTexture *)uni->pvalue; @@ -1186,102 +1167,10 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) } } -#ifdef USE_GPU_SELECT -# define GPU_SELECT_LOAD_IF_PICKSEL(_select_id) \ - if (G.f & G_FLAG_PICKSEL) { \ - GPU_select_load_id(_select_id); \ - } \ - ((void)0) - -# define GPU_SELECT_LOAD_IF_PICKSEL_CALL(_call) \ - if ((G.f & G_FLAG_PICKSEL) && (_call)) { \ - GPU_select_load_id((_call)->select_id); \ - } \ - ((void)0) - -# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \ - _start = 0; \ - _count = _shgroup->instance_count; \ - int *select_id = NULL; \ - if (G.f & G_FLAG_PICKSEL) { \ - if (_shgroup->override_selectid == -1) { \ - /* Hack : get vbo data without actually drawing. */ \ - GPUVertBufRaw raw; \ - GPU_vertbuf_attr_get_raw_data(_shgroup->inst_selectid, 0, &raw); \ - select_id = GPU_vertbuf_raw_step(&raw); \ - switch (_shgroup->type) { \ - case DRW_SHG_TRIANGLE_BATCH: \ - _count = 3; \ - break; \ - case DRW_SHG_LINE_BATCH: \ - _count = 2; \ - break; \ - default: \ - _count = 1; \ - break; \ - } \ - } \ - else { \ - GPU_select_load_id(_shgroup->override_selectid); \ - } \ - } \ - while (_start < _shgroup->instance_count) { \ - if (select_id) { \ - GPU_select_load_id(select_id[_start]); \ - } - -# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(_start, _count) \ - _start += _count; \ - } \ - ((void)0) - -#else -# define GPU_SELECT_LOAD_IF_PICKSEL(select_id) -# define GPU_SELECT_LOAD_IF_PICKSEL_CALL(call) -# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count) ((void)0) -# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \ - _start = 0; \ - _count = _shgroup->instance_count; - -#endif - BLI_assert(ubo_bindings_validate(shgroup)); /* Rendering Calls */ - if (!ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)) { - /* Replacing multiple calls with only one */ - if (ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_INSTANCE_EXTERNAL)) { - if (shgroup->type == DRW_SHG_INSTANCE_EXTERNAL) { - if (shgroup->instance_geom != NULL) { - GPU_SELECT_LOAD_IF_PICKSEL(shgroup->override_selectid); - draw_geometry_prepare(shgroup, NULL); - draw_geometry_execute_ex(shgroup, shgroup->instance_geom, 0, 0, true); - } - } - else { - if (shgroup->instance_count > 0) { - uint count, start; - draw_geometry_prepare(shgroup, NULL); - GPU_SELECT_LOAD_IF_PICKSEL_LIST (shgroup, start, count) { - draw_geometry_execute_ex(shgroup, shgroup->instance_geom, start, count, true); - } - GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count); - } - } - } - else { /* DRW_SHG_***_BATCH */ - /* Some dynamic batch can have no geom (no call to aggregate) */ - if (shgroup->instance_count > 0) { - uint count, start; - draw_geometry_prepare(shgroup, NULL); - GPU_SELECT_LOAD_IF_PICKSEL_LIST (shgroup, start, count) { - draw_geometry_execute_ex(shgroup, shgroup->batch_geom, start, count, false); - } - GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count); - } - } - } - else { + { bool prev_neg_scale = false; int callid = 0; for (DRWCall *call = shgroup->calls.first; call; call = call->next) { @@ -1308,26 +1197,18 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) prev_neg_scale = neg_scale; } - GPU_SELECT_LOAD_IF_PICKSEL_CALL(call); draw_geometry_prepare(shgroup, call); - switch (call->type) { - case DRW_CALL_SINGLE: - draw_geometry_execute(shgroup, call->single.geometry); - break; - case DRW_CALL_RANGE: - draw_geometry_execute_ex( - shgroup, call->range.geometry, call->range.start, call->range.count, false); - break; - case DRW_CALL_INSTANCES: - draw_geometry_execute_ex( - shgroup, call->instances.geometry, 0, *call->instances.count, true); - break; - case DRW_CALL_PROCEDURAL: - GPU_draw_primitive(call->procedural.prim_type, call->procedural.vert_count); - break; - default: - BLI_assert(0); + if (draw_select_do_call(shgroup, call)) { + continue; + } + + /* TODO revisit when DRW_SHG_INSTANCE and the like is gone. */ + if (call->inst_count == 0) { + draw_geometry_execute(shgroup, call->batch, call->vert_first, call->vert_count, false); + } + else { + draw_geometry_execute(shgroup, call->batch, 0, call->inst_count, true); } } /* Reset state */ @@ -1352,10 +1233,10 @@ static void drw_update_view(void) DST.state_cache_id = 1; /* We must reset all CallStates to ensure that not * a single one stayed with cache_id equal to 1. */ - BLI_mempool_iter iter; + BLI_memblock_iter iter; DRWCallState *state; - BLI_mempool_iternew(DST.vmempool->states, &iter); - while ((state = BLI_mempool_iterstep(&iter))) { + BLI_memblock_iternew(DST.vmempool->states, &iter); + while ((state = BLI_memblock_iterstep(&iter))) { state->cache_id = 0; } } diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index b60a41ab0c9..186bbae5cad 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -394,6 +394,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene, if (mat == NULL) { scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id); mat = GPU_material_from_nodetree(scene, + NULL, wo->nodetree, &wo->gpumaterial, engine_type, @@ -430,6 +431,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene, if (mat == NULL) { scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id); mat = GPU_material_from_nodetree(scene, + ma, ma->nodetree, &ma->gpumaterial, engine_type, diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c index e47393c88c4..5177a8f4cd0 100644 --- a/source/blender/draw/modes/edit_curve_mode.c +++ b/source/blender/draw/modes/edit_curve_mode.c @@ -39,6 +39,7 @@ * Not needed for constant color. */ extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; extern char datatoc_edit_curve_overlay_loosevert_vert_glsl[]; extern char datatoc_edit_curve_overlay_normals_vert_glsl[]; extern char datatoc_edit_curve_overlay_handle_vert_glsl[]; @@ -124,8 +125,10 @@ static void EDIT_CURVE_engine_init(void *UNUSED(vedata)) if (!sh_data->wire_normals_sh) { sh_data->wire_normals_sh = GPU_shader_create_from_arrays({ - .vert = - (const char *[]){sh_cfg_data->lib, datatoc_edit_curve_overlay_normals_vert_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_edit_curve_overlay_normals_vert_glsl, + NULL}, .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); @@ -133,8 +136,10 @@ static void EDIT_CURVE_engine_init(void *UNUSED(vedata)) if (!sh_data->overlay_edge_sh) { sh_data->overlay_edge_sh = GPU_shader_create_from_arrays({ - .vert = - (const char *[]){sh_cfg_data->lib, datatoc_edit_curve_overlay_handle_vert_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_edit_curve_overlay_handle_vert_glsl, + NULL}, .geom = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, datatoc_edit_curve_overlay_handle_geom_glsl, @@ -148,6 +153,7 @@ static void EDIT_CURVE_engine_init(void *UNUSED(vedata)) sh_data->overlay_vert_sh = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, + datatoc_common_view_lib_glsl, datatoc_edit_curve_overlay_loosevert_vert_glsl, NULL}, .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL}, @@ -270,31 +276,30 @@ static void EDIT_CURVE_cache_populate(void *vedata, Object *ob) } geom = DRW_cache_curve_edge_wire_get(ob); - DRW_shgroup_call_add(wire_shgrp, geom, ob->obmat); + DRW_shgroup_call(wire_shgrp, geom, ob->obmat); if ((cu->flag & CU_3D) && (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_NORMALS) != 0) { - static uint instance_len = 2; geom = DRW_cache_curve_edge_normal_get(ob); - DRW_shgroup_call_instances_add(wire_normals_shgrp, geom, ob->obmat, &instance_len); + DRW_shgroup_call_instances(wire_normals_shgrp, geom, ob->obmat, 2); } geom = DRW_cache_curve_edge_overlay_get(ob); if (geom) { - DRW_shgroup_call_add(stl->g_data->overlay_edge_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->overlay_edge_shgrp, geom, ob->obmat); } geom = DRW_cache_curve_vert_overlay_get(ob, stl->g_data->show_handles); - DRW_shgroup_call_add(stl->g_data->overlay_vert_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->overlay_vert_shgrp, geom, ob->obmat); } } if (ob->type == OB_SURF) { if (BKE_object_is_in_editmode(ob)) { struct GPUBatch *geom = DRW_cache_curve_edge_overlay_get(ob); - DRW_shgroup_call_add(stl->g_data->overlay_edge_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->overlay_edge_shgrp, geom, ob->obmat); geom = DRW_cache_curve_vert_overlay_get(ob, false); - DRW_shgroup_call_add(stl->g_data->overlay_vert_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->overlay_vert_shgrp, geom, ob->obmat); } } } diff --git a/source/blender/draw/modes/edit_lattice_mode.c b/source/blender/draw/modes/edit_lattice_mode.c index 273480b8127..cede3ed12c6 100644 --- a/source/blender/draw/modes/edit_lattice_mode.c +++ b/source/blender/draw/modes/edit_lattice_mode.c @@ -32,6 +32,7 @@ #include "draw_mode_engines.h" extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; extern char datatoc_edit_lattice_overlay_loosevert_vert_glsl[]; extern char datatoc_edit_lattice_overlay_frag_glsl[]; @@ -152,6 +153,7 @@ static void EDIT_LATTICE_engine_init(void *vedata) sh_data->overlay_vert = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, + datatoc_common_view_lib_glsl, datatoc_edit_lattice_overlay_loosevert_vert_glsl, NULL}, .frag = (const char *[]){datatoc_common_globals_lib_glsl, @@ -212,10 +214,10 @@ static void EDIT_LATTICE_cache_populate(void *vedata, Object *ob) struct GPUBatch *geom; geom = DRW_cache_lattice_wire_get(ob, true); - DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->wire_shgrp, geom, ob->obmat); geom = DRW_cache_lattice_vert_overlay_get(ob); - DRW_shgroup_call_add(stl->g_data->vert_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->vert_shgrp, geom, ob->obmat); } } } diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index ffe7fe5845c..ee2d6239c41 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -60,6 +60,7 @@ extern char datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl[]; extern char datatoc_edit_normals_vert_glsl[]; extern char datatoc_edit_normals_geom_glsl[]; extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; @@ -197,6 +198,7 @@ static void EDIT_MESH_engine_init(void *vedata) sh_data->weight_face = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, + datatoc_common_view_lib_glsl, datatoc_paint_weight_vert_glsl, NULL}, .frag = (const char *[]){datatoc_common_globals_lib_glsl, @@ -207,6 +209,7 @@ static void EDIT_MESH_engine_init(void *vedata) char *lib = BLI_string_joinN(sh_cfg_data->lib, datatoc_common_globals_lib_glsl, + datatoc_common_view_lib_glsl, datatoc_edit_mesh_overlay_common_lib_glsl); /* Use geometry shader to draw edge wireframe. This ensure us * the same result accross platforms and more flexibility. But @@ -265,43 +268,43 @@ static void EDIT_MESH_engine_init(void *vedata) sh_data->overlay_mix = DRW_shader_create_fullscreen(datatoc_edit_mesh_overlay_mix_frag_glsl, NULL); + lib = BLI_string_joinN(sh_cfg_data->lib, datatoc_common_view_lib_glsl); + sh_data->normals_face = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_vert_glsl, NULL}, - .geom = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_geom_glsl, NULL}, + .vert = (const char *[]){lib, datatoc_edit_normals_vert_glsl, NULL}, + .geom = (const char *[]){lib, datatoc_edit_normals_geom_glsl, NULL}, .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, "#define FACE_NORMALS\n", NULL}, }); sh_data->normals_loop = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_vert_glsl, NULL}, - .geom = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_geom_glsl, NULL}, + .vert = (const char *[]){lib, datatoc_edit_normals_vert_glsl, NULL}, + .geom = (const char *[]){lib, datatoc_edit_normals_geom_glsl, NULL}, .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, "#define LOOP_NORMALS\n", NULL}, }); sh_data->normals = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_vert_glsl, NULL}, - .geom = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_geom_glsl, NULL}, + .vert = (const char *[]){lib, datatoc_edit_normals_vert_glsl, NULL}, + .geom = (const char *[]){lib, datatoc_edit_normals_geom_glsl, NULL}, .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); /* Mesh Analysis */ sh_data->mesh_analysis_face = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, - datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl, - NULL}, + .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl, NULL}, .frag = (const char *[]){datatoc_edit_mesh_overlay_mesh_analysis_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, "#define FACE_COLOR\n", NULL}, }); sh_data->mesh_analysis_vertex = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, - datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl, - NULL}, + .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl, NULL}, .frag = (const char *[]){datatoc_edit_mesh_overlay_mesh_analysis_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, "#define VERTEX_COLOR\n", NULL}, }); + MEM_freeN(lib); + sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg); } } @@ -603,7 +606,7 @@ static void EDIT_MESH_cache_init(void *vedata) psl->mix_occlude = DRW_pass_create("Mix Occluded Wires", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); DRWShadingGroup *mix_shgrp = DRW_shgroup_create(sh_data->overlay_mix, psl->mix_occlude); - DRW_shgroup_call_add(mix_shgrp, quad, NULL); + DRW_shgroup_call(mix_shgrp, quad, NULL); DRW_shgroup_uniform_float(mix_shgrp, "alpha", &backwire_opacity, 1); DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireColor", &e_data.occlude_wire_color_tx); DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireDepth", &e_data.occlude_wire_depth_tx); @@ -636,17 +639,17 @@ static void edit_mesh_add_ob_to_pass(Scene *scene, geom_tris = DRW_mesh_batch_cache_get_edit_triangles(ob->data); geom_edges = DRW_mesh_batch_cache_get_edit_edges(ob->data); - DRW_shgroup_call_add(edge_shgrp, geom_edges, ob->obmat); - DRW_shgroup_call_add(face_shgrp, geom_tris, ob->obmat); + DRW_shgroup_call(edge_shgrp, geom_edges, ob->obmat); + DRW_shgroup_call(face_shgrp, geom_tris, ob->obmat); if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) { geom_verts = DRW_mesh_batch_cache_get_edit_vertices(ob->data); - DRW_shgroup_call_add(vert_shgrp, geom_verts, ob->obmat); + DRW_shgroup_call(vert_shgrp, geom_verts, ob->obmat); } if (facedot_shgrp && (tsettings->selectmode & SCE_SELECT_FACE) != 0) { geom_fcenter = DRW_mesh_batch_cache_get_edit_facedots(ob->data); - DRW_shgroup_call_add(facedot_shgrp, geom_fcenter, ob->obmat); + DRW_shgroup_call(facedot_shgrp, geom_fcenter, ob->obmat); } } @@ -691,7 +694,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob) if (do_show_weight) { geom = DRW_cache_mesh_surface_weights_get(ob); - DRW_shgroup_call_add(g_data->fweights_shgrp, geom, ob->obmat); + DRW_shgroup_call(g_data->fweights_shgrp, geom, ob->obmat); } if (do_show_mesh_analysis) { @@ -702,30 +705,30 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob) if (is_original) { geom = DRW_cache_mesh_surface_mesh_analysis_get(ob); if (geom) { - DRW_shgroup_call_add(g_data->mesh_analysis_shgrp, geom, ob->obmat); + DRW_shgroup_call(g_data->mesh_analysis_shgrp, geom, ob->obmat); } } } if (do_occlude_wire || do_in_front) { geom = DRW_cache_mesh_surface_get(ob); - DRW_shgroup_call_add(do_in_front ? g_data->depth_shgrp_hidden_wire_in_front : - g_data->depth_shgrp_hidden_wire, - geom, - ob->obmat); + DRW_shgroup_call(do_in_front ? g_data->depth_shgrp_hidden_wire_in_front : + g_data->depth_shgrp_hidden_wire, + geom, + ob->obmat); } if (vnormals_do) { geom = DRW_mesh_batch_cache_get_edit_vertices(ob->data); - DRW_shgroup_call_add(g_data->vnormals_shgrp, geom, ob->obmat); + DRW_shgroup_call(g_data->vnormals_shgrp, geom, ob->obmat); } if (lnormals_do) { geom = DRW_mesh_batch_cache_get_edit_lnors(ob->data); - DRW_shgroup_call_add(g_data->lnormals_shgrp, geom, ob->obmat); + DRW_shgroup_call(g_data->lnormals_shgrp, geom, ob->obmat); } if (fnormals_do) { geom = DRW_mesh_batch_cache_get_edit_facedots(ob->data); - DRW_shgroup_call_add(g_data->fnormals_shgrp, geom, ob->obmat); + DRW_shgroup_call(g_data->fnormals_shgrp, geom, ob->obmat); } if (g_data->do_zbufclip) { diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c index aa7c6863423..11ff95a212b 100644 --- a/source/blender/draw/modes/edit_metaball_mode.c +++ b/source/blender/draw/modes/edit_metaball_mode.c @@ -26,6 +26,8 @@ #include "BKE_object.h" +#include "DEG_depsgraph_query.h" + #include "ED_mball.h" /* If builtin shaders are needed */ @@ -86,7 +88,7 @@ typedef struct EDIT_METABALL_Data { typedef struct EDIT_METABALL_PrivateData { /* This keeps the references of the shading groups for * easy access in EDIT_METABALL_cache_populate() */ - DRWShadingGroup *group; + DRWCallBuffer *group; } EDIT_METABALL_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ @@ -119,7 +121,7 @@ static void EDIT_METABALL_cache_init(void *vedata) psl->pass = DRW_pass_create("My Pass", state); /* Create a shadingGroup using a function in draw_common.c or custom one */ - stl->g_data->group = shgroup_instance_mball_handles(psl->pass, draw_ctx->sh_cfg); + stl->g_data->group = buffer_instance_mball_handles(psl->pass, draw_ctx->sh_cfg); } } @@ -131,7 +133,7 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob) if (ob->type == OB_MBALL) { const DRWContextState *draw_ctx = DRW_context_state_get(); - DRWShadingGroup *group = stl->g_data->group; + DRWCallBuffer *group = stl->g_data->group; if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) { MetaBall *mb = ob->data; @@ -160,7 +162,8 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob) copy_v3_v3(draw_scale_xform[2], scamat[2]); } - int select_id = ob->select_id; + const Object *orig_object = DEG_get_original_object(ob); + int select_id = orig_object->runtime.select_id; for (MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next, select_id += 0x10000) { float world_pos[3]; mul_v3_m4v3(world_pos, ob->obmat, &ml->x); @@ -181,7 +184,7 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob) DRW_select_load_id(select_id | MBALLSEL_RADIUS); } - DRW_shgroup_call_dynamic_add(group, draw_scale_xform, &ml->rad, color); + DRW_buffer_add_entry(group, draw_scale_xform, &ml->rad, color); if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) { color = col_stiffness_select; @@ -194,7 +197,7 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob) DRW_select_load_id(select_id | MBALLSEL_STIFF); } - DRW_shgroup_call_dynamic_add(group, draw_scale_xform, &draw_stiffness_radius, color); + DRW_buffer_add_entry(group, draw_scale_xform, &draw_stiffness_radius, color); } } } diff --git a/source/blender/draw/modes/edit_text_mode.c b/source/blender/draw/modes/edit_text_mode.c index 5f44a74b24e..fa2248e9aa5 100644 --- a/source/blender/draw/modes/edit_text_mode.c +++ b/source/blender/draw/modes/edit_text_mode.c @@ -102,8 +102,8 @@ typedef struct EDIT_TEXT_PrivateData { DRWShadingGroup *wire_shgrp; DRWShadingGroup *overlay_select_shgrp; DRWShadingGroup *overlay_cursor_shgrp; - DRWShadingGroup *box_shgrp; - DRWShadingGroup *box_active_shgrp; + DRWCallBuffer *box_shgrp; + DRWCallBuffer *box_active_shgrp; } EDIT_TEXT_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ @@ -179,9 +179,9 @@ static void EDIT_TEXT_cache_init(void *vedata) psl->text_box_pass = DRW_pass_create("Font Text Boxes", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH); - stl->g_data->box_shgrp = shgroup_dynlines_dashed_uniform_color( + stl->g_data->box_shgrp = buffer_dynlines_dashed_uniform_color( psl->text_box_pass, G_draw.block.colorWire, draw_ctx->sh_cfg); - stl->g_data->box_active_shgrp = shgroup_dynlines_dashed_uniform_color( + stl->g_data->box_active_shgrp = buffer_dynlines_dashed_uniform_color( psl->text_box_pass, G_draw.block.colorActive, draw_ctx->sh_cfg); } } @@ -241,7 +241,7 @@ static void edit_text_cache_populate_select(void *vedata, Object *ob) v2_quad_corners_to_mat4(box, final_mat); mul_m4_m4m4(final_mat, ob->obmat, final_mat); - DRW_shgroup_call_add(stl->g_data->overlay_select_shgrp, geom, final_mat); + DRW_shgroup_call(stl->g_data->overlay_select_shgrp, geom, final_mat); } } @@ -257,7 +257,7 @@ static void edit_text_cache_populate_cursor(void *vedata, Object *ob) mul_m4_m4m4(mat, ob->obmat, mat); struct GPUBatch *geom = DRW_cache_quad_get(); - DRW_shgroup_call_add(stl->g_data->overlay_cursor_shgrp, geom, mat); + DRW_shgroup_call(stl->g_data->overlay_cursor_shgrp, geom, mat); } static void edit_text_cache_populate_boxes(void *vedata, Object *ob) @@ -265,7 +265,7 @@ static void edit_text_cache_populate_boxes(void *vedata, Object *ob) EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl; const Curve *cu = ob->data; - DRWShadingGroup *shading_groups[] = { + DRWCallBuffer *callbufs[] = { stl->g_data->box_active_shgrp, stl->g_data->box_shgrp, }; @@ -279,7 +279,7 @@ static void edit_text_cache_populate_boxes(void *vedata, Object *ob) } const bool is_active = i == (cu->actbox - 1); - DRWShadingGroup *shading_group = shading_groups[is_active ? 0 : 1]; + DRWCallBuffer *callbuf = callbufs[is_active ? 0 : 1]; vec[0] = cu->xof + tb->x; vec[1] = cu->yof + tb->y + cu->fsize_realtime; @@ -289,29 +289,29 @@ static void edit_text_cache_populate_boxes(void *vedata, Object *ob) vec[0] += tb->w; mul_v3_m4v3(vec2, ob->obmat, vec); - DRW_shgroup_call_dynamic_add(shading_group, vec1); - DRW_shgroup_call_dynamic_add(shading_group, vec2); + DRW_buffer_add_entry(callbuf, vec1); + DRW_buffer_add_entry(callbuf, vec2); vec[1] -= tb->h; copy_v3_v3(vec1, vec2); mul_v3_m4v3(vec2, ob->obmat, vec); - DRW_shgroup_call_dynamic_add(shading_group, vec1); - DRW_shgroup_call_dynamic_add(shading_group, vec2); + DRW_buffer_add_entry(callbuf, vec1); + DRW_buffer_add_entry(callbuf, vec2); vec[0] -= tb->w; copy_v3_v3(vec1, vec2); mul_v3_m4v3(vec2, ob->obmat, vec); - DRW_shgroup_call_dynamic_add(shading_group, vec1); - DRW_shgroup_call_dynamic_add(shading_group, vec2); + DRW_buffer_add_entry(callbuf, vec1); + DRW_buffer_add_entry(callbuf, vec2); vec[1] += tb->h; copy_v3_v3(vec1, vec2); mul_v3_m4v3(vec2, ob->obmat, vec); - DRW_shgroup_call_dynamic_add(shading_group, vec1); - DRW_shgroup_call_dynamic_add(shading_group, vec2); + DRW_buffer_add_entry(callbuf, vec1); + DRW_buffer_add_entry(callbuf, vec2); } } @@ -334,7 +334,7 @@ static void EDIT_TEXT_cache_populate(void *vedata, Object *ob) if ((cu->flag & CU_FAST) || !has_surface) { geom = DRW_cache_text_edge_wire_get(ob); if (geom) { - DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->wire_shgrp, geom, ob->obmat); } } else { diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 378f810551e..e98f11dc6ea 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -88,6 +88,7 @@ extern char datatoc_object_particle_prim_vert_glsl[]; extern char datatoc_object_particle_dot_vert_glsl[]; extern char datatoc_object_particle_dot_frag_glsl[]; extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; extern char datatoc_common_fxaa_lib_glsl[]; extern char datatoc_gpu_shader_flat_color_frag_glsl[]; extern char datatoc_gpu_shader_flat_id_frag_glsl[]; @@ -171,82 +172,82 @@ typedef struct OBJECT_ShadingGroupList { struct DRWPass *bone_axes; /* Empties */ - DRWShadingGroup *plain_axes; - DRWShadingGroup *cube; - DRWShadingGroup *circle; - DRWShadingGroup *sphere; - DRWShadingGroup *sphere_solid; - DRWShadingGroup *cylinder; - DRWShadingGroup *capsule_cap; - DRWShadingGroup *capsule_body; - DRWShadingGroup *cone; - DRWShadingGroup *single_arrow; - DRWShadingGroup *single_arrow_line; - DRWShadingGroup *empty_axes; + DRWCallBuffer *plain_axes; + DRWCallBuffer *cube; + DRWCallBuffer *circle; + DRWCallBuffer *sphere; + DRWCallBuffer *sphere_solid; + DRWCallBuffer *cylinder; + DRWCallBuffer *capsule_cap; + DRWCallBuffer *capsule_body; + DRWCallBuffer *cone; + DRWCallBuffer *single_arrow; + DRWCallBuffer *single_arrow_line; + DRWCallBuffer *empty_axes; /* Force Field */ - DRWShadingGroup *field_wind; - DRWShadingGroup *field_force; - DRWShadingGroup *field_vortex; - DRWShadingGroup *field_curve_sta; - DRWShadingGroup *field_curve_end; - DRWShadingGroup *field_tube_limit; - DRWShadingGroup *field_cone_limit; + DRWCallBuffer *field_wind; + DRWCallBuffer *field_force; + DRWCallBuffer *field_vortex; + DRWCallBuffer *field_curve_sta; + DRWCallBuffer *field_curve_end; + DRWCallBuffer *field_tube_limit; + DRWCallBuffer *field_cone_limit; /* Grease Pencil */ - DRWShadingGroup *gpencil_axes; + DRWCallBuffer *gpencil_axes; /* Speaker */ - DRWShadingGroup *speaker; + DRWCallBuffer *speaker; /* Probe */ - DRWShadingGroup *probe_cube; - DRWShadingGroup *probe_planar; - DRWShadingGroup *probe_grid; + DRWCallBuffer *probe_cube; + DRWCallBuffer *probe_planar; + DRWCallBuffer *probe_grid; /* MetaBalls */ - DRWShadingGroup *mball_handle; + DRWCallBuffer *mball_handle; /* Lights */ - DRWShadingGroup *light_center; - DRWShadingGroup *light_groundpoint; - DRWShadingGroup *light_groundline; - DRWShadingGroup *light_circle; - DRWShadingGroup *light_circle_shadow; - DRWShadingGroup *light_sunrays; - DRWShadingGroup *light_distance; - DRWShadingGroup *light_buflimit; - DRWShadingGroup *light_buflimit_points; - DRWShadingGroup *light_area_sphere; - DRWShadingGroup *light_area_square; - DRWShadingGroup *light_area_disk; - DRWShadingGroup *light_hemi; - DRWShadingGroup *light_spot_cone; - DRWShadingGroup *light_spot_blend; - DRWShadingGroup *light_spot_pyramid; - DRWShadingGroup *light_spot_blend_rect; - DRWShadingGroup *light_spot_volume; - DRWShadingGroup *light_spot_volume_rect; - DRWShadingGroup *light_spot_volume_outside; - DRWShadingGroup *light_spot_volume_rect_outside; + DRWCallBuffer *light_center; + DRWCallBuffer *light_groundpoint; + DRWCallBuffer *light_groundline; + DRWCallBuffer *light_circle; + DRWCallBuffer *light_circle_shadow; + DRWCallBuffer *light_sunrays; + DRWCallBuffer *light_distance; + DRWCallBuffer *light_buflimit; + DRWCallBuffer *light_buflimit_points; + DRWCallBuffer *light_area_sphere; + DRWCallBuffer *light_area_square; + DRWCallBuffer *light_area_disk; + DRWCallBuffer *light_hemi; + DRWCallBuffer *light_spot_cone; + DRWCallBuffer *light_spot_blend; + DRWCallBuffer *light_spot_pyramid; + DRWCallBuffer *light_spot_blend_rect; + DRWCallBuffer *light_spot_volume; + DRWCallBuffer *light_spot_volume_rect; + DRWCallBuffer *light_spot_volume_outside; + DRWCallBuffer *light_spot_volume_rect_outside; /* Helpers */ - DRWShadingGroup *relationship_lines; - DRWShadingGroup *constraint_lines; + DRWCallBuffer *relationship_lines; + DRWCallBuffer *constraint_lines; /* Camera */ - DRWShadingGroup *camera; - DRWShadingGroup *camera_frame; - DRWShadingGroup *camera_tria; - DRWShadingGroup *camera_focus; - DRWShadingGroup *camera_clip; - DRWShadingGroup *camera_clip_points; - DRWShadingGroup *camera_mist; - DRWShadingGroup *camera_mist_points; - DRWShadingGroup *camera_stereo_plane; - DRWShadingGroup *camera_stereo_plane_wires; - DRWShadingGroup *camera_stereo_volume; - DRWShadingGroup *camera_stereo_volume_wires; + DRWCallBuffer *camera; + DRWCallBuffer *camera_frame; + DRWCallBuffer *camera_tria; + DRWCallBuffer *camera_focus; + DRWCallBuffer *camera_clip; + DRWCallBuffer *camera_clip_points; + DRWCallBuffer *camera_mist; + DRWCallBuffer *camera_mist_points; + DRWCallBuffer *camera_stereo_plane; + DRWCallBuffer *camera_stereo_plane_wires; + DRWCallBuffer *camera_stereo_volume; + DRWCallBuffer *camera_stereo_volume_wires; ListBase camera_path; /* Wire */ @@ -268,7 +269,7 @@ typedef struct OBJECT_ShadingGroupList { DRWShadingGroup *points_dupli_select; /* Texture Space */ - DRWShadingGroup *texspace; + DRWCallBuffer *texspace; } OBJECT_ShadingGroupList; typedef struct OBJECT_PrivateData { @@ -284,22 +285,22 @@ typedef struct OBJECT_PrivateData { DRWShadingGroup *outlines_transform; /* Lightprobes */ - DRWShadingGroup *lightprobes_cube_select; - DRWShadingGroup *lightprobes_cube_select_dupli; - DRWShadingGroup *lightprobes_cube_active; - DRWShadingGroup *lightprobes_cube_transform; + DRWCallBuffer *lightprobes_cube_select; + DRWCallBuffer *lightprobes_cube_select_dupli; + DRWCallBuffer *lightprobes_cube_active; + DRWCallBuffer *lightprobes_cube_transform; - DRWShadingGroup *lightprobes_planar_select; - DRWShadingGroup *lightprobes_planar_select_dupli; - DRWShadingGroup *lightprobes_planar_active; - DRWShadingGroup *lightprobes_planar_transform; + DRWCallBuffer *lightprobes_planar_select; + DRWCallBuffer *lightprobes_planar_select_dupli; + DRWCallBuffer *lightprobes_planar_active; + DRWCallBuffer *lightprobes_planar_transform; /* Objects Centers */ - DRWShadingGroup *center_active; - DRWShadingGroup *center_selected; - DRWShadingGroup *center_deselected; - DRWShadingGroup *center_selected_lib; - DRWShadingGroup *center_deselected_lib; + DRWCallBuffer *center_active; + DRWCallBuffer *center_selected; + DRWCallBuffer *center_deselected; + DRWCallBuffer *center_selected_lib; + DRWCallBuffer *center_deselected_lib; /* Outlines id offset (accessed as an array) */ int id_ofs_active; @@ -316,15 +317,20 @@ typedef struct OBJECT_PrivateData { bool xray_enabled_and_not_wire; } OBJECT_PrivateData; /* Transient data */ +typedef struct OBJECT_DupliData { + DRWShadingGroup *outline_shgrp; + GPUBatch *outline_geom; + DRWShadingGroup *extra_shgrp; + GPUBatch *extra_geom; +} OBJECT_DupliData; + static struct { /* Instance Data format */ - struct GPUVertFormat *particle_format; struct GPUVertFormat *empty_image_format; struct GPUVertFormat *empty_image_wire_format; OBJECT_Shaders sh_data[GPU_SHADER_CFG_LEN]; - float camera_pos[3]; float grid_settings[5]; float grid_mesh_size; int grid_flag; @@ -412,8 +418,14 @@ static void OBJECT_engine_init(void *vedata) .defs = (const char *[]){sh_cfg_data->def, NULL}, }); sh_data->outline_prepass_wire = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_outline_prepass_vert_glsl, NULL}, - .geom = (const char *[]){sh_cfg_data->lib, datatoc_object_outline_prepass_geom_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_object_outline_prepass_vert_glsl, + NULL}, + .geom = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_object_outline_prepass_geom_glsl, + NULL}, .frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); @@ -455,37 +467,53 @@ static void OBJECT_engine_init(void *vedata) "#define DEPTH_BACK " STRINGIFY(OB_EMPTY_IMAGE_DEPTH_BACK) "\n"); sh_data->object_empty_image = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_empty_image_vert_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_object_empty_image_vert_glsl, + NULL}, .frag = (const char *[]){datatoc_object_empty_image_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, empty_image_defs, NULL}, }); sh_data->object_empty_image_wire = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_empty_image_vert_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_object_empty_image_vert_glsl, + NULL}, .frag = (const char *[]){datatoc_object_empty_image_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, "#define USE_WIRE\n", empty_image_defs, NULL}, }); } /* Grid */ - sh_data->grid = DRW_shader_create_with_lib(datatoc_object_grid_vert_glsl, - NULL, - datatoc_object_grid_frag_glsl, - datatoc_common_globals_lib_glsl, - NULL); + sh_data->grid = GPU_shader_create_from_arrays({ + .vert = (const char *[]){datatoc_common_globals_lib_glsl, + datatoc_common_view_lib_glsl, + datatoc_object_grid_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_common_globals_lib_glsl, + datatoc_common_view_lib_glsl, + datatoc_object_grid_frag_glsl, + NULL}, + }); /* Particles */ - sh_data->part_prim = DRW_shader_create(datatoc_object_particle_prim_vert_glsl, - NULL, - datatoc_gpu_shader_flat_color_frag_glsl, - NULL); - - sh_data->part_axis = DRW_shader_create(datatoc_object_particle_prim_vert_glsl, - NULL, - datatoc_gpu_shader_flat_color_frag_glsl, - "#define USE_AXIS\n"); - - sh_data->part_dot = DRW_shader_create( - datatoc_object_particle_dot_vert_glsl, NULL, datatoc_object_particle_dot_frag_glsl, NULL); + sh_data->part_prim = DRW_shader_create_with_lib(datatoc_object_particle_prim_vert_glsl, + NULL, + datatoc_gpu_shader_flat_color_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); + + sh_data->part_axis = DRW_shader_create_with_lib(datatoc_object_particle_prim_vert_glsl, + NULL, + datatoc_gpu_shader_flat_color_frag_glsl, + datatoc_common_view_lib_glsl, + "#define USE_AXIS\n"); + + sh_data->part_dot = DRW_shader_create_with_lib(datatoc_object_particle_dot_vert_glsl, + NULL, + datatoc_object_particle_dot_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); /* Lightprobes */ sh_data->lightprobe_grid = DRW_shader_create(datatoc_object_lightprobe_grid_vert_glsl, @@ -523,9 +551,6 @@ static void OBJECT_engine_init(void *vedata) DRW_viewport_matrix_get(invwinmat, DRW_MAT_WININV); DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); - /* Setup camera pos */ - copy_v3_v3(e_data.camera_pos, invviewmat[3]); - /* if perps */ if (winmat[3][3] == 0.0f) { float fov; @@ -597,8 +622,9 @@ static void OBJECT_engine_init(void *vedata) if (((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) && show_axis_z) { e_data.zpos_flag = SHOW_AXIS_Z; - float zvec[4] = {0.0f, 0.0f, -1.0f, 0.0f}; - mul_m4_v4(invviewmat, zvec); + float zvec[3], campos[3]; + negate_v3_v3(zvec, invviewmat[2]); + copy_v3_v3(campos, invviewmat[3]); /* z axis : chose the most facing plane */ if (fabsf(zvec[0]) < fabsf(zvec[1])) { @@ -612,7 +638,7 @@ static void OBJECT_engine_init(void *vedata) /* Persp : If camera is below floor plane, we switch clipping * Ortho : If eye vector is looking up, we switch clipping */ - if (((winmat[3][3] == 0.0f) && (e_data.camera_pos[2] > 0.0f)) || + if (((winmat[3][3] == 0.0f) && (campos[2] > 0.0f)) || ((winmat[3][3] != 0.0f) && (zvec[2] < 0.0f))) { e_data.zpos_flag |= CLIP_ZPOS; e_data.zneg_flag |= CLIP_ZNEG; @@ -661,7 +687,6 @@ static void OBJECT_engine_init(void *vedata) static void OBJECT_engine_free(void) { - MEM_SAFE_FREE(e_data.particle_format); MEM_SAFE_FREE(e_data.empty_image_format); MEM_SAFE_FREE(e_data.empty_image_wire_format); @@ -771,8 +796,8 @@ static int *shgroup_theme_id_to_outline_counter(OBJECT_StorageList *stl, } } -static DRWShadingGroup *shgroup_theme_id_to_probe_planar_outline_shgrp(OBJECT_StorageList *stl, - int theme_id) +static DRWCallBuffer *buffer_theme_id_to_probe_planar_outline_shgrp(OBJECT_StorageList *stl, + int theme_id) { /* does not increment counter */ switch (theme_id) { @@ -786,9 +811,9 @@ static DRWShadingGroup *shgroup_theme_id_to_probe_planar_outline_shgrp(OBJECT_St } } -static DRWShadingGroup *shgroup_theme_id_to_probe_cube_outline_shgrp(OBJECT_StorageList *stl, - int theme_id, - const int base_flag) +static DRWCallBuffer *buffer_theme_id_to_probe_cube_outline_shgrp(OBJECT_StorageList *stl, + int theme_id, + const int base_flag) { /* does not increment counter */ if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) { @@ -961,7 +986,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data, GPUTexture *tex = NULL; if (ob->data != NULL) { - tex = GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false); + tex = GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D); if (tex) { size[0] = GPU_texture_width(tex); size[1] = GPU_texture_height(tex); @@ -985,9 +1010,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data, { DRWShadingGroup *grp = DRW_shgroup_create(sh_data->object_empty_image_wire, sgl->non_meshes); - /* TODO(fclem) implement DRW_shgroup_uniform_vec2_copy */ - DRW_shgroup_uniform_float_copy(grp, "aspectX", image_aspect[0]); - DRW_shgroup_uniform_float_copy(grp, "aspectY", image_aspect[1]); + DRW_shgroup_uniform_vec2_copy(grp, "aspect", image_aspect); DRW_shgroup_uniform_int_copy(grp, "depthMode", depth_mode); DRW_shgroup_uniform_float(grp, "size", &ob->empty_drawsize, 1); DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1); @@ -995,7 +1018,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data, if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - DRW_shgroup_call_add(grp, DRW_cache_image_plane_wire_get(), ob->obmat); + DRW_shgroup_call(grp, DRW_cache_image_plane_wire_get(), ob->obmat); } if (!BKE_object_empty_image_data_is_visible_in_view3d(ob, rv3d)) { @@ -1005,8 +1028,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data, if (tex && ((ob->color[3] > 0.0f) || !use_alpha_blend)) { DRWShadingGroup *grp = DRW_shgroup_create( sh_data->object_empty_image, (use_alpha_blend) ? sgl->image_empties : sgl->non_meshes); - DRW_shgroup_uniform_float_copy(grp, "aspectX", image_aspect[0]); - DRW_shgroup_uniform_float_copy(grp, "aspectY", image_aspect[1]); + DRW_shgroup_uniform_vec2_copy(grp, "aspect", image_aspect); DRW_shgroup_uniform_int_copy(grp, "depthMode", depth_mode); DRW_shgroup_uniform_float(grp, "size", &ob->empty_drawsize, 1); DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1); @@ -1016,7 +1038,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data, if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); } - DRW_shgroup_call_add(grp, DRW_cache_image_plane_get(), ob->obmat); + DRW_shgroup_call(grp, DRW_cache_image_plane_get(), ob->obmat); } } @@ -1081,23 +1103,23 @@ static void OBJECT_cache_init(void *vedata) struct GPUBatch *quad = DRW_cache_quad_get(); /* Cubemap */ - g_data->lightprobes_cube_select = shgroup_instance_outline( + g_data->lightprobes_cube_select = buffer_instance_outline( pass, sphere, &g_data->id_ofs_prb_select); - g_data->lightprobes_cube_select_dupli = shgroup_instance_outline( + g_data->lightprobes_cube_select_dupli = buffer_instance_outline( pass, sphere, &g_data->id_ofs_prb_select_dupli); - g_data->lightprobes_cube_active = shgroup_instance_outline( + g_data->lightprobes_cube_active = buffer_instance_outline( pass, sphere, &g_data->id_ofs_prb_active); - g_data->lightprobes_cube_transform = shgroup_instance_outline( + g_data->lightprobes_cube_transform = buffer_instance_outline( pass, sphere, &g_data->id_ofs_prb_transform); /* Planar */ - g_data->lightprobes_planar_select = shgroup_instance_outline( + g_data->lightprobes_planar_select = buffer_instance_outline( pass, quad, &g_data->id_ofs_prb_select); - g_data->lightprobes_planar_select_dupli = shgroup_instance_outline( + g_data->lightprobes_planar_select_dupli = buffer_instance_outline( pass, quad, &g_data->id_ofs_prb_select_dupli); - g_data->lightprobes_planar_active = shgroup_instance_outline( + g_data->lightprobes_planar_active = buffer_instance_outline( pass, quad, &g_data->id_ofs_prb_active); - g_data->lightprobes_planar_transform = shgroup_instance_outline( + g_data->lightprobes_planar_transform = buffer_instance_outline( pass, quad, &g_data->id_ofs_prb_transform); g_data->id_ofs_prb_select = 0; @@ -1123,7 +1145,7 @@ static void OBJECT_cache_init(void *vedata) DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_float_copy(grp, "alphaOcclu", alphaOcclu); DRW_shgroup_uniform_int(grp, "idOffsets", &stl->g_data->id_ofs_active, 4); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); /* This is the bleed pass if do_outline_expand is false. */ GPUShader *fade_sh = (do_large_expand) ? sh_data->outline_fade_large : sh_data->outline_fade; @@ -1132,7 +1154,7 @@ static void OBJECT_cache_init(void *vedata) grp = DRW_shgroup_create(fade_sh, psl->outlines_expand); DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_blur_tx); DRW_shgroup_uniform_bool_copy(grp, "doExpand", do_outline_expand); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); psl->outlines_bleed = DRW_pass_create("Outlines Bleed Pass", state); @@ -1140,7 +1162,7 @@ static void OBJECT_cache_init(void *vedata) grp = DRW_shgroup_create(sh_data->outline_fade, psl->outlines_bleed); DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_color_tx); DRW_shgroup_uniform_bool_copy(grp, "doExpand", false); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } } @@ -1155,7 +1177,7 @@ static void OBJECT_cache_init(void *vedata) DRWShadingGroup *grp = DRW_shgroup_create(sh_data->outline_resolve_aa, psl->outlines_resolve); DRW_shgroup_uniform_texture_ref(grp, "outlineBluredColor", outline_tx); DRW_shgroup_uniform_vec2(grp, "rcpDimensions", e_data.inv_viewport_size, 1); - DRW_shgroup_call_add(grp, quad, NULL); + DRW_shgroup_call(grp, quad, NULL); } { @@ -1172,28 +1194,27 @@ static void OBJECT_cache_init(void *vedata) DRWShadingGroup *grp = DRW_shgroup_create(sh_data->grid, psl->grid); DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zneg_flag, 1); DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1); - DRW_shgroup_uniform_vec3(grp, "cameraPos", e_data.camera_pos, 1); DRW_shgroup_uniform_vec4(grp, "gridSettings", e_data.grid_settings, 1); DRW_shgroup_uniform_float_copy(grp, "lineKernel", grid_line_size); DRW_shgroup_uniform_float_copy(grp, "meshSize", e_data.grid_mesh_size); DRW_shgroup_uniform_float(grp, "gridOneOverLogSubdiv", &e_data.grid_settings[4], 1); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_call_add(grp, geom, mat); + DRW_shgroup_call(grp, geom, mat); grp = DRW_shgroup_create(sh_data->grid, psl->grid); DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.grid_flag, 1); DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.grid_axes, 1); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_call_add(grp, geom, mat); + DRW_shgroup_call(grp, geom, mat); grp = DRW_shgroup_create(sh_data->grid, psl->grid); DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zpos_flag, 1); DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_call_add(grp, geom, mat); + DRW_shgroup_call(grp, geom, mat); } for (int i = 0; i < 2; ++i) { @@ -1236,113 +1257,111 @@ static void OBJECT_cache_init(void *vedata) /* Empties */ geom = DRW_cache_plain_axes_get(); - sgl->plain_axes = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->plain_axes = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_empty_cube_get(); - sgl->cube = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->cube = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_circle_get(); - sgl->circle = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->circle = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_empty_sphere_get(); - sgl->sphere = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->sphere = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_sphere_get(); - sgl->sphere_solid = shgroup_instance_solid(sgl->non_meshes, geom); + sgl->sphere_solid = buffer_instance_solid(sgl->non_meshes, geom); geom = DRW_cache_empty_cylinder_get(); - sgl->cylinder = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->cylinder = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_empty_capsule_cap_get(); - sgl->capsule_cap = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->capsule_cap = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_empty_capsule_body_get(); - sgl->capsule_body = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->capsule_body = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_empty_cone_get(); - sgl->cone = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->cone = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_single_arrow_get(); - sgl->single_arrow = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->single_arrow = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_single_line_get(); - sgl->single_arrow_line = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->single_arrow_line = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_bone_arrows_get(); - sgl->empty_axes = shgroup_instance_empty_axes(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->empty_axes = buffer_instance_empty_axes(sgl->non_meshes, geom, draw_ctx->sh_cfg); /* Force Field */ geom = DRW_cache_field_wind_get(); - sgl->field_wind = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->field_wind = buffer_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_field_force_get(); - sgl->field_force = shgroup_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->field_force = buffer_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_field_vortex_get(); - sgl->field_vortex = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->field_vortex = buffer_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_screenspace_circle_get(); - sgl->field_curve_sta = shgroup_instance_screen_aligned( - sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->field_curve_sta = buffer_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg); /* Grease Pencil */ geom = DRW_cache_gpencil_axes_get(); - sgl->gpencil_axes = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->gpencil_axes = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); /* Speaker */ geom = DRW_cache_speaker_get(); - sgl->speaker = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->speaker = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); /* Probe */ static float probeSize = 14.0f; geom = DRW_cache_lightprobe_cube_get(); - sgl->probe_cube = shgroup_instance_screenspace( + sgl->probe_cube = buffer_instance_screenspace( sgl->non_meshes, geom, &probeSize, draw_ctx->sh_cfg); geom = DRW_cache_lightprobe_grid_get(); - sgl->probe_grid = shgroup_instance_screenspace( + sgl->probe_grid = buffer_instance_screenspace( sgl->non_meshes, geom, &probeSize, draw_ctx->sh_cfg); static float probePlanarSize = 20.0f; geom = DRW_cache_lightprobe_planar_get(); - sgl->probe_planar = shgroup_instance_screenspace( + sgl->probe_planar = buffer_instance_screenspace( sgl->non_meshes, geom, &probePlanarSize, draw_ctx->sh_cfg); /* Camera */ geom = DRW_cache_camera_get(); - sgl->camera = shgroup_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->camera = buffer_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_camera_frame_get(); - sgl->camera_frame = shgroup_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->camera_frame = buffer_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_camera_tria_get(); - sgl->camera_tria = shgroup_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->camera_tria = buffer_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_plain_axes_get(); - sgl->camera_focus = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->camera_focus = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_single_line_get(); - sgl->camera_clip = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - sgl->camera_mist = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->camera_clip = buffer_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->camera_mist = buffer_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_single_line_endpoints_get(); - sgl->camera_clip_points = shgroup_distance_lines_instance( + sgl->camera_clip_points = buffer_distance_lines_instance( sgl->non_meshes, geom, draw_ctx->sh_cfg); - sgl->camera_mist_points = shgroup_distance_lines_instance( + sgl->camera_mist_points = buffer_distance_lines_instance( sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_quad_wires_get(); - sgl->camera_stereo_plane_wires = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); - DRW_shgroup_state_enable(sgl->camera_stereo_plane_wires, DRW_STATE_WIRE); + sgl->camera_stereo_plane_wires = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_empty_cube_get(); - sgl->camera_stereo_volume_wires = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->camera_stereo_volume_wires = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); BLI_listbase_clear(&sgl->camera_path); /* Texture Space */ geom = DRW_cache_empty_cube_get(); - sgl->texspace = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->texspace = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); /* Wires (for loose edges) */ sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_UNIFORM_COLOR, draw_ctx->sh_cfg); @@ -1374,123 +1393,138 @@ static void OBJECT_cache_init(void *vedata) DRW_shgroup_state_disable(sgl->points_dupli_select, DRW_STATE_BLEND); /* Metaballs Handles */ - sgl->mball_handle = shgroup_instance_mball_handles(sgl->non_meshes, draw_ctx->sh_cfg); + sgl->mball_handle = buffer_instance_mball_handles(sgl->non_meshes, draw_ctx->sh_cfg); /* Lights */ /* TODO * for now we create multiple times the same VBO with only light center coordinates * but ideally we would only create it once */ - /* start with buflimit because we don't want stipples */ - geom = DRW_cache_single_line_get(); - sgl->light_buflimit = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sh = GPU_shader_get_builtin_shader_with_config( + GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, draw_ctx->sh_cfg); + + DRWShadingGroup *grp = DRW_shgroup_create(sh, sgl->non_meshes); + DRW_shgroup_uniform_vec4(grp, "color", gb->colorLightNoAlpha, 1); + DRW_shgroup_uniform_float(grp, "size", &gb->sizeLightCenter, 1); + DRW_shgroup_state_enable(grp, DRW_STATE_POINT); + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + } + + sgl->light_center = buffer_dynpoints_uniform_color(grp); - sgl->light_center = shgroup_dynpoints_uniform_color( - sgl->non_meshes, gb->colorLightNoAlpha, &gb->sizeLightCenter, draw_ctx->sh_cfg); + geom = DRW_cache_single_line_get(); + sgl->light_buflimit = buffer_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_light_get(); - sgl->light_circle = shgroup_instance_screenspace( + sgl->light_circle = buffer_instance_screenspace( sgl->non_meshes, geom, &gb->sizeLightCircle, draw_ctx->sh_cfg); geom = DRW_cache_light_shadows_get(); - sgl->light_circle_shadow = shgroup_instance_screenspace( + sgl->light_circle_shadow = buffer_instance_screenspace( sgl->non_meshes, geom, &gb->sizeLightCircleShadow, draw_ctx->sh_cfg); geom = DRW_cache_light_sunrays_get(); - sgl->light_sunrays = shgroup_instance_screenspace( + sgl->light_sunrays = buffer_instance_screenspace( sgl->non_meshes, geom, &gb->sizeLightCircle, draw_ctx->sh_cfg); - sgl->light_groundline = shgroup_groundlines_uniform_color( + sgl->light_groundline = buffer_groundlines_uniform_color( sgl->non_meshes, gb->colorLight, draw_ctx->sh_cfg); - sgl->light_groundpoint = shgroup_groundpoints_uniform_color( + sgl->light_groundpoint = buffer_groundpoints_uniform_color( sgl->non_meshes, gb->colorLight, draw_ctx->sh_cfg); geom = DRW_cache_screenspace_circle_get(); - sgl->light_area_sphere = shgroup_instance_screen_aligned( + sgl->light_area_sphere = buffer_instance_screen_aligned( sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_light_area_square_get(); - sgl->light_area_square = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->light_area_square = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_light_area_disk_get(); - sgl->light_area_disk = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->light_area_disk = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_light_hemi_get(); - sgl->light_hemi = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->light_hemi = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_single_line_get(); - sgl->light_distance = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->light_distance = buffer_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_single_line_endpoints_get(); - sgl->light_buflimit_points = shgroup_distance_lines_instance( + sgl->light_buflimit_points = buffer_distance_lines_instance( sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_light_spot_get(); - sgl->light_spot_cone = shgroup_spot_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->light_spot_cone = buffer_spot_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_circle_get(); - sgl->light_spot_blend = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->light_spot_blend = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_light_spot_square_get(); - sgl->light_spot_pyramid = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->light_spot_pyramid = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); geom = DRW_cache_square_get(); - sgl->light_spot_blend_rect = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->light_spot_blend_rect = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg); /* -------- STIPPLES ------- */ /* Relationship Lines */ - sgl->relationship_lines = shgroup_dynlines_dashed_uniform_color( + sgl->relationship_lines = buffer_dynlines_dashed_uniform_color( sgl->non_meshes, gb->colorWire, draw_ctx->sh_cfg); - sgl->constraint_lines = shgroup_dynlines_dashed_uniform_color( + sgl->constraint_lines = buffer_dynlines_dashed_uniform_color( sgl->non_meshes, gb->colorGridAxisZ, draw_ctx->sh_cfg); /* Force Field Curve Guide End (here because of stipple) */ /* TODO port to shader stipple */ geom = DRW_cache_screenspace_circle_get(); - sgl->field_curve_end = shgroup_instance_screen_aligned( - sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->field_curve_end = buffer_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg); /* Force Field Limits */ /* TODO port to shader stipple */ geom = DRW_cache_field_tube_limit_get(); - sgl->field_tube_limit = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->field_tube_limit = buffer_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); /* TODO port to shader stipple */ geom = DRW_cache_field_cone_limit_get(); - sgl->field_cone_limit = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); + sgl->field_cone_limit = buffer_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg); /* Transparent Shapes */ state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_CULL_FRONT; sgl->transp_shapes = psl->transp_shapes[i] = DRW_pass_create("Transparent Shapes", state); + sh = GPU_shader_get_builtin_shader_with_config( + GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, draw_ctx->sh_cfg); + + DRWShadingGroup *grp_transp = DRW_shgroup_create(sh, sgl->transp_shapes); + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_world_clip_planes_from_rv3d(grp_transp, DRW_context_state_get()->rv3d); + } + + DRWShadingGroup *grp_cull_back = DRW_shgroup_create_sub(grp_transp); + DRW_shgroup_state_disable(grp_cull_back, DRW_STATE_CULL_FRONT); + DRW_shgroup_state_enable(grp_cull_back, DRW_STATE_CULL_BACK); + + DRWShadingGroup *grp_cull_none = DRW_shgroup_create_sub(grp_transp); + DRW_shgroup_state_disable(grp_cull_none, DRW_STATE_CULL_FRONT); + /* Spot cones */ geom = DRW_cache_light_spot_volume_get(); - sgl->light_spot_volume = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg); + sgl->light_spot_volume = buffer_instance_alpha(grp_transp, geom); geom = DRW_cache_light_spot_square_volume_get(); - sgl->light_spot_volume_rect = shgroup_instance_alpha( - sgl->transp_shapes, geom, draw_ctx->sh_cfg); + sgl->light_spot_volume_rect = buffer_instance_alpha(grp_transp, geom); geom = DRW_cache_light_spot_volume_get(); - sgl->light_spot_volume_outside = shgroup_instance_alpha( - sgl->transp_shapes, geom, draw_ctx->sh_cfg); - DRW_shgroup_state_disable(sgl->light_spot_volume_outside, DRW_STATE_CULL_FRONT); - DRW_shgroup_state_enable(sgl->light_spot_volume_outside, DRW_STATE_CULL_BACK); + sgl->light_spot_volume_outside = buffer_instance_alpha(grp_cull_back, geom); geom = DRW_cache_light_spot_square_volume_get(); - sgl->light_spot_volume_rect_outside = shgroup_instance_alpha( - sgl->transp_shapes, geom, draw_ctx->sh_cfg); - DRW_shgroup_state_disable(sgl->light_spot_volume_rect_outside, DRW_STATE_CULL_FRONT); - DRW_shgroup_state_enable(sgl->light_spot_volume_rect_outside, DRW_STATE_CULL_BACK); + sgl->light_spot_volume_rect_outside = buffer_instance_alpha(grp_cull_back, geom); /* Camera stereo volumes */ geom = DRW_cache_cube_get(); - sgl->camera_stereo_volume = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg); + sgl->camera_stereo_volume = buffer_instance_alpha(grp_transp, geom); geom = DRW_cache_quad_get(); - sgl->camera_stereo_plane = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg); - DRW_shgroup_state_disable(sgl->camera_stereo_plane, DRW_STATE_CULL_FRONT); + sgl->camera_stereo_plane = buffer_instance_alpha(grp_cull_none, geom); } { @@ -1508,7 +1542,7 @@ static void OBJECT_cache_init(void *vedata) GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, draw_ctx->sh_cfg); /* Active */ - grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + grp = DRW_shgroup_create(sh, psl->ob_center); DRW_shgroup_uniform_float(grp, "size", &size, 1); DRW_shgroup_uniform_float(grp, "outlineWidth", &outlineWidth, 1); DRW_shgroup_uniform_vec4(grp, "color", gb->colorActive, 1); @@ -1516,39 +1550,28 @@ static void OBJECT_cache_init(void *vedata) if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); } - stl->g_data->center_active = grp; + /* TODO find better name. */ + stl->g_data->center_active = buffer_dynpoints_uniform_color(grp); /* Select */ - grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + grp = DRW_shgroup_create_sub(grp); DRW_shgroup_uniform_vec4(grp, "color", gb->colorSelect, 1); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); - } - stl->g_data->center_selected = grp; + stl->g_data->center_selected = buffer_dynpoints_uniform_color(grp); /* Deselect */ - grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + grp = DRW_shgroup_create_sub(grp); DRW_shgroup_uniform_vec4(grp, "color", gb->colorDeselect, 1); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); - } - stl->g_data->center_deselected = grp; + stl->g_data->center_deselected = buffer_dynpoints_uniform_color(grp); /* Select (library) */ - grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + grp = DRW_shgroup_create_sub(grp); DRW_shgroup_uniform_vec4(grp, "color", gb->colorLibrarySelect, 1); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); - } - stl->g_data->center_selected_lib = grp; + stl->g_data->center_selected_lib = buffer_dynpoints_uniform_color(grp); /* Deselect (library) */ - grp = DRW_shgroup_point_batch_create(sh, psl->ob_center); + grp = DRW_shgroup_create_sub(grp); DRW_shgroup_uniform_vec4(grp, "color", gb->colorLibrary, 1); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); - } - stl->g_data->center_deselected_lib = grp; + stl->g_data->center_deselected_lib = buffer_dynpoints_uniform_color(grp); } { @@ -1593,7 +1616,7 @@ static void DRW_shgroup_mball_handles(OBJECT_ShadingGroupList *sgl, draw_scale_xform[1][3] = world_pos[1]; draw_scale_xform[2][3] = world_pos[2]; - DRW_shgroup_call_dynamic_add(sgl->mball_handle, draw_scale_xform, &ml->rad, color); + DRW_buffer_add_entry(sgl->mball_handle, draw_scale_xform, &ml->rad, color); } } @@ -1619,25 +1642,25 @@ static void DRW_shgroup_light(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLaye if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) { /* Don't draw the center if it's selected or active */ if (theme_id == TH_LIGHT) { - DRW_shgroup_call_dynamic_add(sgl->light_center, ob->obmat[3]); + DRW_buffer_add_entry(sgl->light_center, ob->obmat[3]); } } /* First circle */ - DRW_shgroup_call_dynamic_add(sgl->light_circle, ob->obmat[3], color); + DRW_buffer_add_entry(sgl->light_circle, ob->obmat[3], color); /* draw dashed outer circle for shadow */ - DRW_shgroup_call_dynamic_add(sgl->light_circle_shadow, ob->obmat[3], color); + DRW_buffer_add_entry(sgl->light_circle_shadow, ob->obmat[3], color); /* Distance */ if (ELEM(la->type, LA_SUN, LA_AREA)) { - DRW_shgroup_call_dynamic_add(sgl->light_distance, color, &zero, &la->dist, ob->obmat); + DRW_buffer_add_entry(sgl->light_distance, color, &zero, &la->dist, ob->obmat); } copy_m4_m4(shapemat, ob->obmat); if (la->type == LA_SUN) { - DRW_shgroup_call_dynamic_add(sgl->light_sunrays, ob->obmat[3], color); + DRW_buffer_add_entry(sgl->light_sunrays, ob->obmat[3], color); } else if (la->type == LA_SPOT) { float size[3], sizemat[4][4]; @@ -1659,42 +1682,39 @@ static void DRW_shgroup_light(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLaye mul_m4_m4m4(spotblendmat, shapemat, sizemat); if (la->mode & LA_SQUARE) { - DRW_shgroup_call_dynamic_add(sgl->light_spot_pyramid, color, &one, shapemat); + DRW_buffer_add_entry(sgl->light_spot_pyramid, color, &one, shapemat); /* hide line if it is zero size or overlaps with outer border, * previously it adjusted to always to show it but that seems * confusing because it doesn't show the actual blend size */ if (blend != 0.0f && blend != 1.0f) { - DRW_shgroup_call_dynamic_add(sgl->light_spot_blend_rect, color, &one, spotblendmat); + DRW_buffer_add_entry(sgl->light_spot_blend_rect, color, &one, spotblendmat); } if (la->mode & LA_SHOW_CONE) { - DRW_shgroup_call_dynamic_add(sgl->light_spot_volume_rect, cone_inside, &one, shapemat); - DRW_shgroup_call_dynamic_add( - sgl->light_spot_volume_rect_outside, cone_outside, &one, shapemat); + DRW_buffer_add_entry(sgl->light_spot_volume_rect, cone_inside, &one, shapemat); + DRW_buffer_add_entry(sgl->light_spot_volume_rect_outside, cone_outside, &one, shapemat); } } else { - DRW_shgroup_call_dynamic_add(sgl->light_spot_cone, color, shapemat); + DRW_buffer_add_entry(sgl->light_spot_cone, color, shapemat); /* hide line if it is zero size or overlaps with outer border, * previously it adjusted to always to show it but that seems * confusing because it doesn't show the actual blend size */ if (blend != 0.0f && blend != 1.0f) { - DRW_shgroup_call_dynamic_add(sgl->light_spot_blend, color, &one, spotblendmat); + DRW_buffer_add_entry(sgl->light_spot_blend, color, &one, spotblendmat); } if (la->mode & LA_SHOW_CONE) { - DRW_shgroup_call_dynamic_add(sgl->light_spot_volume, cone_inside, &one, shapemat); - DRW_shgroup_call_dynamic_add(sgl->light_spot_volume_outside, cone_outside, &one, shapemat); + DRW_buffer_add_entry(sgl->light_spot_volume, cone_inside, &one, shapemat); + DRW_buffer_add_entry(sgl->light_spot_volume_outside, cone_outside, &one, shapemat); } } - DRW_shgroup_call_dynamic_add( - sgl->light_buflimit, color, &la->clipsta, &la->clipend, ob->obmat); - DRW_shgroup_call_dynamic_add( - sgl->light_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat); + DRW_buffer_add_entry(sgl->light_buflimit, color, &la->clipsta, &la->clipend, ob->obmat); + DRW_buffer_add_entry(sgl->light_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat); } else if (la->type == LA_AREA) { float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4]; @@ -1706,10 +1726,10 @@ static void DRW_shgroup_light(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLaye } if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) { - DRW_shgroup_call_dynamic_add(sgl->light_area_disk, color, &la->area_size, shapemat); + DRW_buffer_add_entry(sgl->light_area_disk, color, &la->area_size, shapemat); } else { - DRW_shgroup_call_dynamic_add(sgl->light_area_square, color, &la->area_size, shapemat); + DRW_buffer_add_entry(sgl->light_area_square, color, &la->area_size, shapemat); } } @@ -1719,12 +1739,12 @@ static void DRW_shgroup_light(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLaye shapemat[0][1] = shapemat[0][2] = 0.0f; shapemat[1][0] = shapemat[1][2] = 0.0f; shapemat[2][0] = shapemat[2][1] = 0.0f; - DRW_shgroup_call_dynamic_add(sgl->light_area_sphere, color, &la->area_size, shapemat); + DRW_buffer_add_entry(sgl->light_area_sphere, color, &la->area_size, shapemat); } /* Line and point going to the ground */ - DRW_shgroup_call_dynamic_add(sgl->light_groundline, ob->obmat[3]); - DRW_shgroup_call_dynamic_add(sgl->light_groundpoint, ob->obmat[3]); + DRW_buffer_add_entry(sgl->light_groundline, ob->obmat[3]); + DRW_buffer_add_entry(sgl->light_groundpoint, ob->obmat[3]); } static GPUBatch *batch_camera_path_get(ListBase *camera_paths, @@ -1820,19 +1840,19 @@ static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl copy_v2_v2(drw_tria_dummy[eye][1], cam->runtime.drw_corners[eye][0]); if (is_stereo3d_cameras) { - DRW_shgroup_call_dynamic_add(sgl->camera_frame, - color, - cam->runtime.drw_corners[eye], - &cam->runtime.drw_depth[eye], - cam->runtime.drw_tria, - obmat); + DRW_buffer_add_entry(sgl->camera_frame, + color, + cam->runtime.drw_corners[eye], + &cam->runtime.drw_depth[eye], + cam->runtime.drw_tria, + obmat); - DRW_shgroup_call_dynamic_add(sgl->camera, - color, - cam->runtime.drw_corners[eye], - &cam->runtime.drw_depth[eye], - drw_tria_dummy[eye], - obmat); + DRW_buffer_add_entry(sgl->camera, + color, + cam->runtime.drw_corners[eye], + &cam->runtime.drw_depth[eye], + drw_tria_dummy[eye], + obmat); } /* Connecting line. */ @@ -1841,8 +1861,8 @@ static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl /* Draw connecting lines. */ if (is_stereo3d_cameras) { - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, origin[0]); - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, origin[1]); + DRW_buffer_add_entry(sgl->relationship_lines, origin[0]); + DRW_buffer_add_entry(sgl->relationship_lines, origin[1]); } /* Draw convergence plane. */ @@ -1879,9 +1899,9 @@ static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl translate_m4(plane_mat, 2.0f * cam->shiftx, (width / height) * 2.0f * cam->shifty, 0.0f); if (v3d->stereo3d_convergence_alpha > 0.0f) { - DRW_shgroup_call_dynamic_add(sgl->camera_stereo_plane, color_plane[0], &one, plane_mat); + DRW_buffer_add_entry(sgl->camera_stereo_plane, color_plane[0], &one, plane_mat); } - DRW_shgroup_call_dynamic_add(sgl->camera_stereo_plane_wires, color_plane[1], &one, plane_mat); + DRW_buffer_add_entry(sgl->camera_stereo_plane_wires, color_plane[1], &one, plane_mat); } /* Draw convergence volume. */ @@ -1905,10 +1925,9 @@ static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl invert_m4_m4(persinv, persmat); if (v3d->stereo3d_volume_alpha > 0.0f) { - DRW_shgroup_call_dynamic_add(sgl->camera_stereo_volume, color_volume[eye], &one, persinv); + DRW_buffer_add_entry(sgl->camera_stereo_volume, color_volume[eye], &one, persinv); } - DRW_shgroup_call_dynamic_add( - sgl->camera_stereo_volume_wires, color_volume[2], &one, persinv); + DRW_buffer_add_entry(sgl->camera_stereo_volume_wires, color_volume[2], &one, persinv); } } } @@ -1916,13 +1935,14 @@ static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl static void camera_view3d_reconstruction(OBJECT_ShadingGroupList *sgl, Scene *scene, View3D *v3d, - const Object *camera_object, + Object *camera_object, Object *ob, const float color[4], const bool is_select) { const DRWContextState *draw_ctx = DRW_context_state_get(); Camera *cam = ob->data; + const Object *orig_camera_object = DEG_get_original_object(camera_object); if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0) { return; @@ -2003,7 +2023,7 @@ static void camera_view3d_reconstruction(OBJECT_ShadingGroupList *sgl, } if (is_select) { - DRW_select_load_id(camera_object->select_id | (track_index << 16)); + DRW_select_load_id(orig_camera_object->runtime.select_id | (track_index << 16)); track_index++; } @@ -2021,7 +2041,7 @@ static void camera_view3d_reconstruction(OBJECT_ShadingGroupList *sgl, }; mul_m4_m4m4(bundle_mat, bundle_mat, bundle_scale_mat); - DRW_shgroup_call_dynamic_add(sgl->sphere_solid, bundle_mat, bundle_color_v4); + DRW_buffer_add_entry(sgl->sphere_solid, bundle_mat, bundle_color_v4); } else { DRW_shgroup_empty_ex( @@ -2055,7 +2075,7 @@ static void camera_view3d_reconstruction(OBJECT_ShadingGroupList *sgl, GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); DRWShadingGroup *shading_group = DRW_shgroup_create(shader, sgl->non_meshes); DRW_shgroup_uniform_vec4(shading_group, "color", camera_path_color, 1); - DRW_shgroup_call_add(shading_group, geom, camera_mat); + DRW_shgroup_call(shading_group, geom, camera_mat); } } } @@ -2069,7 +2089,7 @@ static void DRW_shgroup_camera(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLay RegionView3D *rv3d = draw_ctx->rv3d; Camera *cam = ob->data; - const Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera); + Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera); const bool is_select = DRW_state_is_select(); const bool is_active = (ob == camera_object); const bool look_through = (is_active && (rv3d->persp == RV3D_CAMOB)); @@ -2136,31 +2156,31 @@ static void DRW_shgroup_camera(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLay copy_m4_m4(mat, ob->obmat); } - DRW_shgroup_call_dynamic_add(sgl->camera_frame, - color, - cam->runtime.drw_corners[0], - &cam->runtime.drw_depth[0], - cam->runtime.drw_tria, - mat); + DRW_buffer_add_entry(sgl->camera_frame, + color, + cam->runtime.drw_corners[0], + &cam->runtime.drw_depth[0], + cam->runtime.drw_tria, + mat); } else { if (!is_stereo3d_cameras) { - DRW_shgroup_call_dynamic_add(sgl->camera, - color, - cam->runtime.drw_corners[0], - &cam->runtime.drw_depth[0], - cam->runtime.drw_tria, - ob->obmat); + DRW_buffer_add_entry(sgl->camera, + color, + cam->runtime.drw_corners[0], + &cam->runtime.drw_depth[0], + cam->runtime.drw_tria, + ob->obmat); } /* Active cam */ if (is_active) { - DRW_shgroup_call_dynamic_add(sgl->camera_tria, - color, - cam->runtime.drw_corners[0], - &cam->runtime.drw_depth[0], - cam->runtime.drw_tria, - ob->obmat); + DRW_buffer_add_entry(sgl->camera_tria, + color, + cam->runtime.drw_corners[0], + &cam->runtime.drw_depth[0], + cam->runtime.drw_tria, + ob->obmat); } } @@ -2177,16 +2197,16 @@ static void DRW_shgroup_camera(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLay size_to_mat4(sizemat, size); mul_m4_m4m4(cam->runtime.drw_focusmat, cam->runtime.drw_focusmat, sizemat); - DRW_shgroup_call_dynamic_add( + DRW_buffer_add_entry( sgl->camera_focus, (is_active ? col_hi : col), &cam->drawsize, cam->runtime.drw_focusmat); - DRW_shgroup_call_dynamic_add( + DRW_buffer_add_entry( sgl->camera_clip, color, &cam->clip_start, &cam->clip_end, cam->runtime.drw_normalmat); - DRW_shgroup_call_dynamic_add(sgl->camera_clip_points, - (is_active ? col_hi : col), - &cam->clip_start, - &cam->clip_end, - cam->runtime.drw_normalmat); + DRW_buffer_add_entry(sgl->camera_clip_points, + (is_active ? col_hi : col), + &cam->clip_start, + &cam->clip_end, + cam->runtime.drw_normalmat); } if (cam->flag & CAM_SHOWMIST) { @@ -2195,13 +2215,13 @@ static void DRW_shgroup_camera(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLay if (world) { static float col[4] = {0.5f, 0.5f, 0.5f, 1.0f}, col_hi[4] = {1.0f, 1.0f, 1.0f, 1.0f}; world->mistend = world->miststa + world->mistdist; - DRW_shgroup_call_dynamic_add( + DRW_buffer_add_entry( sgl->camera_mist, color, &world->miststa, &world->mistend, cam->runtime.drw_normalmat); - DRW_shgroup_call_dynamic_add(sgl->camera_mist_points, - (is_active ? col_hi : col), - &world->miststa, - &world->mistend, - cam->runtime.drw_normalmat); + DRW_buffer_add_entry(sgl->camera_mist_points, + (is_active ? col_hi : col), + &world->miststa, + &world->mistend, + cam->runtime.drw_normalmat); } } @@ -2223,26 +2243,26 @@ static void DRW_shgroup_empty_ex(OBJECT_ShadingGroupList *sgl, { switch (draw_type) { case OB_PLAINAXES: - DRW_shgroup_call_dynamic_add(sgl->plain_axes, color, draw_size, mat); + DRW_buffer_add_entry(sgl->plain_axes, color, draw_size, mat); break; case OB_SINGLE_ARROW: - DRW_shgroup_call_dynamic_add(sgl->single_arrow, color, draw_size, mat); - DRW_shgroup_call_dynamic_add(sgl->single_arrow_line, color, draw_size, mat); + DRW_buffer_add_entry(sgl->single_arrow, color, draw_size, mat); + DRW_buffer_add_entry(sgl->single_arrow_line, color, draw_size, mat); break; case OB_CUBE: - DRW_shgroup_call_dynamic_add(sgl->cube, color, draw_size, mat); + DRW_buffer_add_entry(sgl->cube, color, draw_size, mat); break; case OB_CIRCLE: - DRW_shgroup_call_dynamic_add(sgl->circle, color, draw_size, mat); + DRW_buffer_add_entry(sgl->circle, color, draw_size, mat); break; case OB_EMPTY_SPHERE: - DRW_shgroup_call_dynamic_add(sgl->sphere, color, draw_size, mat); + DRW_buffer_add_entry(sgl->sphere, color, draw_size, mat); break; case OB_EMPTY_CONE: - DRW_shgroup_call_dynamic_add(sgl->cone, color, draw_size, mat); + DRW_buffer_add_entry(sgl->cone, color, draw_size, mat); break; case OB_ARROWS: - DRW_shgroup_call_dynamic_add(sgl->empty_axes, color, draw_size, mat); + DRW_buffer_add_entry(sgl->empty_axes, color, draw_size, mat); break; case OB_EMPTY_IMAGE: BLI_assert(!"Should never happen, use DRW_shgroup_empty instead."); @@ -2334,19 +2354,19 @@ static void DRW_shgroup_forcefield(OBJECT_ShadingGroupList *sgl, Object *ob, Vie switch (pd->forcefield) { case PFIELD_WIND: - DRW_shgroup_call_dynamic_add(sgl->field_wind, color, &pd->drawvec1, ob->obmat); + DRW_buffer_add_entry(sgl->field_wind, color, &pd->drawvec1, ob->obmat); break; case PFIELD_FORCE: - DRW_shgroup_call_dynamic_add(sgl->field_force, color, &pd->drawvec1, ob->obmat); + DRW_buffer_add_entry(sgl->field_force, color, &pd->drawvec1, ob->obmat); break; case PFIELD_VORTEX: - DRW_shgroup_call_dynamic_add(sgl->field_vortex, color, &pd->drawvec1, ob->obmat); + DRW_buffer_add_entry(sgl->field_vortex, color, &pd->drawvec1, ob->obmat); break; case PFIELD_GUIDE: if (cu && (cu->flag & CU_PATH) && ob->runtime.curve_cache->path && ob->runtime.curve_cache->path->data) { - DRW_shgroup_call_dynamic_add(sgl->field_curve_sta, color, &pd->f_strength, ob->obmat); - DRW_shgroup_call_dynamic_add(sgl->field_curve_end, color, &pd->f_strength, ob->obmat); + DRW_buffer_add_entry(sgl->field_curve_sta, color, &pd->f_strength, ob->obmat); + DRW_buffer_add_entry(sgl->field_curve_end, color, &pd->f_strength, ob->obmat); } break; } @@ -2354,33 +2374,29 @@ static void DRW_shgroup_forcefield(OBJECT_ShadingGroupList *sgl, Object *ob, Vie if (pd->falloff == PFIELD_FALL_SPHERE) { /* as last, guide curve alters it */ if ((pd->flag & PFIELD_USEMAX) != 0) { - DRW_shgroup_call_dynamic_add(sgl->field_curve_end, color, &pd->maxdist, ob->obmat); + DRW_buffer_add_entry(sgl->field_curve_end, color, &pd->maxdist, ob->obmat); } if ((pd->flag & PFIELD_USEMIN) != 0) { - DRW_shgroup_call_dynamic_add(sgl->field_curve_end, color, &pd->mindist, ob->obmat); + DRW_buffer_add_entry(sgl->field_curve_end, color, &pd->mindist, ob->obmat); } } else if (pd->falloff == PFIELD_FALL_TUBE) { if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { - DRW_shgroup_call_dynamic_add( - sgl->field_tube_limit, color, &pd->drawvec_falloff_max, ob->obmat); + DRW_buffer_add_entry(sgl->field_tube_limit, color, &pd->drawvec_falloff_max, ob->obmat); } if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { - DRW_shgroup_call_dynamic_add( - sgl->field_tube_limit, color, &pd->drawvec_falloff_min, ob->obmat); + DRW_buffer_add_entry(sgl->field_tube_limit, color, &pd->drawvec_falloff_min, ob->obmat); } } else if (pd->falloff == PFIELD_FALL_CONE) { if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { - DRW_shgroup_call_dynamic_add( - sgl->field_cone_limit, color, &pd->drawvec_falloff_max, ob->obmat); + DRW_buffer_add_entry(sgl->field_cone_limit, color, &pd->drawvec_falloff_max, ob->obmat); } if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { - DRW_shgroup_call_dynamic_add( - sgl->field_cone_limit, color, &pd->drawvec_falloff_min, ob->obmat); + DRW_buffer_add_entry(sgl->field_cone_limit, color, &pd->drawvec_falloff_min, ob->obmat); } } } @@ -2412,7 +2428,7 @@ static void DRW_shgroup_volume_extra(OBJECT_ShadingGroupList *sgl, translate_m4(voxel_cubemat, 1.0f, 1.0f, 1.0f); mul_m4_m4m4(voxel_cubemat, ob->obmat, voxel_cubemat); - DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, voxel_cubemat); + DRW_buffer_add_entry(sgl->cube, color, &one, voxel_cubemat); /* Don't show smoke before simulation starts, this could be made an option in the future. */ if (!sds->draw_velocity || !sds->fluid || CFRA < sds->point_cache[0]->startframe) { @@ -2446,7 +2462,7 @@ static void DRW_shgroup_volume_extra(OBJECT_ShadingGroupList *sgl, DRW_shgroup_uniform_float_copy(grp, "displaySize", sds->vector_scale); DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth); DRW_shgroup_uniform_int_copy(grp, "sliceAxis", slice_axis); - DRW_shgroup_call_procedural_lines_add(grp, line_count, ob->obmat); + DRW_shgroup_call_procedural_lines(grp, line_count, ob->obmat); BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(smd)); } @@ -2472,7 +2488,7 @@ static void DRW_shgroup_speaker(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLa static float one = 1.0f; DRW_object_wire_theme_get(ob, view_layer, &color); - DRW_shgroup_call_dynamic_add(sgl->speaker, color, &one, ob->obmat); + DRW_buffer_add_entry(sgl->speaker, color, &one, ob->obmat); } typedef struct OBJECT_LightProbeEngineData { @@ -2547,7 +2563,7 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, DRW_shgroup_uniform_vec3(grp, "increment_y", prb_data->increment_y, 1); DRW_shgroup_uniform_vec3(grp, "increment_z", prb_data->increment_z, 1); DRW_shgroup_uniform_ivec3(grp, "grid_resolution", &prb->grid_resolution_x, 1); - DRW_shgroup_call_procedural_points_add(grp, cell_count, NULL); + DRW_shgroup_call_procedural_points(grp, cell_count, NULL); } else if (prb->type == LIGHTPROBE_TYPE_CUBE) { float draw_size = 1.0f; @@ -2556,17 +2572,17 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, // unit_m4(prb_data->probe_cube_mat); // copy_v3_v3(prb_data->probe_cube_mat[3], ob->obmat[3]); - DRWShadingGroup *grp = shgroup_theme_id_to_probe_cube_outline_shgrp( + DRWCallBuffer *buf = buffer_theme_id_to_probe_cube_outline_shgrp( stl, theme_id, ob->base_flag); /* TODO remove or change the drawing of the cube probes. Theses line draws nothing on purpose * to keep the call ids correct. */ zero_m4(probe_cube_mat); - DRW_shgroup_call_dynamic_add(grp, call_id, &draw_size, probe_cube_mat); + DRW_buffer_add_entry(buf, call_id, &draw_size, probe_cube_mat); } else { float draw_size = 1.0f; - DRWShadingGroup *grp = shgroup_theme_id_to_probe_planar_outline_shgrp(stl, theme_id); - DRW_shgroup_call_dynamic_add(grp, call_id, &draw_size, ob->obmat); + DRWCallBuffer *buf = buffer_theme_id_to_probe_planar_outline_shgrp(stl, theme_id); + DRW_buffer_add_entry(buf, call_id, &draw_size, ob->obmat); } *call_id += 1; @@ -2574,14 +2590,14 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, switch (prb->type) { case LIGHTPROBE_TYPE_PLANAR: - DRW_shgroup_call_dynamic_add(sgl->probe_planar, ob->obmat[3], color); + DRW_buffer_add_entry(sgl->probe_planar, ob->obmat[3], color); break; case LIGHTPROBE_TYPE_GRID: - DRW_shgroup_call_dynamic_add(sgl->probe_grid, ob->obmat[3], color); + DRW_buffer_add_entry(sgl->probe_grid, ob->obmat[3], color); break; case LIGHTPROBE_TYPE_CUBE: default: - DRW_shgroup_call_dynamic_add(sgl->probe_cube, ob->obmat[3], color); + DRW_buffer_add_entry(sgl->probe_cube, ob->obmat[3], color); break; } @@ -2590,13 +2606,13 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, copy_m4_m4(mat, ob->obmat); normalize_m4(mat); - DRW_shgroup_call_dynamic_add(sgl->single_arrow, color, &ob->empty_drawsize, mat); - DRW_shgroup_call_dynamic_add(sgl->single_arrow_line, color, &ob->empty_drawsize, mat); + DRW_buffer_add_entry(sgl->single_arrow, color, &ob->empty_drawsize, mat); + DRW_buffer_add_entry(sgl->single_arrow_line, color, &ob->empty_drawsize, mat); copy_m4_m4(mat, ob->obmat); zero_v3(mat[2]); - DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, mat); + DRW_buffer_add_entry(sgl->cube, color, &one, mat); } if ((prb->flag & LIGHTPROBE_FLAG_SHOW_INFLUENCE) != 0) { @@ -2610,8 +2626,8 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, } if (prb->type == LIGHTPROBE_TYPE_GRID || prb->attenuation_type == LIGHTPROBE_SHAPE_BOX) { - DRW_shgroup_call_dynamic_add(sgl->cube, color, &prb->distgridinf, ob->obmat); - DRW_shgroup_call_dynamic_add(sgl->cube, color, &prb->distfalloff, ob->obmat); + DRW_buffer_add_entry(sgl->cube, color, &prb->distgridinf, ob->obmat); + DRW_buffer_add_entry(sgl->cube, color, &prb->distfalloff, ob->obmat); } else if (prb->type == LIGHTPROBE_TYPE_PLANAR) { float rangemat[4][4]; @@ -2619,17 +2635,17 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, normalize_v3(rangemat[2]); mul_v3_fl(rangemat[2], prb->distinf); - DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, rangemat); + DRW_buffer_add_entry(sgl->cube, color, &one, rangemat); copy_m4_m4(rangemat, ob->obmat); normalize_v3(rangemat[2]); mul_v3_fl(rangemat[2], prb->distfalloff); - DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, rangemat); + DRW_buffer_add_entry(sgl->cube, color, &one, rangemat); } else { - DRW_shgroup_call_dynamic_add(sgl->sphere, color, &prb->distgridinf, ob->obmat); - DRW_shgroup_call_dynamic_add(sgl->sphere, color, &prb->distfalloff, ob->obmat); + DRW_buffer_add_entry(sgl->sphere, color, &prb->distgridinf, ob->obmat); + DRW_buffer_add_entry(sgl->sphere, color, &prb->distfalloff, ob->obmat); } } @@ -2648,10 +2664,10 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, } if (prb->parallax_type == LIGHTPROBE_SHAPE_BOX) { - DRW_shgroup_call_dynamic_add(sgl->cube, color, dist, obmat); + DRW_buffer_add_entry(sgl->cube, color, dist, obmat); } else { - DRW_shgroup_call_dynamic_add(sgl->sphere, color, dist, obmat); + DRW_buffer_add_entry(sgl->sphere, color, dist, obmat); } } } @@ -2690,9 +2706,8 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, normalize_m4_m4(clipmat, ob->obmat); mul_m4_m4m4(clipmat, clipmat, cubefacemat[i]); - DRW_shgroup_call_dynamic_add( - sgl->light_buflimit, color, &prb->clipsta, &prb->clipend, clipmat); - DRW_shgroup_call_dynamic_add( + DRW_buffer_add_entry(sgl->light_buflimit, color, &prb->clipsta, &prb->clipend, clipmat); + DRW_buffer_add_entry( sgl->light_buflimit_points, color, &prb->clipsta, &prb->clipend, clipmat); } } @@ -2700,8 +2715,8 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data, /* Line and point going to the ground */ if (prb->type == LIGHTPROBE_TYPE_CUBE) { - DRW_shgroup_call_dynamic_add(sgl->light_groundline, ob->obmat[3]); - DRW_shgroup_call_dynamic_add(sgl->light_groundpoint, ob->obmat[3]); + DRW_buffer_add_entry(sgl->light_groundline, ob->obmat[3]); + DRW_buffer_add_entry(sgl->light_groundpoint, ob->obmat[3]); } } @@ -2711,20 +2726,20 @@ static void DRW_shgroup_relationship_lines(OBJECT_ShadingGroupList *sgl, Object *ob) { if (ob->parent && (DRW_object_visibility_in_active_context(ob->parent) & OB_VISIBLE_SELF)) { - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->runtime.parent_display_origin); - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]); + DRW_buffer_add_entry(sgl->relationship_lines, ob->runtime.parent_display_origin); + DRW_buffer_add_entry(sgl->relationship_lines, ob->obmat[3]); } if (ob->rigidbody_constraint) { Object *rbc_ob1 = ob->rigidbody_constraint->ob1; Object *rbc_ob2 = ob->rigidbody_constraint->ob2; if (rbc_ob1 && (DRW_object_visibility_in_active_context(rbc_ob1) & OB_VISIBLE_SELF)) { - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, rbc_ob1->obmat[3]); - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]); + DRW_buffer_add_entry(sgl->relationship_lines, rbc_ob1->obmat[3]); + DRW_buffer_add_entry(sgl->relationship_lines, ob->obmat[3]); } if (rbc_ob2 && (DRW_object_visibility_in_active_context(rbc_ob2) & OB_VISIBLE_SELF)) { - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, rbc_ob2->obmat[3]); - DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]); + DRW_buffer_add_entry(sgl->relationship_lines, rbc_ob2->obmat[3]); + DRW_buffer_add_entry(sgl->relationship_lines, ob->obmat[3]); } } @@ -2756,8 +2771,8 @@ static void DRW_shgroup_relationship_lines(OBJECT_ShadingGroupList *sgl, } if (camob) { - DRW_shgroup_call_dynamic_add(sgl->constraint_lines, camob->obmat[3]); - DRW_shgroup_call_dynamic_add(sgl->constraint_lines, ob->obmat[3]); + DRW_buffer_add_entry(sgl->constraint_lines, camob->obmat[3]); + DRW_buffer_add_entry(sgl->constraint_lines, ob->obmat[3]); } } else { @@ -2778,8 +2793,8 @@ static void DRW_shgroup_relationship_lines(OBJECT_ShadingGroupList *sgl, unit_m4(ct->matrix); } - DRW_shgroup_call_dynamic_add(sgl->constraint_lines, ct->matrix[3]); - DRW_shgroup_call_dynamic_add(sgl->constraint_lines, ob->obmat[3]); + DRW_buffer_add_entry(sgl->constraint_lines, ct->matrix[3]); + DRW_buffer_add_entry(sgl->constraint_lines, ob->obmat[3]); } if (cti->flush_constraint_targets) { @@ -2802,32 +2817,32 @@ static void DRW_shgroup_object_center(OBJECT_StorageList *stl, return; } const bool is_library = ob->id.us > 1 || ID_IS_LINKED(ob); - DRWShadingGroup *shgroup; + DRWCallBuffer *buf; if (ob == OBACT(view_layer)) { - shgroup = stl->g_data->center_active; + buf = stl->g_data->center_active; } else if (ob->base_flag & BASE_SELECTED) { if (is_library) { - shgroup = stl->g_data->center_selected_lib; + buf = stl->g_data->center_selected_lib; } else { - shgroup = stl->g_data->center_selected; + buf = stl->g_data->center_selected; } } else if (v3d->flag & V3D_DRAW_CENTERS) { if (is_library) { - shgroup = stl->g_data->center_deselected_lib; + buf = stl->g_data->center_deselected_lib; } else { - shgroup = stl->g_data->center_deselected; + buf = stl->g_data->center_deselected; } } else { return; } - DRW_shgroup_call_dynamic_add(shgroup, ob->obmat[3]); + DRW_buffer_add_entry(buf, ob->obmat[3]); } static void DRW_shgroup_texture_space(OBJECT_ShadingGroupList *sgl, Object *ob, int theme_id) @@ -2877,7 +2892,7 @@ static void DRW_shgroup_texture_space(OBJECT_ShadingGroupList *sgl, Object *ob, float color[4]; UI_GetThemeColor4fv(theme_id, color); - DRW_shgroup_call_dynamic_add(sgl->texspace, color, &one, tmp); + DRW_buffer_add_entry(sgl->texspace, color, &one, tmp); } static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int theme_id) @@ -2914,7 +2929,7 @@ static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int the size_to_mat4(tmp, size); copy_v3_v3(tmp[3], center); mul_m4_m4m4(tmp, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, tmp); + DRW_buffer_add_entry(sgl->cube, color, &one, tmp); break; case OB_BOUND_SPHERE: size[0] = max_fff(size[0], size[1], size[2]); @@ -2922,7 +2937,7 @@ static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int the size_to_mat4(tmp, size); copy_v3_v3(tmp[3], center); mul_m4_m4m4(tmp, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->sphere, color, &one, tmp); + DRW_buffer_add_entry(sgl->sphere, color, &one, tmp); break; case OB_BOUND_CYLINDER: size[0] = max_ff(size[0], size[1]); @@ -2930,7 +2945,7 @@ static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int the size_to_mat4(tmp, size); copy_v3_v3(tmp[3], center); mul_m4_m4m4(tmp, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->cylinder, color, &one, tmp); + DRW_buffer_add_entry(sgl->cylinder, color, &one, tmp); break; case OB_BOUND_CONE: size[0] = max_ff(size[0], size[1]); @@ -2941,7 +2956,7 @@ static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int the swap_v3_v3(tmp[1], tmp[2]); tmp[3][2] -= size[2]; mul_m4_m4m4(tmp, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->cone, color, &one, tmp); + DRW_buffer_add_entry(sgl->cone, color, &one, tmp); break; case OB_BOUND_CAPSULE: size[0] = max_ff(size[0], size[1]); @@ -2950,14 +2965,14 @@ static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int the copy_v2_v2(tmp[3], center); tmp[3][2] = center[2] + max_ff(0.0f, size[2] - size[0]); mul_m4_m4m4(final_mat, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->capsule_cap, color, &one, final_mat); + DRW_buffer_add_entry(sgl->capsule_cap, color, &one, final_mat); negate_v3(tmp[2]); tmp[3][2] = center[2] - max_ff(0.0f, size[2] - size[0]); mul_m4_m4m4(final_mat, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->capsule_cap, color, &one, final_mat); + DRW_buffer_add_entry(sgl->capsule_cap, color, &one, final_mat); tmp[2][2] = max_ff(0.0f, size[2] * 2.0f - size[0] * 2.0f); mul_m4_m4m4(final_mat, ob->obmat, tmp); - DRW_shgroup_call_dynamic_add(sgl->capsule_body, color, &one, final_mat); + DRW_buffer_add_entry(sgl->capsule_body, color, &one, final_mat); break; } } @@ -2980,13 +2995,10 @@ static void OBJECT_cache_populate_particles(OBJECT_Shaders *sh_data, if (draw_as != PART_DRAW_PATH) { struct GPUBatch *geom = DRW_cache_particles_get_dots(ob, psys); DRWShadingGroup *shgrp = NULL; - static int screen_space[2] = {0, 1}; + struct GPUBatch *shape = NULL; static float def_prim_col[3] = {0.5f, 0.5f, 0.5f}; static float def_sec_col[3] = {1.0f, 1.0f, 1.0f}; - /* Dummy particle format for instancing to work. */ - DRW_shgroup_instance_format(e_data.particle_format, {{"dummy", DRW_ATTR_FLOAT, 1}}); - Material *ma = give_current_material(ob, part->omat); switch (draw_as) { @@ -2997,43 +3009,36 @@ static void OBJECT_cache_populate_particles(OBJECT_Shaders *sh_data, DRW_shgroup_uniform_float(shgrp, "pixel_size", DRW_viewport_pixelsize_get(), 1); DRW_shgroup_uniform_float(shgrp, "size", &part->draw_size, 1); DRW_shgroup_uniform_texture(shgrp, "ramp", G_draw.ramp); - DRW_shgroup_call_add(shgrp, geom, mat); + DRW_shgroup_call(shgrp, geom, mat); break; case PART_DRAW_CROSS: - shgrp = DRW_shgroup_instance_create(sh_data->part_prim, - psl->particle, - DRW_cache_particles_get_prim(PART_DRAW_CROSS), - e_data.particle_format); + shgrp = DRW_shgroup_create(sh_data->part_prim, psl->particle); DRW_shgroup_uniform_texture(shgrp, "ramp", G_draw.ramp); DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); - DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1); + DRW_shgroup_uniform_float(shgrp, "draw_size", &part->draw_size, 1); + DRW_shgroup_uniform_bool_copy(shgrp, "screen_space", false); + shape = DRW_cache_particles_get_prim(PART_DRAW_CROSS); + DRW_shgroup_call_instances_with_attribs(shgrp, shape, NULL, geom); break; case PART_DRAW_CIRC: - shgrp = DRW_shgroup_instance_create(sh_data->part_prim, - psl->particle, - DRW_cache_particles_get_prim(PART_DRAW_CIRC), - e_data.particle_format); + shape = DRW_cache_particles_get_prim(PART_DRAW_CIRC); + shgrp = DRW_shgroup_create(sh_data->part_prim, psl->particle); DRW_shgroup_uniform_texture(shgrp, "ramp", G_draw.ramp); DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1); - DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[1], 1); + DRW_shgroup_uniform_float(shgrp, "draw_size", &part->draw_size, 1); + DRW_shgroup_uniform_bool_copy(shgrp, "screen_space", true); + DRW_shgroup_call_instances_with_attribs(shgrp, shape, NULL, geom); break; case PART_DRAW_AXIS: - shgrp = DRW_shgroup_instance_create(sh_data->part_axis, - psl->particle, - DRW_cache_particles_get_prim(PART_DRAW_AXIS), - e_data.particle_format); - DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1); + shape = DRW_cache_particles_get_prim(PART_DRAW_AXIS); + shgrp = DRW_shgroup_create(sh_data->part_axis, psl->particle); + DRW_shgroup_uniform_float(shgrp, "draw_size", &part->draw_size, 1); + DRW_shgroup_uniform_bool_copy(shgrp, "screen_space", false); + DRW_shgroup_call_instances_with_attribs(shgrp, shape, NULL, geom); break; default: break; } - - if (shgrp) { - if (draw_as != PART_DRAW_DOT) { - DRW_shgroup_uniform_float(shgrp, "draw_size", &part->draw_size, 1); - DRW_shgroup_instance_batch(shgrp, geom); - } - } } } } @@ -3096,6 +3101,24 @@ static void OBJECT_gpencil_color_names(Object *ob, struct DRWTextStore *dt, ucha } } +BLI_INLINE OBJECT_DupliData *OBJECT_duplidata_get(Object *ob, void *vedata, bool *init) +{ + OBJECT_DupliData **dupli_data = (OBJECT_DupliData **)DRW_duplidata_get(vedata); + *init = false; + if (!ELEM(ob->type, OB_MESH, OB_SURF, OB_LATTICE, OB_CURVE, OB_FONT)) { + return NULL; + } + + if (dupli_data) { + if (*dupli_data == NULL) { + *dupli_data = MEM_callocN(sizeof(OBJECT_DupliData), "OBJECT_DupliData"); + *init = true; + } + return *dupli_data; + } + return NULL; +} + static void OBJECT_cache_populate(void *vedata, Object *ob) { OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl; @@ -3132,10 +3155,15 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) /* Show if this is the camera we're looking through since it's useful for selecting. */ (((rv3d->persp == RV3D_CAMOB) && ((ID *)v3d->camera == ob->id.orig_id)) == 0)); + /* Fast path for duplis. */ + bool init_duplidata; + OBJECT_DupliData *dupli_data = OBJECT_duplidata_get(ob, vedata, &init_duplidata); + if (do_outlines) { if (!BKE_object_is_in_editmode(ob) && !((ob == draw_ctx->obact) && (draw_ctx->object_mode & OB_MODE_ALL_PAINT))) { struct GPUBatch *geom; + DRWShadingGroup *shgroup = NULL; /* This fixes only the biggest case which is a plane in ortho view. */ int flat_axis = 0; @@ -3143,185 +3171,211 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) DRW_object_is_flat(ob, &flat_axis) && DRW_object_axis_orthogonal_to_view(ob, flat_axis)); - if (stl->g_data->xray_enabled_and_not_wire || is_flat_object_viewed_from_side) { - geom = DRW_cache_object_edge_detection_get(ob, NULL); + if (dupli_data && !init_duplidata) { + geom = dupli_data->outline_geom; + shgroup = dupli_data->outline_shgrp; } else { - geom = DRW_cache_object_surface_get(ob); - } + if (stl->g_data->xray_enabled_and_not_wire || is_flat_object_viewed_from_side) { + geom = DRW_cache_object_edge_detection_get(ob, NULL); + } + else { + geom = DRW_cache_object_surface_get(ob); + } - if (geom) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - DRWShadingGroup *shgroup = shgroup_theme_id_to_outline_or_null( - stl, theme_id, ob->base_flag); - if (shgroup != NULL) { - DRW_shgroup_call_object_add(shgroup, geom, ob); + if (geom) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + shgroup = shgroup_theme_id_to_outline_or_null(stl, theme_id, ob->base_flag); } } - } - } - switch (ob->type) { - case OB_MESH: { - if (hide_object_extra) { - break; + if (shgroup && geom) { + DRW_shgroup_call_object(shgroup, geom, ob); } - Mesh *me = ob->data; - if (!is_edit_mode && me->totedge == 0) { - struct GPUBatch *geom = DRW_cache_mesh_all_verts_get(ob); - if (geom) { - if (theme_id == TH_UNDEFINED) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - } - DRWShadingGroup *shgroup = shgroup_theme_id_to_point(sgl, theme_id, ob->base_flag); - DRW_shgroup_call_object_add(shgroup, geom, ob); - } + + if (init_duplidata) { + dupli_data->outline_shgrp = shgroup; + dupli_data->outline_geom = geom; } - else { - bool has_edit_mesh_cage = false; - /* TODO: Should be its own function. */ - if (is_edit_mode) { - BMEditMesh *embm = me->edit_mesh; - has_edit_mesh_cage = embm->mesh_eval_cage && - (embm->mesh_eval_cage != embm->mesh_eval_final); + } + } + + if (dupli_data && !init_duplidata) { + if (dupli_data->extra_shgrp && dupli_data->extra_geom) { + DRW_shgroup_call_object(dupli_data->extra_shgrp, dupli_data->extra_geom, ob); + } + } + else { + struct GPUBatch *geom = NULL; + DRWShadingGroup *shgroup = NULL; + switch (ob->type) { + case OB_MESH: { + if (hide_object_extra) { + break; } - if ((!is_edit_mode && me->totedge > 0) || has_edit_mesh_cage) { - struct GPUBatch *geom = DRW_cache_mesh_loose_edges_get(ob); + Mesh *me = ob->data; + if (!is_edit_mode && me->totedge == 0) { + geom = DRW_cache_mesh_all_verts_get(ob); if (geom) { if (theme_id == TH_UNDEFINED) { theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); } - DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); - DRW_shgroup_call_object_add(shgroup, geom, ob); + shgroup = shgroup_theme_id_to_point(sgl, theme_id, ob->base_flag); + DRW_shgroup_call_object(shgroup, geom, ob); + } + } + else { + bool has_edit_mesh_cage = false; + /* TODO: Should be its own function. */ + if (is_edit_mode) { + BMEditMesh *embm = me->edit_mesh; + has_edit_mesh_cage = embm->mesh_eval_cage && + (embm->mesh_eval_cage != embm->mesh_eval_final); + } + if ((!is_edit_mode && me->totedge > 0) || has_edit_mesh_cage) { + geom = DRW_cache_mesh_loose_edges_get(ob); + if (geom) { + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); + DRW_shgroup_call_object(shgroup, geom, ob); + } } } - } - break; - } - case OB_SURF: { - if (hide_object_extra) { - break; - } - struct GPUBatch *geom = DRW_cache_surf_edge_wire_get(ob); - if (geom == NULL) { break; } - if (theme_id == TH_UNDEFINED) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - } - DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); - DRW_shgroup_call_object_add(shgroup, geom, ob); - break; - } - case OB_LATTICE: { - if (!is_edit_mode) { + case OB_SURF: { if (hide_object_extra) { break; } - struct GPUBatch *geom = DRW_cache_lattice_wire_get(ob, false); - if (theme_id == TH_UNDEFINED) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); - } - - DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); - DRW_shgroup_call_object_add(shgroup, geom, ob); - } - break; - } - case OB_CURVE: { - if (!is_edit_mode) { - if (hide_object_extra) { + geom = DRW_cache_surf_edge_wire_get(ob); + if (geom == NULL) { break; } - struct GPUBatch *geom = DRW_cache_curve_edge_wire_get(ob); if (theme_id == TH_UNDEFINED) { theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); } - DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); - DRW_shgroup_call_object_add(shgroup, geom, ob); - } - break; - } - case OB_MBALL: { - if (!is_edit_mode) { - DRW_shgroup_mball_handles(sgl, ob, view_layer); - } - break; - } - case OB_LAMP: - if (hide_object_extra) { + shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); + DRW_shgroup_call_object(shgroup, geom, ob); break; } - DRW_shgroup_light(sgl, ob, view_layer); - break; - case OB_CAMERA: - if (hide_object_extra) { + case OB_LATTICE: { + if (!is_edit_mode) { + if (hide_object_extra) { + break; + } + geom = DRW_cache_lattice_wire_get(ob, false); + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + + shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); + DRW_shgroup_call_object(shgroup, geom, ob); + } break; } - DRW_shgroup_camera(sgl, ob, view_layer); - break; - case OB_EMPTY: - if (hide_object_extra) { + case OB_CURVE: { + if (!is_edit_mode) { + if (hide_object_extra) { + break; + } + geom = DRW_cache_curve_edge_wire_get(ob); + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); + DRW_shgroup_call_object(shgroup, geom, ob); + } break; } - DRW_shgroup_empty(sh_data, sgl, ob, view_layer, rv3d, draw_ctx->sh_cfg); - break; - case OB_SPEAKER: - if (hide_object_extra) { + case OB_MBALL: { + if (!is_edit_mode) { + DRW_shgroup_mball_handles(sgl, ob, view_layer); + } break; } - DRW_shgroup_speaker(sgl, ob, view_layer); - break; - case OB_LIGHTPROBE: - if (hide_object_extra) { + case OB_LAMP: + if (hide_object_extra) { + break; + } + DRW_shgroup_light(sgl, ob, view_layer); break; - } - DRW_shgroup_lightprobe(sh_data, stl, psl, ob, view_layer); - break; - case OB_ARMATURE: { - if ((v3d->flag2 & V3D_HIDE_OVERLAYS) || (v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES) || - ((ob->dt < OB_WIRE) && !DRW_state_is_select())) { + case OB_CAMERA: + if (hide_object_extra) { + break; + } + DRW_shgroup_camera(sgl, ob, view_layer); break; - } - bArmature *arm = ob->data; - if (arm->edbo == NULL) { - if (DRW_state_is_select() || !DRW_pose_mode_armature(ob, draw_ctx->obact)) { - bool is_wire = (v3d->shading.type == OB_WIRE) || (ob->dt <= OB_WIRE) || - XRAY_FLAG_ENABLED(v3d); - DRWArmaturePasses passes = { - .bone_solid = (is_wire) ? NULL : sgl->bone_solid, - .bone_outline = sgl->bone_outline, - .bone_wire = sgl->bone_wire, - .bone_envelope = sgl->bone_envelope, - .bone_axes = sgl->bone_axes, - .relationship_lines = NULL, /* Don't draw relationship lines */ - .custom_shapes = stl->g_data->custom_shapes, - }; - DRW_shgroup_armature_object(ob, view_layer, passes, is_wire); + case OB_EMPTY: + if (hide_object_extra) { + break; + } + DRW_shgroup_empty(sh_data, sgl, ob, view_layer, rv3d, draw_ctx->sh_cfg); + break; + case OB_SPEAKER: + if (hide_object_extra) { + break; + } + DRW_shgroup_speaker(sgl, ob, view_layer); + break; + case OB_LIGHTPROBE: + if (hide_object_extra) { + break; + } + DRW_shgroup_lightprobe(sh_data, stl, psl, ob, view_layer); + break; + case OB_ARMATURE: { + if ((v3d->flag2 & V3D_HIDE_OVERLAYS) || (v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES) || + ((ob->dt < OB_WIRE) && !DRW_state_is_select())) { + break; + } + bArmature *arm = ob->data; + if (arm->edbo == NULL) { + if (DRW_state_is_select() || !DRW_pose_mode_armature(ob, draw_ctx->obact)) { + bool is_wire = (v3d->shading.type == OB_WIRE) || (ob->dt <= OB_WIRE) || + XRAY_FLAG_ENABLED(v3d); + DRWArmaturePasses passes = { + .bone_solid = (is_wire) ? NULL : sgl->bone_solid, + .bone_outline = sgl->bone_outline, + .bone_wire = sgl->bone_wire, + .bone_envelope = sgl->bone_envelope, + .bone_axes = sgl->bone_axes, + .relationship_lines = NULL, /* Don't draw relationship lines */ + .custom_shapes = stl->g_data->custom_shapes, + }; + DRW_shgroup_armature_object(ob, view_layer, passes, is_wire); + } } - } - break; - } - case OB_FONT: { - if (hide_object_extra) { break; } - Curve *cu = (Curve *)ob->data; - bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f || cu->ext2 != 0.0f; - if (!has_surface) { - struct GPUBatch *geom = DRW_cache_text_edge_wire_get(ob); - if (geom) { - if (theme_id == TH_UNDEFINED) { - theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + case OB_FONT: { + if (hide_object_extra) { + break; + } + Curve *cu = (Curve *)ob->data; + bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f || + cu->ext2 != 0.0f; + if (!has_surface) { + geom = DRW_cache_text_edge_wire_get(ob); + if (geom) { + if (theme_id == TH_UNDEFINED) { + theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL); + } + shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); + DRW_shgroup_call_object(shgroup, geom, ob); } - DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag); - DRW_shgroup_call_object_add(shgroup, geom, ob); } + break; } - break; + default: + break; + } + + if (init_duplidata) { + dupli_data->extra_shgrp = shgroup; + dupli_data->extra_geom = geom; } - default: - break; } if (ob->pd && ob->pd->forcefield) { @@ -3386,7 +3440,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob) float *color, axes_size = 1.0f; DRW_object_wire_theme_get(ob, view_layer, &color); - DRW_shgroup_call_dynamic_add(sgl->empty_axes, color, &axes_size, ob->obmat); + DRW_buffer_add_entry(sgl->empty_axes, color, &axes_size, ob->obmat); } if ((md = modifiers_findByType(ob, eModifierType_Smoke)) && diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c index 90fac136f73..36493c5eff5 100644 --- a/source/blender/draw/modes/overlay_mode.c +++ b/source/blender/draw/modes/overlay_mode.c @@ -46,6 +46,11 @@ /* Structures */ +typedef struct OVERLAY_DupliData { + DRWShadingGroup *shgrp; + struct GPUBatch *geom; +} OVERLAY_DupliData; + typedef struct OVERLAY_StorageList { struct OVERLAY_PrivateData *g_data; } OVERLAY_StorageList; @@ -95,6 +100,8 @@ extern char datatoc_overlay_face_wireframe_geom_glsl[]; extern char datatoc_overlay_face_wireframe_frag_glsl[]; extern char datatoc_gpu_shader_depth_only_frag_glsl[]; +extern char datatoc_common_view_lib_glsl[]; + /* Functions */ static void overlay_engine_init(void *vedata) { @@ -119,8 +126,10 @@ static void overlay_engine_init(void *vedata) if (!sh_data->face_orientation) { /* Face orientation */ sh_data->face_orientation = GPU_shader_create_from_arrays({ - .vert = - (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_orientation_vert_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_overlay_face_orientation_vert_glsl, + NULL}, .frag = (const char *[]){datatoc_overlay_face_orientation_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); @@ -128,7 +137,10 @@ static void overlay_engine_init(void *vedata) if (!sh_data->face_wireframe) { sh_data->select_wireframe = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_overlay_face_wireframe_vert_glsl, + NULL}, .geom = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_geom_glsl, NULL}, .frag = (const char *[]){datatoc_gpu_shader_depth_only_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, "#define SELECT_EDGES\n", NULL}, @@ -136,14 +148,20 @@ static void overlay_engine_init(void *vedata) #if USE_GEOM_SHADER_WORKAROUND /* Apple drivers does not support wide wires. Use geometry shader as a workaround. */ sh_data->face_wireframe = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_overlay_face_wireframe_vert_glsl, + NULL}, .geom = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_geom_glsl, NULL}, .frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, "#define USE_GEOM\n", NULL}, }); #else sh_data->face_wireframe = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_overlay_face_wireframe_vert_glsl, + NULL}, .frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); @@ -337,12 +355,27 @@ static void overlay_cache_populate(void *vedata, Object *ob) if (DRW_object_is_renderable(ob) && pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) { struct GPUBatch *geom = DRW_cache_object_surface_get(ob); if (geom) { - DRW_shgroup_call_add(pd->face_orientation_shgrp, geom, ob->obmat); + DRW_shgroup_call_object(pd->face_orientation_shgrp, geom, ob); } } if ((pd->overlay.flag & V3D_OVERLAY_WIREFRAMES) || (v3d->shading.type == OB_WIRE) || (ob->dtx & OB_DRAWWIRE) || (ob->dt == OB_WIRE)) { + + /* Fast path for duplis. */ + OVERLAY_DupliData **dupli_data = (OVERLAY_DupliData **)DRW_duplidata_get(vedata); + if (dupli_data) { + if (*dupli_data == NULL) { + *dupli_data = MEM_callocN(sizeof(OVERLAY_DupliData), "OVERLAY_DupliData"); + } + else { + if ((*dupli_data)->shgrp && (*dupli_data)->geom) { + DRW_shgroup_call_object((*dupli_data)->shgrp, (*dupli_data)->geom, ob); + } + return; + } + } + const bool is_edit_mode = BKE_object_is_in_editmode(ob); bool has_edit_mesh_cage = false; if (ob->type == OB_MESH) { @@ -389,12 +422,18 @@ static void overlay_cache_populate(void *vedata, Object *ob) } if (is_sculpt_mode) { - DRW_shgroup_call_sculpt_add(shgrp, ob, true, false, false); + DRW_shgroup_call_sculpt(shgrp, ob, true, false, false); } else { - DRW_shgroup_call_add(shgrp, geom, ob->obmat); + DRW_shgroup_call_object(shgrp, geom, ob); } } + + if (dupli_data) { + (*dupli_data)->shgrp = shgrp; + (*dupli_data)->geom = geom; + } + if (is_wire && shgrp != NULL) { /* If object is wireframe, don't try to use stencil test. */ DRW_shgroup_state_disable(shgrp, DRW_STATE_STENCIL_EQUAL); diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c index 3e292f4e4bc..e99a0c0dab2 100644 --- a/source/blender/draw/modes/paint_texture_mode.c +++ b/source/blender/draw/modes/paint_texture_mode.c @@ -27,6 +27,8 @@ #include "BKE_node.h" +#include "BLI_string_utils.h" + /* If builtin shaders are needed */ #include "GPU_shader.h" #include "GPU_texture.h" @@ -39,6 +41,7 @@ #include "DEG_depsgraph_query.h" extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; extern char datatoc_paint_texture_vert_glsl[]; extern char datatoc_paint_texture_frag_glsl[]; extern char datatoc_paint_wire_vert_glsl[]; @@ -132,26 +135,31 @@ static void PAINT_TEXTURE_engine_init(void *UNUSED(vedata)) if (!e_data.fallback_sh) { e_data.fallback_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); - e_data.image_sh = DRW_shader_create_with_lib(datatoc_paint_texture_vert_glsl, - NULL, - datatoc_paint_texture_frag_glsl, - datatoc_common_globals_lib_glsl, - NULL); + char *lib = BLI_string_joinN(datatoc_common_globals_lib_glsl, datatoc_common_view_lib_glsl); + + e_data.image_sh = DRW_shader_create_with_lib( + datatoc_paint_texture_vert_glsl, NULL, datatoc_paint_texture_frag_glsl, lib, NULL); e_data.image_masking_sh = DRW_shader_create_with_lib(datatoc_paint_texture_vert_glsl, NULL, datatoc_paint_texture_frag_glsl, - datatoc_common_globals_lib_glsl, + lib, "#define TEXTURE_PAINT_MASK\n"); e_data.wire_overlay_shader = DRW_shader_create_with_lib(datatoc_paint_wire_vert_glsl, NULL, datatoc_paint_wire_frag_glsl, - datatoc_common_globals_lib_glsl, + lib, "#define VERTEX_MODE\n"); - e_data.face_overlay_shader = DRW_shader_create( - datatoc_paint_face_vert_glsl, NULL, datatoc_gpu_shader_uniform_color_frag_glsl, NULL); + e_data.face_overlay_shader = DRW_shader_create_with_lib( + datatoc_paint_face_vert_glsl, + NULL, + datatoc_gpu_shader_uniform_color_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); + + MEM_freeN(lib); } } @@ -174,7 +182,7 @@ static DRWShadingGroup *create_texture_paint_shading_group(PAINT_TEXTURE_PassLis if (masking_enabled) { const bool masking_inverted = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) > 0; - GPUTexture *stencil = GPU_texture_from_blender(imapaint->stencil, NULL, GL_TEXTURE_2D, false); + GPUTexture *stencil = GPU_texture_from_blender(imapaint->stencil, NULL, GL_TEXTURE_2D); DRW_shgroup_uniform_texture(grp, "maskingImage", stencil); DRW_shgroup_uniform_vec3(grp, "maskingColor", imapaint->stencil_col, 1); DRW_shgroup_uniform_bool_copy(grp, "maskingInvertStencil", masking_inverted); @@ -228,7 +236,7 @@ static void PAINT_TEXTURE_cache_init(void *vedata) NULL; int interp = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].interp : 0; - GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false); + GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D); if (tex) { DRWShadingGroup *grp = create_texture_paint_shading_group( @@ -242,7 +250,7 @@ static void PAINT_TEXTURE_cache_init(void *vedata) } else { Image *ima = imapaint->canvas; - GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false); + GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D); if (tex) { DRWShadingGroup *grp = create_texture_paint_shading_group( @@ -308,24 +316,23 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob) for (int i = 0; i < mat_nr; i++) { const int index = use_material_slots ? i : 0; if ((i < me->totcol) && stl->g_data->shgroup_image_array[index]) { - DRW_shgroup_call_add( - stl->g_data->shgroup_image_array[index], geom_array[i], ob->obmat); + DRW_shgroup_call(stl->g_data->shgroup_image_array[index], geom_array[i], ob->obmat); } else { - DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat); + DRW_shgroup_call(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat); } } } else { if (stl->g_data->shgroup_image_array[0]) { struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob); - DRW_shgroup_call_add(stl->g_data->shgroup_image_array[0], geom, ob->obmat); + DRW_shgroup_call(stl->g_data->shgroup_image_array[0], geom, ob->obmat); } } } else { struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob); - DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->shgroup_fallback, geom, ob->obmat); } } @@ -333,10 +340,10 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob) if (use_face_sel) { struct GPUBatch *geom; geom = DRW_cache_mesh_surface_edges_get(ob); - DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->lwire_shgrp, geom, ob->obmat); geom = DRW_cache_mesh_surface_get(ob); - DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->face_shgrp, geom, ob->obmat); } } } diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c index ef3af1255eb..da76573a7e4 100644 --- a/source/blender/draw/modes/paint_vertex_mode.c +++ b/source/blender/draw/modes/paint_vertex_mode.c @@ -42,6 +42,7 @@ extern char datatoc_paint_wire_vert_glsl[]; extern char datatoc_paint_wire_frag_glsl[]; extern char datatoc_paint_vert_frag_glsl[]; extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; @@ -115,12 +116,16 @@ static void PAINT_VERTEX_engine_init(void *UNUSED(vedata)) if (!sh_data->face_select_overlay) { sh_data->by_mode[VERTEX_MODE].color_face = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_paint_vertex_vert_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_paint_vertex_vert_glsl, + NULL}, .frag = (const char *[]){datatoc_paint_vertex_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); sh_data->by_mode[WEIGHT_MODE].color_face = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, datatoc_common_globals_lib_glsl, datatoc_paint_weight_vert_glsl, NULL}, @@ -131,13 +136,17 @@ static void PAINT_VERTEX_engine_init(void *UNUSED(vedata)) }); sh_data->face_select_overlay = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg_data->lib, datatoc_paint_face_vert_glsl, NULL}, + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_paint_face_vert_glsl, + NULL}, .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); sh_data->vert_select_overlay = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, + datatoc_common_view_lib_glsl, datatoc_paint_wire_vert_glsl, NULL}, .frag = (const char *[]){datatoc_paint_vert_frag_glsl, NULL}, @@ -152,6 +161,7 @@ static void PAINT_VERTEX_engine_init(void *UNUSED(vedata)) sh_data->by_mode[i].wire_overlay = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, + datatoc_common_view_lib_glsl, datatoc_paint_wire_vert_glsl, NULL}, .frag = (const char *[]){datatoc_paint_wire_frag_glsl, NULL}, @@ -160,6 +170,7 @@ static void PAINT_VERTEX_engine_init(void *UNUSED(vedata)) sh_data->by_mode[i].wire_select_overlay = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, + datatoc_common_view_lib_glsl, datatoc_paint_wire_vert_glsl, NULL}, .frag = (const char *[]){datatoc_paint_wire_frag_glsl, NULL}, @@ -301,24 +312,24 @@ static void PAINT_VERTEX_cache_populate(void *vedata, Object *ob) } } if (geom != NULL) { - DRW_shgroup_call_add(stl->g_data->by_mode[draw_mode].color_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->by_mode[draw_mode].color_shgrp, geom, ob->obmat); } if (use_face_sel || use_wire) { DRWShadingGroup *shgrp = use_face_sel ? stl->g_data->by_mode[draw_mode].lwire_select_shgrp : stl->g_data->by_mode[draw_mode].lwire_shgrp; geom = DRW_cache_mesh_surface_edges_get(ob); - DRW_shgroup_call_add(shgrp, geom, ob->obmat); + DRW_shgroup_call(shgrp, geom, ob->obmat); } if (use_face_sel) { geom = DRW_cache_mesh_surface_get(ob); - DRW_shgroup_call_add(stl->g_data->face_select_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->face_select_shgrp, geom, ob->obmat); } if (use_vert_sel) { geom = DRW_cache_mesh_all_verts_get(ob); - DRW_shgroup_call_add(stl->g_data->vert_select_shgrp, geom, ob->obmat); + DRW_shgroup_call(stl->g_data->vert_select_shgrp, geom, ob->obmat); } } } diff --git a/source/blender/draw/modes/particle_mode.c b/source/blender/draw/modes/particle_mode.c index 600a29fecb4..c4a0a768796 100644 --- a/source/blender/draw/modes/particle_mode.c +++ b/source/blender/draw/modes/particle_mode.c @@ -27,6 +27,8 @@ #include "BKE_pointcache.h" +#include "BLI_string_utils.h" + #include "GPU_shader.h" #include "draw_common.h" @@ -39,6 +41,7 @@ extern char datatoc_particle_strand_vert_glsl[]; extern char datatoc_particle_strand_frag_glsl[]; extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; /* *********** LISTS *********** */ @@ -86,23 +89,23 @@ typedef struct PARTICLE_PrivateData { static void particle_engine_init(void *UNUSED(vedata)) { if (!e_data.strands_shader) { - e_data.strands_shader = DRW_shader_create_with_lib(datatoc_particle_strand_vert_glsl, - NULL, - datatoc_particle_strand_frag_glsl, - datatoc_common_globals_lib_glsl, - ""); + char *lib = BLI_string_joinN(datatoc_common_globals_lib_glsl, datatoc_common_view_lib_glsl); + + e_data.strands_shader = DRW_shader_create_with_lib( + datatoc_particle_strand_vert_glsl, NULL, datatoc_particle_strand_frag_glsl, lib, ""); e_data.strands_weight_shader = DRW_shader_create_with_lib(datatoc_particle_strand_vert_glsl, NULL, datatoc_particle_strand_frag_glsl, - datatoc_common_globals_lib_glsl, + lib, "#define USE_WEIGHT"); e_data.points_shader = DRW_shader_create_with_lib(datatoc_particle_strand_vert_glsl, NULL, datatoc_particle_strand_frag_glsl, - datatoc_common_globals_lib_glsl, + lib, "#define USE_POINTS"); + MEM_freeN(lib); } } @@ -147,15 +150,15 @@ static void particle_edit_cache_populate(void *vedata, { struct GPUBatch *strands = DRW_cache_particles_get_edit_strands( object, psys, edit, use_weight); - DRW_shgroup_call_add(stl->g_data->strands_group, strands, NULL); + DRW_shgroup_call(stl->g_data->strands_group, strands, NULL); } if (pset->selectmode == SCE_SELECT_POINT) { struct GPUBatch *points = DRW_cache_particles_get_edit_inner_points(object, psys, edit); - DRW_shgroup_call_add(stl->g_data->inner_points_group, points, NULL); + DRW_shgroup_call(stl->g_data->inner_points_group, points, NULL); } if (ELEM(pset->selectmode, SCE_SELECT_POINT, SCE_SELECT_END)) { struct GPUBatch *points = DRW_cache_particles_get_edit_tip_points(object, psys, edit); - DRW_shgroup_call_add(stl->g_data->tip_points_group, points, NULL); + DRW_shgroup_call(stl->g_data->tip_points_group, points, NULL); } } diff --git a/source/blender/draw/modes/pose_mode.c b/source/blender/draw/modes/pose_mode.c index a37901a1fa9..cde0d392480 100644 --- a/source/blender/draw/modes/pose_mode.c +++ b/source/blender/draw/modes/pose_mode.c @@ -226,10 +226,10 @@ static void POSE_cache_populate(void *vedata, Object *ob) struct GPUBatch *geom = DRW_cache_object_surface_get(ob); if (geom) { if (POSE_is_driven_by_active_armature(ob)) { - DRW_shgroup_call_object_add(ppd->bone_selection_shgrp, geom, ob); + DRW_shgroup_call_object(ppd->bone_selection_shgrp, geom, ob); } else { - DRW_shgroup_call_object_add(ppd->bone_selection_invert_shgrp, geom, ob); + DRW_shgroup_call_object(ppd->bone_selection_invert_shgrp, geom, ob); } } } diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c index 053e73e4068..363476445c1 100644 --- a/source/blender/draw/modes/sculpt_mode.c +++ b/source/blender/draw/modes/sculpt_mode.c @@ -37,6 +37,7 @@ #include "draw_common.h" #include "draw_mode_engines.h" +extern char datatoc_common_view_lib_glsl[]; extern char datatoc_sculpt_mask_vert_glsl[]; extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; @@ -111,8 +112,11 @@ static void SCULPT_engine_init(void *vedata) UNUSED_VARS(txl, fbl, stl); if (!e_data.shader_mask) { - e_data.shader_mask = DRW_shader_create( - datatoc_sculpt_mask_vert_glsl, NULL, datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL); + e_data.shader_mask = DRW_shader_create_with_lib(datatoc_sculpt_mask_vert_glsl, + NULL, + datatoc_gpu_shader_3D_smooth_color_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); } } @@ -154,7 +158,7 @@ static void SCULPT_cache_populate(void *vedata, Object *ob) if (ob->sculpt && (ob == draw_ctx->obact)) { PBVH *pbvh = ob->sculpt->pbvh; if (pbvh && pbvh_has_mask(pbvh)) { - DRW_shgroup_call_sculpt_add(stl->g_data->mask_overlay_grp, ob, false, true, false); + DRW_shgroup_call_sculpt(stl->g_data->mask_overlay_grp, ob, false, true, false); } } } diff --git a/source/blender/draw/modes/shaders/armature_axes_vert.glsl b/source/blender/draw/modes/shaders/armature_axes_vert.glsl index a689dce4d70..d7ed3e9ab71 100644 --- a/source/blender/draw/modes/shaders/armature_axes_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_axes_vert.glsl @@ -1,9 +1,7 @@ uniform mat4 ViewProjectionMatrix; uniform vec3 screenVecs[3]; -#ifdef USE_WORLD_CLIP_PLANES -uniform mat4 ModelMatrix; -#endif + /* ---- Instantiated Attrs ---- */ in float axis; /* position on the axis. [0.0-1.0] is X axis, [1.0-2.0] is Y, etc... */ in vec2 screenPos; @@ -32,6 +30,6 @@ void main() finalColor.a = 1.0; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance(pos_4d.xyz); #endif } diff --git a/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl index 1e7fc4d11b8..c0bde90bf28 100644 --- a/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl @@ -3,9 +3,6 @@ uniform mat4 ViewMatrix; uniform mat4 ViewMatrixInverse; uniform mat4 ViewProjectionMatrix; uniform mat4 ProjectionMatrix; -#ifdef USE_WORLD_CLIP_PLANES -uniform mat4 ModelMatrix; -#endif uniform vec2 viewportSize; uniform float lineThickness = 2.0; @@ -145,7 +142,7 @@ void main() vec4 pos_4d = vec4(wpos1, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance(pos_4d.xyz); #endif vec4 V = ViewMatrix * pos_4d; diff --git a/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl index 7f8ccc0c95a..d9567bb84f4 100644 --- a/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl @@ -2,9 +2,6 @@ uniform mat4 ViewMatrix; uniform mat4 ViewMatrixInverse; uniform mat4 ViewProjectionMatrix; -#ifdef USE_WORLD_CLIP_PLANES -uniform mat4 ModelMatrix; -#endif /* ---- Instantiated Attrs ---- */ in vec3 pos; @@ -57,6 +54,6 @@ void main() vec4 pos_4d = vec4(sp, 1.0); gl_Position = ViewProjectionMatrix * pos_4d; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance(pos_4d.xyz); #endif } 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 54315863a2e..dc84b8924d1 100644 --- a/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl @@ -9,7 +9,6 @@ in vec2 ssNor[]; in vec4 vColSize[]; flat out vec4 finalColor; -uniform mat4 ProjectionMatrix; uniform vec2 viewportSize; uniform float lineThickness = 2.0; 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 82a483d91a5..fb2735c196c 100644 --- a/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl @@ -1,8 +1,4 @@ -uniform mat3 NormalMatrix; - -uniform mat4 ViewMatrix; -uniform mat4 ProjectionMatrix; uniform vec2 viewportSize; /* ---- Instantiated Attrs ---- */ @@ -27,20 +23,19 @@ vec2 proj(vec4 pos) void main() { - /* This is slow and run per vertex, but it's still faster than - * doing it per instance on CPU and sending it on via instance attribute. */ - mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); - vec4 worldPosition = InstanceModelMatrix * vec4(pos, 1.0); vec4 viewpos = ViewMatrix * worldPosition; vPos = viewpos.xyz; pPos = ProjectionMatrix * viewpos; + /* This is slow and run per vertex, but it's still faster than + * doing it per instance on CPU and sending it on via instance attribute. */ + mat3 normal_mat = transpose(inverse(mat3(InstanceModelMatrix))); /* 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); + ssNor = normalize(normal_world_to_view(normal_mat * snor).xy); ssPos = proj(pPos); 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 2df25bf0e03..df6a9ce2d76 100644 --- a/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl @@ -1,11 +1,4 @@ -uniform mat3 NormalMatrix; -uniform mat4 ViewMatrixInverse; -uniform mat4 ViewProjectionMatrix; - -uniform mat4 ViewMatrix; -uniform mat4 ProjectionMatrix; - /* ---- Instantiated Attrs ---- */ in vec3 pos; in vec3 nor; @@ -19,8 +12,10 @@ out vec4 finalColor; void main() { - mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); - vec3 normal = normalize(NormalMatrix * nor); + /* This is slow and run per vertex, but it's still faster than + * doing it per instance on CPU and sending it on via instance attribute. */ + mat3 normal_mat = transpose(inverse(mat3(InstanceModelMatrix))); + vec3 normal = normalize(normal_world_to_view(normal_mat * nor)); /* Do lighting at an angle to avoid flat shading on front facing bone. */ const vec3 light = vec3(0.1, 0.1, 0.8); diff --git a/source/blender/draw/modes/shaders/armature_stick_vert.glsl b/source/blender/draw/modes/shaders/armature_stick_vert.glsl index 9e5a3d76c0d..fd8a12fcd2c 100644 --- a/source/blender/draw/modes/shaders/armature_stick_vert.glsl +++ b/source/blender/draw/modes/shaders/armature_stick_vert.glsl @@ -1,7 +1,7 @@ uniform mat4 ProjectionMatrix; uniform mat4 ViewProjectionMatrix; -uniform mat4 ModelMatrix; + uniform mat4 ViewMatrix; uniform vec2 viewportSize; @@ -88,8 +88,7 @@ void main() gl_Position.z += (is_bone) ? 0.0 : 1e-6; /* Avoid Z fighting of head/tails. */ #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance( - (ModelMatrix * (is_head ? boneStart_4d : boneEnd_4d)).xyz); + world_clip_planes_calc_clip_distance((is_head ? boneStart_4d : boneEnd_4d).xyz); #endif } else { diff --git a/source/blender/draw/modes/shaders/common_view_lib.glsl b/source/blender/draw/modes/shaders/common_view_lib.glsl index de9c4e2a96e..79ac351912d 100644 --- a/source/blender/draw/modes/shaders/common_view_lib.glsl +++ b/source/blender/draw/modes/shaders/common_view_lib.glsl @@ -13,3 +13,38 @@ layout(std140) uniform viewBlock vec4 clipPlanes[2]; }; + +uniform mat4 ModelMatrix; +uniform mat4 ModelMatrixInverse; + +/** Transform shortcuts. */ +/* Rule of thumb: Try to reuse world positions and normals because converting though viewspace + * will always be decomposed in at least 2 matrix operation. */ + +/** + * Some clarification: + * Usually Normal matrix is transpose(inverse(ViewMatrix * ModelMatrix)) + * + * But since it is slow to multiply matrices we decompose it. Decomposing + * inversion and transposition both invert the product order leaving us with + * the same original order: + * transpose(ViewMatrixInverse) * transpose(ModelMatrixInverse) + * + * Knowing that the view matrix is orthogonal, the transpose is also the inverse. + * Note: This is only valid because we are only using the mat3 of the ViewMatrixInverse. + * ViewMatrix * transpose(ModelMatrixInverse) + **/ +#define normal_object_to_view(n) (mat3(ViewMatrix) * (transpose(mat3(ModelMatrixInverse)) * n)) +#define normal_object_to_world(n) (transpose(mat3(ModelMatrixInverse)) * n) +#define normal_world_to_object(n) (transpose(mat3(ModelMatrix)) * n) +#define normal_world_to_view(n) (mat3(ViewMatrix) * n) + +#define point_object_to_ndc(p) (ViewProjectionMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)) +#define point_object_to_view(p) ((ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)).xyz) +#define point_object_to_world(p) ((ModelMatrix * vec4(p, 1.0)).xyz) +#define point_view_to_ndc(p) (ProjectionMatrix * vec4(p, 1.0)) +#define point_view_to_object(p) ((ModelMatrixInverse * (ViewMatrixInverse * vec4(p, 1.0))).xyz) +#define point_view_to_world(p) ((ViewMatrixInverse * vec4(p, 1.0)).xyz) +#define point_world_to_ndc(p) (ViewProjectionMatrix * vec4(p, 1.0)) +#define point_world_to_object(p) ((ModelMatrixInverse * vec4(p, 1.0)).xyz) +#define point_world_to_view(p) ((ViewMatrix * vec4(p, 1.0)).xyz) diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl index b7166382b19..2f3d37a6e73 100644 --- a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl @@ -1,6 +1,4 @@ /* Draw Curve Handles */ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; in vec3 pos; in int data; @@ -9,11 +7,11 @@ flat out int vertFlag; void main() { - vec4 pos_4d = vec4(pos, 1.0); - gl_Position = ModelViewProjectionMatrix * pos_4d; + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); vertFlag = data; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl index 4718f11db65..b1b707b59f4 100644 --- a/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl @@ -1,6 +1,5 @@ /* Draw Curve Vertices */ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; + uniform vec2 viewportSize; in vec3 pos; @@ -22,10 +21,10 @@ void main() finalColor = colorVertex; } - vec4 pos_4d = vec4(pos, 1.0); - gl_Position = ModelViewProjectionMatrix * pos_4d; + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); gl_PointSize = sizeVertex * 2.0; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl index 02244086711..ef60ddbc395 100644 --- a/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl @@ -1,6 +1,5 @@ /* Draw Curve Normals */ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; + uniform float normalSize; in vec3 pos; @@ -18,10 +17,10 @@ void main() final_pos += normalSize * rad * (flip * nor - tan); } - vec4 final_pos_4d = vec4(final_pos, 1.0); - gl_Position = ModelViewProjectionMatrix * final_pos_4d; + vec3 world_pos = point_object_to_world(final_pos); + gl_Position = point_world_to_ndc(world_pos); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * final_pos_4d).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl index 3cf808f3c52..f7df6bb4b68 100644 --- a/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl @@ -1,8 +1,5 @@ - /* Draw Lattice Vertices */ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; uniform vec2 viewportSize; in vec3 pos; @@ -27,7 +24,8 @@ void main() { clipCase = 0; - vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + vec4 pPos = point_world_to_ndc(world_pos); /* only vertex position 0 is used */ eData1 = eData2 = vec4(1e10); @@ -39,6 +37,6 @@ void main() gl_Position = pPos; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl index c84d97fa1c5..a20c1124fe1 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl @@ -1,6 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; uniform ivec4 dataMask = ivec4(0xFF); in vec3 pos; @@ -10,13 +8,14 @@ flat out vec4 faceColor; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); ivec4 data_m = data & dataMask; faceColor = EDIT_MESH_face_color(data_m.x); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl index 94d8d2e701c..968a63c7780 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl @@ -1,5 +1,3 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; in vec3 pos; in vec4 weight_color; @@ -14,10 +12,11 @@ out vec4 weightColor; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); weightColor = vec4(weight_color.rgb, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl index d700e69fb57..9aa656818cb 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl @@ -1,9 +1,4 @@ -uniform mat3 NormalMatrix; -uniform mat4 ProjectionMatrix; -uniform mat4 ModelViewMatrix; -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; uniform float faceAlphaMod; uniform ivec4 dataMask = ivec4(0xFF); uniform float ofs; @@ -25,14 +20,17 @@ out int selectOveride; void main() { + vec3 world_pos = point_object_to_world(pos); + #if !defined(FACE) + /* TODO override the ViewProjection Matrix for this case. */ mat4 projmat = ProjectionMatrix; projmat[3][2] -= ofs; - gl_Position = projmat * (ModelViewMatrix * vec4(pos, 1.0)); + gl_Position = projmat * (ViewMatrix * vec4(world_pos, 1.0)); #else - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = point_world_to_ndc(world_pos); #endif ivec4 m_data = data & dataMask; @@ -76,17 +74,16 @@ void main() #if !defined(FACE) /* Facing based color blend */ - vec4 vpos = ModelViewMatrix * vec4(pos, 1.0); - vec3 view_normal = normalize(NormalMatrix * vnor + 1e-4); - vec3 view_vec = (ProjectionMatrix[3][3] == 0.0) ? normalize(vpos.xyz) : vec3(0.0, 0.0, 1.0); + vec3 vpos = point_world_to_view(world_pos); + vec3 view_normal = normalize(normal_object_to_view(vnor) + 1e-4); + vec3 view_vec = (ProjectionMatrix[3][3] == 0.0) ? normalize(vpos) : vec3(0.0, 0.0, 1.0); float facing = dot(view_vec, view_normal); facing = 1.0 - abs(facing) * 0.2; finalColor.rgb = mix(colorEditMeshMiddle.rgb, finalColor.rgb, facing); - #endif #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/edit_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_normals_vert.glsl index 2e34a132cb0..9bf0fb7315c 100644 --- a/source/blender/draw/modes/shaders/edit_normals_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_normals_vert.glsl @@ -1,8 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat3 NormalMatrix; -uniform mat4 ProjectionMatrix; -uniform mat4 ModelMatrix; uniform float normalSize; in vec3 pos; @@ -25,10 +21,14 @@ flat out vec4 v2; void main() { - v1 = ModelViewProjectionMatrix * vec4(pos, 1.0); - vec3 n = normalize(NormalMatrix * nor); /* viewspace */ - v2 = v1 + ProjectionMatrix * vec4(n * normalSize, 0.0); + vec3 n = normalize(normal_object_to_world(nor)); + + vec3 world_pos = point_object_to_world(pos); + + v1 = point_world_to_ndc(world_pos); + v2 = point_world_to_ndc(world_pos + n * normalSize); + #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl b/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl index 7fd955343fc..43c8e313fc3 100644 --- a/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl +++ b/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl @@ -1,8 +1,5 @@ uniform mat4 ViewProjectionMatrix; -#ifdef USE_WORLD_CLIP_PLANES -uniform mat4 ModelMatrix; -#endif uniform vec3 screenVecs[3]; @@ -33,6 +30,6 @@ void main() finalColor = vec4(color, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance(pos_4d.xyz); #endif } diff --git a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl index 386d05636f9..deb82a8904e 100644 --- a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl +++ b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl @@ -14,12 +14,33 @@ uniform sampler2D image; uniform int depthMode; uniform bool useAlphaTest; +float linearrgb_to_srgb(float c) +{ + if (c < 0.0031308) { + return (c < 0.0) ? 0.0 : c * 12.92; + } + else { + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; + } +} + +vec4 texture_read_as_srgb(sampler2D tex, vec2 co) +{ + /* By convention image textures return scene linear colors, but + * overlays still assume srgb. */ + vec4 color = texture(tex, co); + color.r = linearrgb_to_srgb(color.r); + color.g = linearrgb_to_srgb(color.g); + color.b = linearrgb_to_srgb(color.b); + return color; +} + void main() { #ifdef USE_WIRE fragColor = finalColor; #else - vec4 tex_col = texture(image, texCoord_interp); + vec4 tex_col = texture_read_as_srgb(image, texCoord_interp); fragColor = finalColor * tex_col; if (useAlphaTest) { diff --git a/source/blender/draw/modes/shaders/object_empty_image_vert.glsl b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl index 9694c63fef1..36e86290be7 100644 --- a/source/blender/draw/modes/shaders/object_empty_image_vert.glsl +++ b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl @@ -1,7 +1,5 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; -uniform float aspectX; -uniform float aspectY; + +uniform vec2 aspect; uniform float size; uniform vec2 offset; #ifdef USE_WIRE @@ -21,8 +19,9 @@ out vec2 texCoord_interp; void main() { - vec4 pos_4d = vec4((pos + offset) * (size * vec2(aspectX, aspectY)), 0.0, 1.0); - gl_Position = ModelViewProjectionMatrix * pos_4d; + vec3 pos = vec3((pos + offset) * (size * aspect), 0.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); #ifdef USE_WIRE gl_Position.z -= 1e-5; finalColor = vec4(color, 1.0); @@ -32,6 +31,6 @@ void main() #endif #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl index df2cfe7be82..a20f12efd93 100644 --- a/source/blender/draw/modes/shaders/object_grid_frag.glsl +++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl @@ -8,10 +8,7 @@ in vec3 local_pos; out vec4 FragColor; -uniform mat4 ProjectionMatrix; -uniform vec3 cameraPos; uniform vec3 planeAxes; -uniform vec3 eye; uniform vec4 gridSettings; uniform float meshSize; uniform float lineKernel = 0.0; @@ -23,6 +20,8 @@ uniform sampler2D depthBuffer; #define gridScale gridSettings.z #define gridSubdiv gridSettings.w +#define cameraPos (ViewMatrixInverse[3].xyz) + uniform int gridFlag; #define AXIS_X (1 << 0) @@ -109,7 +108,7 @@ void main() dist = 1.0; /* avoid branch after */ if ((gridFlag & PLANE_XY) != 0) { - float angle = 1.0 - abs(eye.z); + float angle = 1.0 - abs(ViewMatrixInverse[2].z); dist = 1.0 + angle * 2.0; angle *= angle; fade *= 1.0 - angle * angle; diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl index e8f4b089b47..d247967b03a 100644 --- a/source/blender/draw/modes/shaders/object_grid_vert.glsl +++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl @@ -2,9 +2,6 @@ /* Infinite grid * Clément Foucault */ -uniform mat4 ViewProjectionMatrix; -uniform mat4 ProjectionMatrix; -uniform vec3 cameraPos; uniform vec3 planeAxes; uniform vec4 gridSettings; uniform float meshSize; @@ -16,6 +13,8 @@ uniform float meshSize; uniform int gridFlag; +#define cameraPos (ViewMatrixInverse[3].xyz) + #define PLANE_XY (1 << 4) #define PLANE_XZ (1 << 5) #define PLANE_YZ (1 << 6) diff --git a/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl b/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl index c395ed01bca..9414309570b 100644 --- a/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl +++ b/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl @@ -4,7 +4,6 @@ * Note that if the stiffness is zero, it assumes the scale is directly multiplied by the radius */ uniform mat4 ViewProjectionMatrix; -uniform mat4 ModelMatrix; uniform vec3 screen_vecs[2]; /* ---- Instantiated Attrs ---- */ @@ -32,6 +31,6 @@ void main() finalColor = vec4(color, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * world_pos).xyz); + world_clip_planes_calc_clip_distance(world_pos.xyz); #endif } diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl index 97d4bdacf07..5a3eb38fb6b 100644 --- a/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl +++ b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl @@ -2,8 +2,6 @@ layout(lines_adjacency) in; layout(line_strip, max_vertices = 2) out; -uniform mat4 ProjectionMatrix; - in vec4 pPos[]; in vec3 vPos[]; diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl index 0b5f4733ebc..e34afe95b5e 100644 --- a/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl +++ b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl @@ -1,8 +1,4 @@ -uniform mat4 ModelViewMatrix; -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; - in vec3 pos; out vec4 pPos; @@ -10,12 +6,13 @@ out vec3 vPos; void main() { - vPos = (ModelViewMatrix * vec4(pos, 1.0)).xyz; - pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + vPos = point_world_to_view(world_pos); + pPos = point_world_to_ndc(world_pos); /* Small bias to always be on top of the geom. */ pPos.z -= 1e-3; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl b/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl index e51b829adb5..f98ae9a9515 100644 --- a/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl +++ b/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl @@ -1,6 +1,4 @@ -uniform mat4 ModelViewMatrix; -uniform mat4 ProjectionMatrix; uniform float pixel_size; uniform float size; @@ -12,10 +10,13 @@ flat out float finalVal; void main() { - gl_Position = ModelViewMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); - float psize = (ProjectionMatrix[3][3] == 0.0) ? (size / (-gl_Position.z * pixel_size)) : - (size / pixel_size); + float view_z = dot(ViewMatrixInverse[2].xyz, world_pos - ViewMatrixInverse[3].xyz); + + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + float psize = (is_persp) ? (size / (-view_z * pixel_size)) : (size / pixel_size); + gl_Position = point_world_to_ndc(world_pos); gl_PointSize = psize; @@ -31,7 +32,5 @@ void main() // convert to PointCoord units radii /= psize; - gl_Position = ProjectionMatrix * gl_Position; - finalVal = val; } diff --git a/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl b/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl index 0f626626498..46aceb245f4 100644 --- a/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl +++ b/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl @@ -1,18 +1,17 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ViewProjectionMatrix; -uniform mat4 ModelViewMatrix; -uniform mat4 ProjectionMatrix; -uniform int screen_space; +uniform bool screen_space; uniform float draw_size; uniform vec3 color; uniform sampler1D ramp; +/* ---- Instantiated Attrs ---- */ +in vec3 inst_pos; +in int axis; + +/* ---- Per instance Attrs ---- */ in vec3 pos; in vec4 rot; in float val; -in vec3 inst_pos; -in int axis; flat out vec4 finalColor; @@ -24,8 +23,9 @@ vec3 rotate(vec3 vec, vec4 quat) void main() { - if (screen_space == 1) { - gl_Position = ModelViewMatrix * vec4(pos, 1.0) + vec4(inst_pos * draw_size, 0.0); + if (screen_space) { + gl_Position = ViewMatrix * (ModelMatrix * vec4(pos, 1.0)); + gl_Position.xyz += inst_pos * draw_size; gl_Position = ProjectionMatrix * gl_Position; } else { @@ -35,7 +35,8 @@ void main() size *= 2; } - gl_Position = ModelViewProjectionMatrix * vec4(pos + rotate(inst_pos * size, rot), 1.0); + vec3 pos_rot = pos + rotate(inst_pos * size, rot); + gl_Position = point_object_to_ndc(pos_rot); } #ifdef USE_AXIS diff --git a/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl index 659e3cbd5f5..2dd84c0a060 100644 --- a/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl +++ b/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl @@ -1,13 +1,12 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; in vec3 pos; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl index 96acba71233..23f64e6e49c 100644 --- a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl +++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl @@ -1,9 +1,4 @@ -uniform mat4 ProjectionMatrix; -uniform mat4 ModelViewMatrix; -uniform mat4 ModelMatrix; -uniform mat3 NormalMatrix; - uniform float wireStepParam; uniform float ofs; @@ -11,57 +6,41 @@ in vec3 pos; in vec3 nor; in float wd; /* wiredata */ -#ifndef USE_SCULPT float get_edge_sharpness(float wd) { +#ifndef USE_SCULPT return ((wd == 0.0) ? -1.5 : wd) + wireStepParam; -} #else -float get_edge_sharpness(float wd) -{ return 1.0; -} #endif +} /* Geometry shader version */ #if defined(SELECT_EDGES) || defined(USE_GEOM) out float facing_g; out float edgeSharpness_g; -void main() -{ - edgeSharpness_g = get_edge_sharpness(wd); - - mat4 projmat = ProjectionMatrix; - projmat[3][2] -= ofs; - - gl_Position = projmat * (ModelViewMatrix * vec4(pos, 1.0)); - - facing_g = normalize(NormalMatrix * nor).z; - -# ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); -# endif -} - #else /* USE_GEOM */ out float facing; flat out float edgeSharpness; +# define facing_g facing +# define edgeSharpness_g edgeSharpness + +#endif /* SELECT_EDGES */ void main() { - edgeSharpness = get_edge_sharpness(wd); - mat4 projmat = ProjectionMatrix; projmat[3][2] -= ofs; - gl_Position = projmat * (ModelViewMatrix * vec4(pos, 1.0)); + vec4 wpos = ModelMatrix * vec4(pos, 1.0); + gl_Position = projmat * (ViewMatrix * wpos); - facing = normalize(NormalMatrix * nor).z; + vec3 wnor = normalize(normal_object_to_world(nor)); + facing_g = dot(wnor, ViewMatrixInverse[2].xyz); + edgeSharpness_g = get_edge_sharpness(wd); -# ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); -# endif +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance(wpos.xyz); +#endif } - -#endif /* SELECT_EDGES */ diff --git a/source/blender/draw/modes/shaders/paint_face_vert.glsl b/source/blender/draw/modes/shaders/paint_face_vert.glsl index 59b88d8d3a7..4b5191ead07 100644 --- a/source/blender/draw/modes/shaders/paint_face_vert.glsl +++ b/source/blender/draw/modes/shaders/paint_face_vert.glsl @@ -1,20 +1,19 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; - in vec3 pos; in vec4 nor; /* select flag on the 4th component */ void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); + /* Don't draw faces that are selected. */ if (nor.w > 0.0) { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); } else { #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } } diff --git a/source/blender/draw/modes/shaders/paint_texture_frag.glsl b/source/blender/draw/modes/shaders/paint_texture_frag.glsl index c7e110122c5..4a3c5cb430c 100644 --- a/source/blender/draw/modes/shaders/paint_texture_frag.glsl +++ b/source/blender/draw/modes/shaders/paint_texture_frag.glsl @@ -16,6 +16,27 @@ uniform vec3 maskingColor; uniform bool maskingInvertStencil; #endif +float linearrgb_to_srgb(float c) +{ + if (c < 0.0031308) { + return (c < 0.0) ? 0.0 : c * 12.92; + } + else { + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; + } +} + +vec4 texture_read_as_srgb(sampler2D tex, vec2 co) +{ + /* By convention image textures return scene linear colors, but + * overlays still assume srgb. */ + vec4 color = texture(tex, co); + color.r = linearrgb_to_srgb(color.r); + color.g = linearrgb_to_srgb(color.g); + color.b = linearrgb_to_srgb(color.b); + return color; +} + void main() { vec2 uv = uv_interp; @@ -24,7 +45,7 @@ void main() uv = (floor(uv_interp * tex_size) + 0.5) / tex_size; } - vec4 color = texture(image, uv); + vec4 color = texture_read_as_srgb(image, uv); color.a *= alpha; #ifdef TEXTURE_PAINT_MASK diff --git a/source/blender/draw/modes/shaders/paint_texture_vert.glsl b/source/blender/draw/modes/shaders/paint_texture_vert.glsl index 03d933b9196..564f988348e 100644 --- a/source/blender/draw/modes/shaders/paint_texture_vert.glsl +++ b/source/blender/draw/modes/shaders/paint_texture_vert.glsl @@ -1,7 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; - in vec2 u; /* active uv map */ in vec3 pos; @@ -17,7 +14,8 @@ out vec2 masking_uv_interp; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); uv_interp = u; @@ -26,6 +24,6 @@ void main() #endif #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/paint_vertex_vert.glsl b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl index 54f6d1a4aea..53e72cc8a20 100644 --- a/source/blender/draw/modes/shaders/paint_vertex_vert.glsl +++ b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl @@ -1,7 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; - in vec3 pos; in vec3 c; /* active color */ @@ -17,11 +14,12 @@ vec3 srgb_to_linear_attr(vec3 c) void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); finalColor = srgb_to_linear_attr(c); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/paint_weight_vert.glsl b/source/blender/draw/modes/shaders/paint_weight_vert.glsl index e95b116df79..330cc7d19f4 100644 --- a/source/blender/draw/modes/shaders/paint_weight_vert.glsl +++ b/source/blender/draw/modes/shaders/paint_weight_vert.glsl @@ -1,7 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; - in float weight; in vec3 pos; @@ -9,12 +6,13 @@ out vec2 weight_interp; /* (weight, alert) */ void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); /* Separate actual weight and alerts for independent interpolation */ weight_interp = max(vec2(weight, -weight), 0.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/paint_wire_vert.glsl b/source/blender/draw/modes/shaders/paint_wire_vert.glsl index a163fd7e8b3..10bf8729f47 100644 --- a/source/blender/draw/modes/shaders/paint_wire_vert.glsl +++ b/source/blender/draw/modes/shaders/paint_wire_vert.glsl @@ -1,7 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; -uniform mat4 ModelMatrix; - in vec3 pos; in vec4 nor; /* flag stored in w */ @@ -16,7 +13,8 @@ void main() bool is_select = false; bool is_hidden = false; #endif - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); /* Add offset in Z to avoid zfighting and render selected wires on top. */ /* TODO scale this bias using znear and zfar range. */ gl_Position.z -= (is_select ? 2e-4 : 1e-4); @@ -46,6 +44,6 @@ void main() finalColor.a = nor.w; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/draw/modes/shaders/particle_strand_frag.glsl b/source/blender/draw/modes/shaders/particle_strand_frag.glsl index 578a4935b37..49d843b7e0e 100644 --- a/source/blender/draw/modes/shaders/particle_strand_frag.glsl +++ b/source/blender/draw/modes/shaders/particle_strand_frag.glsl @@ -1,4 +1,3 @@ -uniform mat4 ModelViewProjectionMatrix; in vec4 finalColor; #ifdef USE_POINTS diff --git a/source/blender/draw/modes/shaders/particle_strand_vert.glsl b/source/blender/draw/modes/shaders/particle_strand_vert.glsl index 6dac6d6b980..c3f8fb89c17 100644 --- a/source/blender/draw/modes/shaders/particle_strand_vert.glsl +++ b/source/blender/draw/modes/shaders/particle_strand_vert.glsl @@ -1,6 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; - in vec3 pos; in float color; @@ -47,7 +45,8 @@ vec3 weight_to_rgb(float weight) void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); #ifdef USE_WEIGHT finalColor = vec4(weight_to_rgb(color), 1.0); diff --git a/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl b/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl index e5e34fee57e..7b026836690 100644 --- a/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl +++ b/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl @@ -1,5 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; uniform float maskOpacity; in vec3 pos; @@ -9,7 +8,8 @@ out vec4 finalColor; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); float mask = 1.0 - (msk * maskOpacity); finalColor = vec4(mask, mask, mask, 1.0); diff --git a/source/blender/draw/modes/shaders/volume_velocity_vert.glsl b/source/blender/draw/modes/shaders/volume_velocity_vert.glsl index 32207afa0b1..e96a789b8b1 100644 --- a/source/blender/draw/modes/shaders/volume_velocity_vert.glsl +++ b/source/blender/draw/modes/shaders/volume_velocity_vert.glsl @@ -1,6 +1,4 @@ -uniform mat4 ModelViewProjectionMatrix; - uniform sampler3D velocityX; uniform sampler3D velocityY; uniform sampler3D velocityZ; @@ -109,5 +107,6 @@ void main() pos += (((gl_VertexID % 2) == 1) ? velocity : vec3(0.0)) * displaySize * voxel_size; #endif - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); } diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt index 978bd772b6f..ce6778a1ff9 100644 --- a/source/blender/editors/animation/CMakeLists.txt +++ b/source/blender/editors/animation/CMakeLists.txt @@ -51,6 +51,7 @@ set(SRC keyframes_general.c keyframing.c keyingsets.c + time_scrub_ui.c anim_intern.h ) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 6d1ee08d5e9..00025112835 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -485,16 +485,10 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name) { if (name) { - BLI_strncpy(name, IFACE_("Dope Sheet Summary"), ANIM_CHAN_NAME_SIZE); + BLI_strncpy(name, IFACE_("Summary"), ANIM_CHAN_NAME_SIZE); } } -// FIXME: this is really a temp icon I think -static int acf_summary_icon(bAnimListElem *UNUSED(ale)) -{ - return ICON_BORDERMOVE; -} - /* check if some setting exists for this channel */ static bool acf_summary_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), @@ -557,7 +551,7 @@ static bAnimChannelType ACF_SUMMARY = { acf_summary_name, /* name */ NULL, /* name prop */ - acf_summary_icon, /* icon */ + NULL, /* icon */ acf_summary_setting_valid, /* has setting */ acf_summary_setting_flag, /* flag for setting */ diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index adc6ec3f6be..9e09fc485a6 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -55,6 +55,7 @@ #include "DEG_depsgraph_build.h" #include "UI_view2d.h" +#include "UI_interface.h" #include "ED_anim_api.h" #include "ED_armature.h" @@ -2542,7 +2543,7 @@ static void box_select_anim_channels(bAnimContext *ac, rcti *rect, short selectm float ymax; if (ac->datatype == ANIMCONT_NLA) { - ymax = NLACHANNEL_FIRST_TOP(snla); + ymax = NLACHANNEL_FIRST_TOP(ac); } else { ymax = ACHANNEL_FIRST_TOP(ac); @@ -2735,7 +2736,7 @@ static int animchannels_channel_get(bAnimContext *ac, const int mval[2]) UI_view2d_listview_view_to_cell(NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, - NLACHANNEL_FIRST_TOP(snla), + NLACHANNEL_FIRST_TOP(ac), x, y, NULL, diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index b94d0e3ada7..a228d819286 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1823,7 +1823,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, } /* outliner restrict-flag */ - if (ob->restrictflag & OB_RESTRICT_VIEW) { + if (ob->restrictflag & OB_RESTRICT_VIEWPORT) { continue; } } @@ -3022,7 +3022,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m } /* outliner restrict-flag */ - if (ob->restrictflag & OB_RESTRICT_VIEW) { + if (ob->restrictflag & OB_RESTRICT_VIEWPORT) { return false; } } diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 66cdae07a36..876bc9ae3e4 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -481,7 +481,9 @@ static void draw_markers_background(rctf *rect) uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - const unsigned char shade[4] = {0, 0, 0, 16}; + unsigned char shade[4]; + UI_GetThemeColor4ubv(TH_SCRUBBING_BACKGROUND, shade); + immUniformColor4ubv(shade); GPU_blend(true); diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 97ba7132c3d..45bb8f3b11e 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -52,9 +52,6 @@ #include "ED_sequencer.h" #include "ED_util.h" -#include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" - #include "anim_intern.h" /* ********************** frame change operator ***************************/ @@ -91,6 +88,7 @@ static bool change_frame_poll(bContext *C) /* Set the new frame number */ static void change_frame_apply(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); float frame = RNA_float_get(op->ptr, "frame"); bool do_snap = RNA_boolean_get(op->ptr, "snap"); @@ -116,7 +114,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) FRAMENUMBER_MIN_CLAMP(CFRA); /* do updates */ - BKE_sound_update_and_seek(CTX_data_main(C), CTX_data_depsgraph(C)); + BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 2a8702802aa..fe079eb59a0 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -1249,7 +1249,8 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op) UI_context_update_anim_flag(C); DEG_relations_tag_update(CTX_data_main(C)); - DEG_id_tag_update(ptr.id.data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + + DEG_id_tag_update(ptr.id.data, ID_RECALC_ANIMATION); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); // XXX diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index a0433b49b16..97d85d25d66 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1307,8 +1307,8 @@ static bool insert_keyframe_fcurve_value(Main *bmain, * - if we're replacing keyframes only, DO NOT create new F-Curves if they do not exist yet * but still try to get the F-Curve if it exists... */ - FCurve *fcu = verify_fcurve( - bmain, act, group, ptr, rna_path, array_index, (flag & INSERTKEY_REPLACE) == 0); + bool can_create_curve = (flag & (INSERTKEY_REPLACE | INSERTKEY_AVAILABLE)) == 0; + FCurve *fcu = verify_fcurve(bmain, act, group, ptr, rna_path, array_index, can_create_curve); /* we may not have a F-Curve when we're replacing only... */ if (fcu) { @@ -1432,7 +1432,7 @@ short insert_keyframe(Main *bmain, /* Key the entire array. */ if (array_index == -1 || force_all) { /* In force mode, if any of the curves succeeds, drop the replace mode and restart. */ - if (force_all && (flag & INSERTKEY_REPLACE) != 0) { + if (force_all && (flag & (INSERTKEY_REPLACE | INSERTKEY_AVAILABLE)) != 0) { int exclude = -1; for (array_index = 0; array_index < value_count; array_index++) { @@ -1455,7 +1455,7 @@ short insert_keyframe(Main *bmain, } if (exclude != -1) { - flag &= ~INSERTKEY_REPLACE; + flag &= ~(INSERTKEY_REPLACE | INSERTKEY_AVAILABLE); for (array_index = 0; array_index < value_count; array_index++) { if (array_index != exclude) { diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c new file mode 100644 index 00000000000..37e7eab74d4 --- /dev/null +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -0,0 +1,214 @@ +/* + * 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) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup edanimation + */ + +#include "BKE_context.h" + +#include "GPU_immediate.h" +#include "GPU_matrix.h" +#include "GPU_state.h" + +#include "ED_time_scrub_ui.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" +#include "UI_interface_icons.h" +#include "UI_view2d.h" +#include "UI_resources.h" + +#include "DNA_scene_types.h" + +#include "BLI_rect.h" +#include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_timecode.h" + +#include "RNA_access.h" + +static void get_scrubbing_region_rect(const ARegion *ar, rcti *rect) +{ + rect->xmin = 0; + rect->xmax = ar->winx; + rect->ymax = ar->winy; + rect->ymin = rect->ymax - UI_SCRUBBING_MARGIN_Y; +} + +static int get_centered_text_y(const rcti *rect) +{ + return BLI_rcti_cent_y(rect) - UI_DPI_FAC * 4; +} + +static void draw_background(const rcti *rect) +{ + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + immUniformThemeColor(TH_SCRUBBING_BACKGROUND); + + GPU_blend(true); + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + + immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + + GPU_blend(false); + + immUnbindProgram(); +} + +static void get_current_time_str( + const Scene *scene, bool display_seconds, int frame, uint max_len, char *r_str) +{ + if (display_seconds) { + BLI_timecode_string_from_time(r_str, max_len, 0, FRA2TIME(frame), FPS, U.timecode_style); + } + else { + BLI_snprintf(r_str, max_len, "%d", frame); + } +} + +static void draw_current_frame(const Scene *scene, + bool display_seconds, + const View2D *v2d, + const rcti *scrubbing_region_rect, + int current_frame) +{ + const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; + const unsigned char color[] = {255, 255, 255, 255}; + int frame_x = UI_view2d_view_to_region_x(v2d, current_frame); + + char frame_str[64]; + get_current_time_str(scene, display_seconds, current_frame, sizeof(frame_str), frame_str); + float text_width = UI_fontstyle_string_width(fstyle, frame_str); + float box_width = MAX2(text_width + 8 * UI_DPI_FAC, 24 * UI_DPI_FAC); + float box_padding = 3 * UI_DPI_FAC; + + float bg_color[4]; + UI_GetThemeColorShade4fv(TH_CFRAME, -5, bg_color); + + UI_draw_roundbox_corner_set(UI_CNR_ALL); + + UI_draw_roundbox_3fvAlpha(true, + frame_x - box_width / 2 + U.pixelsize / 2, + scrubbing_region_rect->ymin + box_padding, + frame_x + box_width / 2 + U.pixelsize / 2, + scrubbing_region_rect->ymax - box_padding, + 4 * UI_DPI_FAC, + bg_color, + 1.0f); + + UI_GetThemeColorShade4fv(TH_CFRAME, 5, bg_color); + UI_draw_roundbox_aa(false, + frame_x - box_width / 2 + U.pixelsize / 2, + scrubbing_region_rect->ymin + box_padding, + frame_x + box_width / 2 + U.pixelsize / 2, + scrubbing_region_rect->ymax - box_padding, + 4 * UI_DPI_FAC, + bg_color); + + UI_fontstyle_draw_simple(fstyle, + frame_x - text_width / 2 + U.pixelsize / 2, + get_centered_text_y(scrubbing_region_rect), + frame_str, + color); +} + +void ED_scrubbing_draw(const ARegion *ar, + const Scene *scene, + bool display_seconds, + bool discrete_frames) +{ + const View2D *v2d = &ar->v2d; + + GPU_matrix_push_projection(); + wmOrtho2_region_pixelspace(ar); + + rcti scrubbing_region_rect; + get_scrubbing_region_rect(ar, &scrubbing_region_rect); + + draw_background(&scrubbing_region_rect); + + rcti numbers_rect = scrubbing_region_rect; + numbers_rect.ymin = get_centered_text_y(&scrubbing_region_rect) - 4 * UI_DPI_FAC; + if (discrete_frames) { + UI_view2d_draw_scale_x__discrete_frames_or_seconds( + ar, v2d, &numbers_rect, scene, display_seconds, TH_TEXT); + } + else { + UI_view2d_draw_scale_x__frames_or_seconds( + ar, v2d, &numbers_rect, scene, display_seconds, TH_TEXT); + } + + draw_current_frame(scene, display_seconds, v2d, &scrubbing_region_rect, scene->r.cfra); + + GPU_matrix_pop_projection(); +} + +bool ED_event_in_scrubbing_region(const ARegion *ar, const wmEvent *event) +{ + rcti rect = ar->winrct; + rect.ymin = rect.ymax - UI_SCRUBBING_MARGIN_Y; + return BLI_rcti_isect_pt(&rect, event->x, event->y); +} + +void ED_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopesheet) +{ + GPU_matrix_push_projection(); + wmOrtho2_region_pixelspace(ar); + + rcti rect; + rect.xmin = 0; + rect.xmax = ceilf(ar->sizex * UI_DPI_FAC); + rect.ymin = ar->sizey * UI_DPI_FAC - UI_SCRUBBING_MARGIN_Y; + rect.ymax = ceilf(ar->sizey * UI_DPI_FAC); + + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_BACK); + immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + immUnbindProgram(); + + uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); + + PointerRNA ptr; + RNA_pointer_create(&CTX_wm_screen(C)->id, &RNA_DopeSheet, dopesheet, &ptr); + PropertyRNA *prop = RNA_struct_find_property(&ptr, "filter_text"); + + int padding = 2 * UI_DPI_FAC; + uiDefAutoButR(block, + &ptr, + prop, + -1, + "", + ICON_NONE, + rect.xmin + padding, + rect.ymin + padding, + BLI_rcti_size_x(&rect) - 2 * padding, + BLI_rcti_size_y(&rect) - 2 * padding); + + UI_block_end(C, block); + UI_block_draw(C, block); + + GPU_matrix_pop_projection(); +} diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index 6c2d9fe8f42..569eb7e2e04 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -210,6 +210,8 @@ void POSELIB_OT_apply_pose(struct wmOperatorType *ot); void POSE_OT_push(struct wmOperatorType *ot); void POSE_OT_relax(struct wmOperatorType *ot); +void POSE_OT_push_rest(struct wmOperatorType *ot); +void POSE_OT_relax_rest(struct wmOperatorType *ot); void POSE_OT_breakdown(struct wmOperatorType *ot); void POSE_OT_propagate(struct wmOperatorType *ot); diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index 083967d5d41..9a1582679a4 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -180,7 +180,17 @@ void ED_armature_bone_rename(Main *bmain, if (bone) { unique_bone_name(arm, newname); + + if (arm->bonehash) { + BLI_assert(BLI_ghash_haskey(arm->bonehash, bone->name)); + BLI_ghash_remove(arm->bonehash, bone->name, NULL, NULL); + } + BLI_strncpy(bone->name, newname, MAXBONENAME); + + if (arm->bonehash) { + BLI_ghash_insert(arm->bonehash, bone->name, bone); + } } else { return; diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index b53ae813f10..a29d0f5f158 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -146,6 +146,8 @@ void ED_operatortypes_armature(void) /* POSE SLIDING */ WM_operatortype_append(POSE_OT_push); WM_operatortype_append(POSE_OT_relax); + WM_operatortype_append(POSE_OT_push_rest); + WM_operatortype_append(POSE_OT_relax_rest); WM_operatortype_append(POSE_OT_breakdown); } diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index b2ca1d84520..2c61818d902 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -66,10 +66,16 @@ /* *************************************** Join *************************************** */ /* NOTE: no operator define here as this is exported to the Object-level operator */ -static void joined_armature_fix_links_constraints( - Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone, ListBase *lb) +static void joined_armature_fix_links_constraints(Main *bmain, + Object *ob, + Object *tarArm, + Object *srcArm, + bPoseChannel *pchan, + EditBone *curbone, + ListBase *lb) { bConstraint *con; + bool changed = false; for (con = lb->first; con; con = con->next) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); @@ -84,10 +90,12 @@ static void joined_armature_fix_links_constraints( if (ct->tar == srcArm) { if (ct->subtarget[0] == '\0') { ct->tar = tarArm; + changed = true; } else if (STREQ(ct->subtarget, pchan->name)) { ct->tar = tarArm; BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget)); + changed = true; } } } @@ -104,13 +112,21 @@ static void joined_armature_fix_links_constraints( if (data->act) { BKE_action_fix_paths_rename( &tarArm->id, data->act, "pose.bones[", pchan->name, curbone->name, 0, 0, false); + + DEG_id_tag_update_ex(bmain, &data->act->id, ID_RECALC_COPY_ON_WRITE); } } } + + if (changed) { + DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE); + } } /* userdata for joined_armature_fix_animdata_cb() */ typedef struct tJoinArmature_AdtFixData { + Main *bmain; + Object *srcArm; Object *tarArm; @@ -129,6 +145,7 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data ID *dst_id = &afd->tarArm->id; GHashIterator gh_iter; + bool changed = false; /* Fix paths - If this is the target object, it will have some "dirty" paths */ if ((id == src_id) && strstr(fcu->rna_path, "pose.bones[")) { @@ -142,6 +159,8 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data fcu->rna_path = BKE_animsys_fix_rna_path_rename( id, fcu->rna_path, "pose.bones", old_name, new_name, 0, 0, false); + changed = true; + /* we don't want to apply a second remapping on this driver now, * so stop trying names, but keep fixing drivers */ @@ -163,6 +182,8 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data if (dtar->id == src_id) { dtar->id = dst_id; + changed = true; + /* also check on the subtarget... * XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own * little twists so that we know that it isn't going to clobber the wrong data @@ -193,6 +214,10 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data DRIVER_TARGETS_LOOPER_END; } } + + if (changed) { + DEG_id_tag_update_ex(afd->bmain, id, ID_RECALC_COPY_ON_WRITE); + } } /* Helper function for armature joining - link fixing */ @@ -210,13 +235,14 @@ static void joined_armature_fix_links( pose = ob->pose; for (pchant = pose->chanbase.first; pchant; pchant = pchant->next) { joined_armature_fix_links_constraints( - tarArm, srcArm, pchan, curbone, &pchant->constraints); + bmain, ob, tarArm, srcArm, pchan, curbone, &pchant->constraints); } } /* fix object-level constraints */ if (ob != srcArm) { - joined_armature_fix_links_constraints(tarArm, srcArm, pchan, curbone, &ob->constraints); + joined_armature_fix_links_constraints( + bmain, ob, tarArm, srcArm, pchan, curbone, &ob->constraints); } /* See if an object is parented to this armature */ @@ -231,6 +257,8 @@ static void joined_armature_fix_links( /* make tar armature be new parent */ ob->parent = tarArm; + + DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE); } } } @@ -286,6 +314,7 @@ int join_armature_exec(bContext *C, wmOperator *op) BLI_assert(ob_active->data != ob_iter->data); /* init callback data for fixing up AnimData links later */ + afd.bmain = bmain; afd.srcArm = ob_iter; afd.tarArm = ob_active; afd.names_map = BLI_ghash_str_new("join_armature_adt_fix"); diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index fbbb68d2003..23ddf77e63d 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -70,7 +70,7 @@ Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases, EditBone *ebone = NULL; /* TODO(campbell): optimize, eg: sort & binary search. */ for (uint base_index = 0; base_index < bases_len; base_index++) { - if (bases[base_index]->object->select_id == hit_object) { + if (bases[base_index]->object->runtime.select_id == hit_object) { base = bases[base_index]; break; } @@ -94,7 +94,7 @@ Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects, EditBone *ebone = NULL; /* TODO(campbell): optimize, eg: sort & binary search. */ for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - if (objects[ob_index]->select_id == hit_object) { + if (objects[ob_index]->runtime.select_id == hit_object) { ob = objects[ob_index]; break; } @@ -118,7 +118,7 @@ Base *ED_armature_base_and_bone_from_select_buffer(Base **bases, Bone *bone = NULL; /* TODO(campbell): optimize, eg: sort & binary search. */ for (uint base_index = 0; base_index < bases_len; base_index++) { - if (bases[base_index]->object->select_id == hit_object) { + if (bases[base_index]->object->runtime.select_id == hit_object) { base = bases[base_index]; break; } @@ -300,6 +300,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv const bool sel = !RNA_boolean_get(op->ptr, "deselect"); view3d_operator_needs_opengl(C); + BKE_object_update_select_id(CTX_data_main(C)); Base *base = NULL; bone = get_nearest_bone(C, event->mval, true, &base); @@ -1817,6 +1818,7 @@ static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const Base *base_dst = NULL; view3d_operator_needs_opengl(C); + BKE_object_update_select_id(CTX_data_main(C)); ebone_src = arm->act_edbone; ebone_dst = get_nearest_bone(C, event->mval, false, &base_dst); diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index b23081cd6fa..20dc7b6c826 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -650,6 +650,7 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm) Object *obt; /* armature bones */ + BKE_armature_bone_hash_free(arm); BKE_armature_bonelist_free(&arm->bonebase); arm->act_bone = NULL; @@ -754,6 +755,8 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm) /* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */ armature_finalize_restpose(&arm->bonebase, arm->edbo); + BKE_armature_bone_hash_make(arm); + /* so all users of this armature should get rebuilt */ for (obt = bmain->objects.first; obt; obt = obt->id.next) { if (obt->data == arm) { diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index d683c599f7b..9bc204c9e3b 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -134,6 +134,8 @@ typedef enum ePoseSlide_Modes { POSESLIDE_PUSH = 0, /* exaggerate the pose... */ POSESLIDE_RELAX, /* soften the pose... */ POSESLIDE_BREAKDOWN, /* slide between the endpoint poses, finding a 'soft' spot */ + POSESLIDE_PUSH_REST, + POSESLIDE_RELAX_REST, } ePoseSlide_Modes; /* Transforms/Channels to Affect */ @@ -627,6 +629,103 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) MEM_freeN(path); } +static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], float default_value) +{ + /* We only slide to the rest pose. So only use the default rest pose value */ + const int lock = pso->axislock; + for (int idx = 0; idx < 3; idx++) { + if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) || + ((lock & PS_LOCK_Z) && (idx == 2))) { + float diff_val = default_value - vec[idx]; + if (pso->mode == POSESLIDE_RELAX_REST) { + vec[idx] += pso->percentage * diff_val; + } + else { + /* Push */ + vec[idx] -= pso->percentage * diff_val; + } + } + } +} + +static void pose_slide_rest_pose_apply_other_rot(tPoseSlideOp *pso, float vec[4], bool quat) +{ + /* We only slide to the rest pose. So only use the default rest pose value */ + float default_values[] = {1.0f, 0.0f, 0.0f, 0.0f}; + if (!quat) { + /* Axis Angle */ + default_values[0] = 0.0f; + default_values[2] = 1.0f; + } + for (int idx = 0; idx < 4; idx++) { + float diff_val = default_values[idx] - vec[idx]; + if (pso->mode == POSESLIDE_RELAX_REST) { + vec[idx] += pso->percentage * diff_val; + } + else { + /* Push */ + vec[idx] -= pso->percentage * diff_val; + } + } +} + +/* apply() - perform the pose sliding between the current pose and the rest pose */ +static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso) +{ + tPChanFCurveLink *pfl; + + /* for each link, handle each set of transforms */ + for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) { + /* valid transforms for each PoseChannel should have been noted already + * - sliding the pose should be a straightforward exercise for location+rotation, + * but rotations get more complicated since we may want to use quaternion blending + * for quaternions instead... + */ + bPoseChannel *pchan = pfl->pchan; + + if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) { + /* calculate these for the 'location' vector, and use location curves */ + pose_slide_rest_pose_apply_vec3(pso, pchan->loc, 0.0f); + } + + if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) { + /* calculate these for the 'scale' vector, and use scale curves */ + pose_slide_rest_pose_apply_vec3(pso, pchan->size, 1.0f); + } + + if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) { + /* everything depends on the rotation mode */ + if (pchan->rotmode > 0) { + /* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */ + pose_slide_rest_pose_apply_vec3(pso, pchan->eul, 0.0f); + } + else if (pchan->rotmode == ROT_MODE_AXISANGLE) { + pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, false); + } + else { + /* quaternions - use quaternion blending */ + pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, true); + } + } + + if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) { + /* bbone properties - they all start a "bbone_" prefix */ + // TODO Not implemented + // pose_slide_apply_props(pso, pfl, "bbone_"); + } + + if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) { + /* Not strictly a transform, but custom properties contribute + * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */ + // TODO Not implemented + // pose_slide_apply_props(pso, pfl, "[\""); /* dummy " for texteditor bugs */ + } + } + + /* depsgraph updates + redraws */ + pose_slide_refresh(C, pso); +} + /* apply() - perform the pose sliding based on weighting various poses */ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) { @@ -888,7 +987,12 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p /* initial apply for operator... */ /* TODO: need to calculate percentage for initial round too... */ - pose_slide_apply(C, pso); + if (pso->mode != POSESLIDE_PUSH_REST && pso->mode != POSESLIDE_RELAX_REST) { + pose_slide_apply(C, pso); + } + else { + pose_slide_rest_pose_apply(C, pso); + } /* depsgraph updates + redraws */ pose_slide_refresh(C, pso); @@ -1122,7 +1226,12 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) pose_slide_reset(pso); /* apply... */ - pose_slide_apply(C, pso); + if (pso->mode != POSESLIDE_PUSH_REST && pso->mode != POSESLIDE_RELAX_REST) { + pose_slide_apply(C, pso); + } + else { + pose_slide_rest_pose_apply(C, pso); + } } /* still running... */ @@ -1140,7 +1249,12 @@ static void pose_slide_cancel(bContext *UNUSED(C), wmOperator *op) static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso) { /* settings should have been set up ok for applying, so just apply! */ - pose_slide_apply(C, pso); + if (pso->mode != POSESLIDE_PUSH_REST && pso->mode != POSESLIDE_RELAX_REST) { + pose_slide_apply(C, pso); + } + else { + pose_slide_rest_pose_apply(C, pso); + } /* insert keyframes if needed */ pose_slide_autoKeyframe(C, pso); @@ -1200,7 +1314,7 @@ static void pose_slide_opdef_properties(wmOperatorType *ot) /* ------------------------------------ */ -/* invoke() - for 'push' mode */ +/* invoke() - for 'push from breakdown' mode */ static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso; @@ -1242,9 +1356,9 @@ static int pose_slide_push_exec(bContext *C, wmOperator *op) void POSE_OT_push(wmOperatorType *ot) { /* identifiers */ - ot->name = "Push Pose"; + ot->name = "Push Pose from Breakdown"; ot->idname = "POSE_OT_push"; - ot->description = "Exaggerate the current pose"; + ot->description = "Exaggerate the current pose in regards to the breakdown pose"; /* callbacks */ ot->exec = pose_slide_push_exec; @@ -1262,7 +1376,7 @@ void POSE_OT_push(wmOperatorType *ot) /* ........................ */ -/* invoke() - for 'relax' mode */ +/* invoke() - for 'relax to breakdown' mode */ static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso; @@ -1304,9 +1418,9 @@ static int pose_slide_relax_exec(bContext *C, wmOperator *op) void POSE_OT_relax(wmOperatorType *ot) { /* identifiers */ - ot->name = "Relax Pose"; + ot->name = "Relax Pose to Breakdown"; ot->idname = "POSE_OT_relax"; - ot->description = "Make the current pose more similar to its surrounding ones"; + ot->description = "Make the current pose more similar to its breakdown pose"; /* callbacks */ ot->exec = pose_slide_relax_exec; @@ -1323,6 +1437,129 @@ void POSE_OT_relax(wmOperatorType *ot) } /* ........................ */ +/* invoke() - for 'push from rest pose' mode */ +static int pose_slide_push_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + tPoseSlideOp *pso; + + /* initialize data */ + if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) { + pose_slide_exit(op); + return OPERATOR_CANCELLED; + } + else { + pso = op->customdata; + } + + /* initialise percentage so that it won't pop on first mouse move */ + pose_slide_mouse_update_percentage(pso, op, event); + + /* do common setup work */ + return pose_slide_invoke_common(C, op, pso); +} + +/* exec() - for push */ +static int pose_slide_push_rest_exec(bContext *C, wmOperator *op) +{ + tPoseSlideOp *pso; + + /* initialize data (from RNA-props) */ + if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) { + pose_slide_exit(op); + return OPERATOR_CANCELLED; + } + else { + pso = op->customdata; + } + + /* do common exec work */ + return pose_slide_exec_common(C, op, pso); +} + +void POSE_OT_push_rest(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Push Pose from Rest Pose"; + ot->idname = "POSE_OT_push_rest"; + ot->description = "Push the current pose further away from the rest pose"; + + /* callbacks */ + ot->exec = pose_slide_push_rest_exec; + ot->invoke = pose_slide_push_rest_invoke; + ot->modal = pose_slide_modal; + ot->cancel = pose_slide_cancel; + ot->poll = ED_operator_posemode; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_USE_EVAL_DATA; + + /* Properties */ + pose_slide_opdef_properties(ot); +} + +/* ........................ */ + +/* invoke() - for 'relax' mode */ +static int pose_slide_relax_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + tPoseSlideOp *pso; + + /* initialize data */ + if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) { + pose_slide_exit(op); + return OPERATOR_CANCELLED; + } + else { + pso = op->customdata; + } + + /* initialise percentage so that it won't pop on first mouse move */ + pose_slide_mouse_update_percentage(pso, op, event); + + /* do common setup work */ + return pose_slide_invoke_common(C, op, pso); +} + +/* exec() - for relax */ +static int pose_slide_relax_rest_exec(bContext *C, wmOperator *op) +{ + tPoseSlideOp *pso; + + /* initialize data (from RNA-props) */ + if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) { + pose_slide_exit(op); + return OPERATOR_CANCELLED; + } + else { + pso = op->customdata; + } + + /* do common exec work */ + return pose_slide_exec_common(C, op, pso); +} + +void POSE_OT_relax_rest(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Relax Pose to Rest Pose"; + ot->idname = "POSE_OT_relax_rest"; + ot->description = "Make the current pose more similar to the rest pose"; + + /* callbacks */ + ot->exec = pose_slide_relax_rest_exec; + ot->invoke = pose_slide_relax_rest_invoke; + ot->modal = pose_slide_modal; + ot->cancel = pose_slide_cancel; + ot->poll = ED_operator_posemode; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_USE_EVAL_DATA; + + /* Properties */ + pose_slide_opdef_properties(ot); +} + +/* ........................ */ /* invoke() - for 'breakdown' mode */ static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event) diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 6207d5412cf..49b66429515 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -59,6 +59,9 @@ #include "ED_screen.h" #include "ED_util.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "armature_intern.h" /* ********************************************** */ @@ -87,6 +90,229 @@ static void applyarmature_fix_boneparents(const bContext *C, Scene *scene, Objec } } +/* Sets the bone head, tail and roll to match the supplied parameters. */ +static void applyarmature_set_edit_position(EditBone *curbone, + const float pose_mat[4][4], + const float new_tail[3], + float r_new_arm_mat[4][4]) +{ + /* Simply copy the head/tail values from pchan over to curbone. */ + copy_v3_v3(curbone->head, pose_mat[3]); + copy_v3_v3(curbone->tail, new_tail); + + /* Fix roll: + * 1. find auto-calculated roll value for this bone now + * 2. remove this from the 'visual' y-rotation + */ + { + float premat[3][3], pmat[3][3]; + float delta[3]; + + /* Obtain new auto y-rotation. */ + sub_v3_v3v3(delta, curbone->tail, curbone->head); + + copy_m3_m4(pmat, pose_mat); + mat3_vec_to_roll(pmat, delta, &curbone->roll); + + /* Compute new rest pose matrix if requested. */ + if (r_new_arm_mat) { + vec_roll_to_mat3(delta, curbone->roll, premat); + copy_m4_m3(r_new_arm_mat, premat); + copy_v3_v3(r_new_arm_mat[3], pose_mat[3]); + } + } +} + +/* Copy properties over from pchan to curbone and reset channels. */ +static void applyarmature_transfer_properties(EditBone *curbone, + bPoseChannel *pchan, + const bPoseChannel *pchan_eval) +{ + /* Combine pose and rest values for bendy bone settings, + * then clear the pchan values (so we don't get a double-up). + */ + if (pchan->bone->segments > 1) { + /* Combine rest/pose values. */ + curbone->curve_in_x += pchan_eval->curve_in_x; + curbone->curve_in_y += pchan_eval->curve_in_y; + curbone->curve_out_x += pchan_eval->curve_out_x; + curbone->curve_out_y += pchan_eval->curve_out_y; + curbone->roll1 += pchan_eval->roll1; + curbone->roll2 += pchan_eval->roll2; + curbone->ease1 += pchan_eval->ease1; + curbone->ease2 += pchan_eval->ease2; + + curbone->scale_in_x *= pchan_eval->scale_in_x; + curbone->scale_in_y *= pchan_eval->scale_in_y; + curbone->scale_out_x *= pchan_eval->scale_out_x; + curbone->scale_out_y *= pchan_eval->scale_out_y; + + /* Reset pose values. */ + pchan->curve_in_x = pchan->curve_out_x = 0.0f; + pchan->curve_in_y = pchan->curve_out_y = 0.0f; + pchan->roll1 = pchan->roll2 = 0.0f; + pchan->ease1 = pchan->ease2 = 0.0f; + pchan->scale_in_x = pchan->scale_in_y = 1.0f; + pchan->scale_out_x = pchan->scale_out_y = 1.0f; + } + + /* Clear transform values for pchan. */ + zero_v3(pchan->loc); + zero_v3(pchan->eul); + unit_qt(pchan->quat); + unit_axis_angle(pchan->rotAxis, &pchan->rotAngle); + pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f; + + /* Set anim lock. */ + curbone->flag |= BONE_UNKEYED; +} + +/* Adjust the current edit position of the bone using the pose space matrix. */ +static void applyarmature_adjust_edit_position(bArmature *arm, + bPoseChannel *pchan, + const float delta_mat[4][4], + float r_new_arm_mat[4][4]) +{ + EditBone *curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name); + float delta[3], new_tail[3], premat[3][3], new_pose[4][4]; + + /* Current orientation matrix. */ + sub_v3_v3v3(delta, curbone->tail, curbone->head); + vec_roll_to_mat3(delta, curbone->roll, premat); + + /* New location and orientation. */ + mul_m4_m4m3(new_pose, delta_mat, premat); + mul_v3_m4v3(new_pose[3], delta_mat, curbone->head); + mul_v3_m4v3(new_tail, delta_mat, curbone->tail); + + applyarmature_set_edit_position(curbone, new_pose, new_tail, r_new_arm_mat); +} + +/* Data about parent position for Apply To Selected mode. */ +typedef struct ApplyArmature_ParentState { + Bone *bone; + + /* New rest position of the bone with scale included. */ + float new_rest_mat[4][4]; + /* New arm_mat of the bone == new_rest_mat without scale. */ + float new_arm_mat[4][4]; +} ApplyArmature_ParentState; + +/* Recursive walk for Apply To Selected mode; pstate NULL unless child of an applied bone. */ +static void applyarmature_process_selected_rec(bArmature *arm, + bPose *pose, + bPose *pose_eval, + Bone *bone, + ListBase *selected, + ApplyArmature_ParentState *pstate) +{ + bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name); + const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(pose_eval, bone->name); + + if (!pchan || !pchan_eval) + return; + + ApplyArmature_ParentState new_pstate = {.bone = bone}; + + if (BLI_findptr(selected, pchan, offsetof(CollectionPointerLink, ptr.data))) { + /* SELECTED BONE: Snap to final pose transform minus unapplied parent effects. + * + * I.e. bone position with accumulated parent effects but no local + * transformation will match the original final pose_mat. + * + * Pose channels are reset as expected. + */ + EditBone *curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name); + BoneParentTransform invparent; + float new_tail[3]; + + if (pchan->parent) { + BoneParentTransform old_bpt, new_bpt; + float offs_bone[4][4]; + + /* Parent effects on the bone transform that have to be removed. */ + BKE_bone_offset_matrix_get(bone, offs_bone); + BKE_bone_parent_transform_calc_from_matrices( + bone->flag, offs_bone, bone->parent->arm_mat, pchan_eval->parent->pose_mat, &old_bpt); + + /* Applied parent effects that have to be kept, if any. */ + float(*new_parent_pose)[4] = pstate ? pstate->new_rest_mat : bone->parent->arm_mat; + BKE_bone_parent_transform_calc_from_matrices( + bone->flag, offs_bone, bone->parent->arm_mat, new_parent_pose, &new_bpt); + + BKE_bone_parent_transform_invert(&old_bpt); + BKE_bone_parent_transform_combine(&new_bpt, &old_bpt, &invparent); + } + else { + BKE_bone_parent_transform_clear(&invparent); + } + + /* Apply change without inherited unapplied parent transformations. */ + BKE_bone_parent_transform_apply(&invparent, pchan_eval->pose_mat, new_pstate.new_rest_mat); + + copy_v3_fl3(new_tail, 0.0, bone->length, 0.0); + mul_m4_v3(new_pstate.new_rest_mat, new_tail); + + applyarmature_set_edit_position( + curbone, new_pstate.new_rest_mat, new_tail, new_pstate.new_arm_mat); + applyarmature_transfer_properties(curbone, pchan, pchan_eval); + + pstate = &new_pstate; + } + else if (pstate) { + /* UNSELECTED CHILD OF SELECTED: Include applied parent effects. + * + * The inherited transform of applied (selected) bones is baked + * into the rest pose so that the final bone position doesn't + * change. + * + * Pose channels are not changed, with the exception of the inherited + * applied parent scale being baked into the location pose channel. + */ + BoneParentTransform bpt; + float offs_bone[4][4], delta[4][4], old_chan_loc[3]; + + /* Include applied parent effects. */ + BKE_bone_offset_matrix_get(bone, offs_bone); + BKE_bone_parent_transform_calc_from_matrices( + bone->flag, offs_bone, pstate->bone->arm_mat, pstate->new_rest_mat, &bpt); + + unit_m4(new_pstate.new_rest_mat); + BKE_bone_parent_transform_apply(&bpt, new_pstate.new_rest_mat, new_pstate.new_rest_mat); + + /* Bone location channel in pose space relative to bone head. */ + mul_v3_mat3_m4v3(old_chan_loc, bpt.loc_mat, pchan_eval->loc); + + /* Apply the change to the rest bone position. */ + invert_m4_m4(delta, bone->arm_mat); + mul_m4_m4m4(delta, new_pstate.new_rest_mat, delta); + + applyarmature_adjust_edit_position(arm, pchan, delta, new_pstate.new_arm_mat); + + /* Location pose channel has to be updated, because it is affected + * by parent scaling, and the rest pose has no scale by definition. */ + if (!(bone->flag & BONE_CONNECTED) && !is_zero_v3(old_chan_loc)) { + float inv_parent_arm[4][4]; + + /* Compute the channel coordinate space matrices for the new rest state. */ + invert_m4_m4(inv_parent_arm, pstate->new_arm_mat); + mul_m4_m4m4(offs_bone, inv_parent_arm, new_pstate.new_arm_mat); + BKE_bone_parent_transform_calc_from_matrices( + bone->flag, offs_bone, pstate->new_arm_mat, pstate->new_arm_mat, &bpt); + + /* Re-apply the location to keep the final effect. */ + invert_m4(bpt.loc_mat); + mul_v3_mat3_m4v3(pchan->loc, bpt.loc_mat, old_chan_loc); + } + + pstate = &new_pstate; + } + + for (Bone *child = bone->childbase.first; child; child = child->next) { + applyarmature_process_selected_rec(arm, pose, pose_eval, child, selected, pstate); + } +} + /* set the current pose as the restpose */ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) { @@ -99,7 +325,9 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) bArmature *arm = BKE_armature_from_object(ob); bPose *pose; bPoseChannel *pchan; - EditBone *curbone; + ListBase selected_bones; + + const bool use_selected = RNA_boolean_get(op->ptr, "selected"); /* don't check if editmode (should be done by caller) */ if (ob->type != OB_ARMATURE) { @@ -119,80 +347,37 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) "transforms stored are relative to the old rest pose"); } + /* Find selected bones before switching to edit mode. */ + if (use_selected) { + CTX_data_selected_pose_bones(C, &selected_bones); + + if (!selected_bones.first) { + return OPERATOR_CANCELLED; + } + } + /* Get editbones of active armature to alter */ ED_armature_to_edit(arm); /* get pose of active object and move it out of posemode */ pose = ob->pose; - for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name); - curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name); - - /* simply copy the head/tail values from pchan over to curbone */ - copy_v3_v3(curbone->head, pchan_eval->pose_head); - copy_v3_v3(curbone->tail, pchan_eval->pose_tail); - - /* fix roll: - * 1. find auto-calculated roll value for this bone now - * 2. remove this from the 'visual' y-rotation - */ - { - float premat[3][3], imat[3][3], pmat[3][3], tmat[3][3]; - float delta[3], eul[3]; - - /* obtain new auto y-rotation */ - sub_v3_v3v3(delta, curbone->tail, curbone->head); - vec_roll_to_mat3(delta, 0.0f, premat); - invert_m3_m3(imat, premat); - - /* get pchan 'visual' matrix */ - copy_m3_m4(pmat, pchan_eval->pose_mat); - - /* remove auto from visual and get euler rotation */ - mul_m3_m3m3(tmat, imat, pmat); - mat3_to_eul(eul, tmat); - - /* just use this euler-y as new roll value */ - curbone->roll = eul[1]; + if (use_selected) { + /* The selected only mode requires a recursive walk to handle parent-child relations. */ + for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) { + applyarmature_process_selected_rec(arm, pose, ob_eval->pose, bone, &selected_bones, NULL); } - /* combine pose and rest values for bendy bone settings, - * then clear the pchan values (so we don't get a double-up) - */ - if (pchan->bone->segments > 1) { - /* combine rest/pose values */ - curbone->curve_in_x += pchan_eval->curve_in_x; - curbone->curve_in_y += pchan_eval->curve_in_y; - curbone->curve_out_x += pchan_eval->curve_out_x; - curbone->curve_out_y += pchan_eval->curve_out_y; - curbone->roll1 += pchan_eval->roll1; - curbone->roll2 += pchan_eval->roll2; - curbone->ease1 += pchan_eval->ease1; - curbone->ease2 += pchan_eval->ease2; - curbone->scale_in_x *= pchan_eval->scale_in_x; - curbone->scale_in_y *= pchan_eval->scale_in_y; - curbone->scale_out_x *= pchan_eval->scale_out_x; - curbone->scale_out_y *= pchan_eval->scale_out_y; - - /* reset pose values */ - pchan->curve_in_x = pchan->curve_out_x = 0.0f; - pchan->curve_in_y = pchan->curve_out_y = 0.0f; - pchan->roll1 = pchan->roll2 = 0.0f; - pchan->ease1 = pchan->ease2 = 0.0f; - pchan->scale_in_x = pchan->scale_in_y = 1.0f; - pchan->scale_out_x = pchan->scale_out_y = 1.0f; - } - - /* clear transform values for pchan */ - zero_v3(pchan->loc); - zero_v3(pchan->eul); - unit_qt(pchan->quat); - unit_axis_angle(pchan->rotAxis, &pchan->rotAngle); - pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f; + BLI_freelistN(&selected_bones); + } + else { + for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name); + EditBone *curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name); - /* set anim lock */ - curbone->flag |= BONE_UNKEYED; + applyarmature_set_edit_position(curbone, pchan_eval->pose_mat, pchan_eval->pose_tail, NULL); + applyarmature_transfer_properties(curbone, pchan, pchan_eval); + } } /* convert editbones back to bones, and then free the edit-data */ @@ -212,6 +397,17 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static void apply_armature_pose2bones_ui(bContext *C, wmOperator *op) +{ + uiLayout *layout = op->layout; + wmWindowManager *wm = CTX_wm_manager(C); + PointerRNA ptr; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + uiItemR(layout, &ptr, "selected", 0, NULL, ICON_NONE); +} + void POSE_OT_armature_apply(wmOperatorType *ot) { /* identifiers */ @@ -222,9 +418,16 @@ void POSE_OT_armature_apply(wmOperatorType *ot) /* callbacks */ ot->exec = apply_armature_pose2bones_exec; ot->poll = ED_operator_posemode; + ot->ui = apply_armature_pose2bones_ui; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; + + RNA_def_boolean(ot->srna, + "selected", + false, + "Selected Only", + "Only apply the selected bones (with propagation to children)"); } /* set the current pose as the restpose */ diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index a787b45c13c..65f502d5cd2 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -5551,6 +5551,8 @@ static int add_vertex_exec(bContext *C, wmOperator *op) } WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + DEG_id_tag_update(obedit->data, 0); return OPERATOR_FINISHED; diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 463c2144276..9ef0657ae83 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -314,7 +314,7 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op) BKE_paint_ensure(ts, (Paint **)&ts->gp_paint); Paint *paint = &ts->gp_paint->paint; /* if not exist, create a new one */ - if (paint->brush == NULL) { + if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) { BKE_brush_gpencil_presets(C); } BKE_paint_toolslots_brush_validate(bmain, &ts->gp_paint->paint); diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c index 9d3c2a6e271..93d8555e014 100644 --- a/source/blender/editors/gpencil/gpencil_merge.c +++ b/source/blender/editors/gpencil/gpencil_merge.c @@ -110,7 +110,7 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo Paint *paint = &ts->gp_paint->paint; /* if not exist, create a new one */ - if (paint->brush == NULL) { + if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) { /* create new brushes */ BKE_brush_gpencil_presets(C); } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index b1b29356060..cd1ebc91fbb 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1819,7 +1819,7 @@ static void gp_init_drawing_brush(bContext *C, tGPsdata *p) Paint *paint = &ts->gp_paint->paint; bool changed = false; /* if not exist, create a new one */ - if (paint->brush == NULL) { + if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) { /* create new brushes */ BKE_brush_gpencil_presets(C); changed = true; diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 08fee2bb393..bff17bf5078 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -314,7 +314,7 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) /* if brush doesn't exist, create a new one */ Paint *paint = &ts->gp_paint->paint; /* if not exist, create a new one */ - if (paint->brush == NULL) { + if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) { /* create new brushes */ BKE_brush_gpencil_presets(C); } diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 129bd01574c..93a80f0fcf8 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -1387,7 +1387,7 @@ void ED_gpencil_add_defaults(bContext *C, Object *ob) BKE_paint_ensure(ts, (Paint **)&ts->gp_paint); Paint *paint = &ts->gp_paint->paint; /* if not exist, create a new one */ - if (paint->brush == NULL) { + if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) { /* create new brushes */ BKE_brush_gpencil_presets(C); } diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 6342a8b26d9..cd68981dee3 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -403,7 +403,8 @@ typedef enum eAnimFilter_Flags { /* -------------- Channel Defines -------------- */ /* channel heights */ -#define ACHANNEL_FIRST_TOP(ac) (-0.4f * (ac)->yscale_fac * U.widget_unit) +#define ACHANNEL_FIRST_TOP(ac) \ + (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_SCRUBBING_MARGIN_Y - ACHANNEL_SKIP) #define ACHANNEL_HEIGHT(ac) (0.8f * (ac)->yscale_fac * U.widget_unit) #define ACHANNEL_SKIP (0.1f * U.widget_unit) #define ACHANNEL_STEP(ac) (ACHANNEL_HEIGHT(ac) + ACHANNEL_SKIP) @@ -420,14 +421,15 @@ typedef enum eAnimFilter_Flags { /* -------------- NLA Channel Defines -------------- */ /* NLA channel heights */ -#define NLACHANNEL_FIRST_TOP(snla) (-0.4f * U.widget_unit) +#define NLACHANNEL_FIRST_TOP(ac) \ + (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_SCRUBBING_MARGIN_Y - NLACHANNEL_SKIP) #define NLACHANNEL_HEIGHT(snla) \ ((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? (0.8f * U.widget_unit) : (1.2f * U.widget_unit)) #define NLACHANNEL_SKIP (0.1f * U.widget_unit) #define NLACHANNEL_STEP(snla) (NLACHANNEL_HEIGHT(snla) + NLACHANNEL_SKIP) /* Additional offset to give some room at the end. */ -#define NLACHANNEL_TOT_HEIGHT(snla, item_amount) \ - (-NLACHANNEL_FIRST_TOP(snla) + NLACHANNEL_STEP(snla) * (item_amount + 1)) +#define NLACHANNEL_TOT_HEIGHT(ac, item_amount) \ + (-NLACHANNEL_FIRST_TOP(ac) + NLACHANNEL_STEP(((SpaceNla *)(ac)->sl)) * (item_amount + 1)) /* channel widths */ #define NLACHANNEL_NAMEWIDTH (10 * U.widget_unit) diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index ce8521a1f6a..c6d25e6f988 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -163,7 +163,10 @@ bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc, float *r_dist, const bool use_select_bias, - bool use_cycle); + bool use_cycle, + struct Base **bases, + uint bases_len, + uint *r_base_index); struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, float *r_dist); struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc, @@ -171,7 +174,10 @@ struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc, float *r_dist_center, const bool use_select_bias, const bool use_cycle, - struct BMEdge **r_eed_zbuf); + struct BMEdge **r_eed_zbuf, + struct Base **bases, + uint bases_len, + uint *r_base_index); struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *r_dist); struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc, @@ -179,7 +185,10 @@ struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc, float *r_dist_center, const bool use_select_bias, const bool use_cycle, - struct BMFace **r_efa_zbuf); + struct BMFace **r_efa_zbuf, + struct Base **bases, + uint bases_len, + uint *r_base_index); struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *r_dist); bool EDBM_unified_findnearest(struct ViewContext *vc, @@ -230,6 +239,7 @@ void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* rename bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len); bool EDBM_mesh_deselect_all_multi(struct bContext *C); +/* Only use for modes that don't support multi-edit-modes (painting). */ extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs; /* editmesh_preselect_edgering.c */ diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 264eb6abdf1..a7a95a4a659 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -87,9 +87,12 @@ void ED_region_panels_ex(const struct bContext *C, void ED_region_panels(const struct bContext *C, struct ARegion *ar); void ED_region_panels_layout_ex(const struct bContext *C, struct ARegion *ar, + struct ListBase *paneltypes, const char *contexts[], int contextnr, - const bool vertical); + const bool vertical, + const char *category_override); + void ED_region_panels_layout(const struct bContext *C, struct ARegion *ar); void ED_region_panels_draw(const struct bContext *C, struct ARegion *ar); @@ -440,8 +443,9 @@ enum { ED_KEYMAP_ANIMATION = (1 << 6), ED_KEYMAP_FRAMES = (1 << 7), ED_KEYMAP_HEADER = (1 << 8), - ED_KEYMAP_GPENCIL = (1 << 9), - ED_KEYMAP_FOOTER = (1 << 10), + ED_KEYMAP_FOOTER = (1 << 9), + ED_KEYMAP_GPENCIL = (1 << 10), + ED_KEYMAP_NAVBAR = (1 << 11), }; /* SCREEN_OT_space_context_cycle direction */ diff --git a/source/blender/editors/include/ED_time_scrub_ui.h b/source/blender/editors/include/ED_time_scrub_ui.h new file mode 100644 index 00000000000..a2e3098e949 --- /dev/null +++ b/source/blender/editors/include/ED_time_scrub_ui.h @@ -0,0 +1,43 @@ +/* + * 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) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup editors + */ + +#ifndef __ED_SCRUBBING_H__ +#define __ED_SCRUBBING_H__ + +struct View2DGrid; +struct bContext; +struct bDopeSheet; +struct wmEvent; + +void ED_scrubbing_draw(const struct ARegion *ar, + const struct Scene *scene, + bool display_seconds, + bool discrete_frames); + +bool ED_event_in_scrubbing_region(const struct ARegion *ar, const struct wmEvent *event); + +void ED_channel_search_draw(const struct bContext *C, + struct ARegion *ar, + struct bDopeSheet *dopesheet); + +#endif /* __ED_SCRUBBING_H__ */ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index fd51419a3ee..3503d38ad92 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -730,4 +730,9 @@ void ED_view3d_gizmo_mesh_preselect_get_active(struct bContext *C, struct Base **r_base, struct BMElem **r_ele); +/* space_view3d.c */ +void ED_view3d_buttons_region_layout_ex(const struct bContext *C, + struct ARegion *ar, + const char *category_override); + #endif /* __ED_VIEW3D_H__ */ diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index b4d345a3344..9ee9e952856 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -24,6 +24,9 @@ /* Note: this is included multiple times with different #defines for DEF_ICON. */ /* Auto define more specific types for places that do not need the distinction. */ +#ifndef DEF_ICON_SCENE +# define DEF_ICON_SCENE DEF_ICON +#endif #ifndef DEF_ICON_COLLECTION # define DEF_ICON_COLLECTION DEF_ICON #endif @@ -133,8 +136,8 @@ DEF_ICON_SHADING(MATERIAL) DEF_ICON_SHADING(TEXTURE) DEF_ICON(ANIM) DEF_ICON_SHADING(WORLD) -DEF_ICON(SCENE) -DEF_ICON(OUTPUT) +DEF_ICON_SCENE(SCENE) +DEF_ICON_SCENE(OUTPUT) DEF_ICON_BLANK(145) DEF_ICON_BLANK(146) DEF_ICON(SCRIPT) @@ -142,7 +145,7 @@ DEF_ICON_MODIFIER(PARTICLES) DEF_ICON_MODIFIER(PHYSICS) DEF_ICON_OBJECT_DATA(SPEAKER) DEF_ICON_BLANK(151) -DEF_ICON(TOOL_SETTINGS) +DEF_ICON_SCENE(TOOL_SETTINGS) DEF_ICON_MODIFIER(SHADERFX) DEF_ICON_MODIFIER(MODIFIER) DEF_ICON_BLANK(155) @@ -211,8 +214,8 @@ DEF_ICON(TRACKING_REFINE_FORWARDS) DEF_ICON_BLANK(77b) /* DATA */ -DEF_ICON(SCENE_DATA) -DEF_ICON(RENDERLAYERS) +DEF_ICON_SCENE(SCENE_DATA) +DEF_ICON_SCENE(RENDERLAYERS) DEF_ICON_SHADING(WORLD_DATA) DEF_ICON_OBJECT(OBJECT_DATA) DEF_ICON_OBJECT_DATA(MESH_DATA) @@ -243,8 +246,8 @@ DEF_ICON_SHADING(BRUSH_DATA) DEF_ICON_SHADING(IMAGE_DATA) DEF_ICON(FILE) DEF_ICON(FCURVE) -DEF_ICON(FONT_DATA) -DEF_ICON(RENDER_RESULT) +DEF_ICON_OBJECT_DATA(FONT_DATA) +DEF_ICON_SCENE(RENDER_RESULT) DEF_ICON_OBJECT_DATA(SURFACE_DATA) DEF_ICON_OBJECT_DATA(EMPTY_DATA) DEF_ICON(PRESET) @@ -320,7 +323,7 @@ DEF_ICON(RESTRICT_SELECT_ON) DEF_ICON(RESTRICT_SELECT_OFF) DEF_ICON(RESTRICT_RENDER_ON) DEF_ICON(RESTRICT_RENDER_OFF) -DEF_ICON_BLANK(330) +DEF_ICON(RESTRICT_INSTANCED_OFF) /* OUTLINER */ DEF_ICON_OBJECT_DATA(OUTLINER_DATA_EMPTY) @@ -334,7 +337,7 @@ DEF_ICON_OBJECT_DATA(OUTLINER_DATA_ARMATURE) DEF_ICON_OBJECT_DATA(OUTLINER_DATA_FONT) DEF_ICON_OBJECT_DATA(OUTLINER_DATA_SURFACE) DEF_ICON_OBJECT_DATA(OUTLINER_DATA_SPEAKER) -DEF_ICON_BLANK(344) +DEF_ICON_OBJECT_DATA(OUTLINER_DATA_LIGHTPROBE) DEF_ICON_BLANK(345) DEF_ICON_OBJECT_DATA(OUTLINER_DATA_GREASEPENCIL) DEF_ICON(GP_SELECT_POINTS) @@ -348,7 +351,7 @@ DEF_ICON(ONIONSKIN_OFF) DEF_ICON(ONIONSKIN_ON) DEF_ICON(RESTRICT_VIEW_ON) DEF_ICON(RESTRICT_VIEW_OFF) -DEF_ICON_BLANK(353) +DEF_ICON(RESTRICT_INSTANCED_ON) /* PRIMITIVES */ DEF_ICON(MESH_PLANE) @@ -456,11 +459,11 @@ DEF_ICON_BLANK(707) DEF_ICON_BLANK(708) DEF_ICON_BLANK(709) DEF_ICON_BLANK(710) -DEF_ICON_BLANK(711) -DEF_ICON_BLANK(712) -DEF_ICON_BLANK(713) -DEF_ICON_BLANK(714) -DEF_ICON_BLANK(715) +DEF_ICON(SELECT_SET) +DEF_ICON(SELECT_EXTEND) +DEF_ICON(SELECT_SUBTRACT) +DEF_ICON(SELECT_INTERSECT) +DEF_ICON(SELECT_DIFFERENCE) /* EMPTY */ DEF_ICON(ALIGN_LEFT) @@ -708,7 +711,7 @@ DEF_ICON_BLANK(240) DEF_ICON_BLANK(241) DEF_ICON_BLANK(242) DEF_ICON_BLANK(243) -DEF_ICON_BLANK(244) +DEF_ICON(GIZMO) DEF_ICON(ORIENTATION_CURSOR) DEF_ICON(NORMALS_VERTEX) DEF_ICON(NORMALS_FACE) @@ -1022,6 +1025,7 @@ DEF_ICON_COLOR(EVENT_RETURN) #undef DEF_ICON #undef DEF_ICON_ERROR +#undef DEF_ICON_SCENE #undef DEF_ICON_COLLECTION #undef DEF_ICON_OBJECT #undef DEF_ICON_OBJECT_DATA diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 18960853011..14d681ee817 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -228,6 +228,7 @@ enum { #define UI_PANEL_WIDTH 340 #define UI_COMPACT_PANEL_WIDTH 160 +#define UI_SIDEBAR_PANEL_WIDTH 220 #define UI_NAVIGATION_REGION_WIDTH UI_COMPACT_PANEL_WIDTH #define UI_NARROW_NAVIGATION_REGION_WIDTH 100 @@ -594,9 +595,16 @@ struct uiLayout *UI_pie_menu_layout(struct uiPieMenu *pie); typedef uiBlock *(*uiBlockCreateFunc)(struct bContext *C, struct ARegion *ar, void *arg1); typedef void (*uiBlockCancelFunc)(struct bContext *C, void *arg1); -void UI_popup_block_invoke(struct bContext *C, uiBlockCreateFunc func, void *arg); -void UI_popup_block_invoke_ex( - struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext); +void UI_popup_block_invoke(struct bContext *C, + uiBlockCreateFunc func, + void *arg, + void (*arg_free)(void *arg)); +void UI_popup_block_invoke_ex(struct bContext *C, + uiBlockCreateFunc func, + void *arg, + void (*arg_free)(void *arg), + const char *opname, + int opcontext); void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, @@ -641,6 +649,7 @@ enum { UI_BLOCK_THEME_STYLE_POPUP = 1, }; void UI_block_theme_style_set(uiBlock *block, char theme_style); +char UI_block_emboss_get(uiBlock *block); void UI_block_emboss_set(uiBlock *block, char dt); void UI_block_free(const struct bContext *C, uiBlock *block); diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index 5666421c27f..1f15fa3bd4d 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -52,8 +52,11 @@ typedef struct IconFile { * Resizable Icons for Blender */ void UI_icons_init(void); +void UI_icons_reload_internal_textures(void); + int UI_icon_get_width(int icon_id); int UI_icon_get_height(int icon_id); +bool UI_icon_get_theme_color(int icon_id, unsigned char color[4]); void UI_id_icon_render(const struct bContext *C, struct Scene *scene, @@ -64,16 +67,17 @@ int UI_preview_render_size(enum eIconSizes size); void UI_icon_draw(float x, float y, int icon_id); void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha); -void UI_icon_draw_preview(float x, float y, int icon_id); -void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect); -void UI_icon_draw_preview_aspect_size( - float x, float y, int icon_id, float aspect, float alpha, int size); - -void UI_icon_draw_aspect( - float x, float y, int icon_id, float aspect, float alpha, const char mono_color[4]); -void UI_icon_draw_aspect_color( - float x, float y, int icon_id, float aspect, const float rgb[3], const char mono_color[4]); -void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha); +void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size); + +void UI_icon_draw_ex(float x, + float y, + int icon_id, + float aspect, + float alpha, + float desaturate, + const char mono_color[4], + const bool mono_border); + void UI_icon_draw_desaturate(float x, float y, int icon_id, @@ -81,6 +85,7 @@ void UI_icon_draw_desaturate(float x, float alpha, float desaturate, const char mono_color[4]); + void UI_icons_free(void); void UI_icons_free_drawinfo(void *drawinfo); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index af94889a1bb..7abc27c5b37 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -105,6 +105,7 @@ typedef enum ThemeColorID { TH_FACE_DOT, TH_FACEDOT_SIZE, TH_CFRAME, + TH_SCRUBBING_BACKGROUND, TH_TIME_KEYFRAME, TH_TIME_GP_KEYFRAME, TH_NURB_ULINE, @@ -261,12 +262,15 @@ typedef enum ThemeColorID { TH_ANIM_INACTIVE, /* no active action */ TH_ANIM_PREVIEW_RANGE, /* preview range overlay */ + TH_ICON_SCENE, TH_ICON_COLLECTION, TH_ICON_OBJECT, TH_ICON_OBJECT_DATA, TH_ICON_MODIFIER, TH_ICON_SHADING, + TH_SCROLL_TEXT, + TH_NLA_TWEAK, /* 'tweaking' track in NLA */ TH_NLA_TWEAK_DUPLI, /* error/warning flag for other strips referencing dupli strip */ @@ -380,7 +384,7 @@ void UI_GetThemeColorType3ubv(int colorid, int spacetype, unsigned char col[3]); void UI_GetThemeColorType4ubv(int colorid, int spacetype, unsigned char col[4]); // get theme color for coloring monochrome icons -bool UI_GetIconThemeColor4fv(int colorid, float col[4]); +bool UI_GetIconThemeColor4ubv(int colorid, unsigned char col[4]); // shade a 3 byte color (same as UI_GetColorPtrBlendShade3ubv with 0.0 factor) void UI_GetColorPtrShade3ubv(const unsigned char cp1[3], unsigned char col[3], int offset); diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 064951d40ed..d03d4b1b4f5 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -63,9 +63,9 @@ enum eView2D_CommonViewTypes { /* scroller area */ #define V2D_SCROLL_HEIGHT (0.45f * U.widget_unit) #define V2D_SCROLL_WIDTH (0.45f * U.widget_unit) -/* For scrollers with scale markings (text written onto them) */ -#define V2D_SCROLL_HEIGHT_TEXT (0.79f * U.widget_unit) -#define V2D_SCROLL_WIDTH_TEXT (0.79f * U.widget_unit) +/* For scrollers with scale handlers */ +#define V2D_SCROLL_HEIGHT_HANDLES (0.6f * U.widget_unit) +#define V2D_SCROLL_WIDTH_HANDLES (0.6f * U.widget_unit) /* scroller 'handles' hotspot radius for mouse */ #define V2D_SCROLLER_HANDLE_SIZE (0.6f * U.widget_unit) @@ -258,6 +258,8 @@ void UI_view2d_smooth_view(struct bContext *C, struct ARegion *ar, const struct rctf *cur, const int smooth_viewtx); + #define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC) +#define UI_SCRUBBING_MARGIN_Y (23 * UI_DPI_FAC) #endif /* __UI_VIEW2D_H__ */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 42f4b4495c3..7c60ac75df8 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -3235,6 +3235,11 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh return block; } +char UI_block_emboss_get(uiBlock *block) +{ + return block->dt; +} + void UI_block_emboss_set(uiBlock *block, char dt) { block->dt = dt; diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index b9de504f3b2..e34d67b6996 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -82,6 +82,11 @@ void ui_but_anim_flag(uiBut *but, float cfra) if (fcu) { if (!driven) { + /* Empty curves are ignored by the animation evaluation system. */ + if (fcu->totvert == 0) { + return; + } + but->flag |= UI_BUT_ANIMATED; /* T41525 - When the active action is a NLA strip being edited, diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 748d6e6c183..0055349d4be 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -58,30 +58,90 @@ /** \name Button Context Menu * \{ */ -static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) +static IDProperty *shortcut_property_from_rna(bContext *C, uiBut *but) { - uiBut *but = (uiBut *)arg1; + /* Compute data path from context to property. */ + const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin); + const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin); + const char *member_id_data_path = member_id; + + if (data_path) { + member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path); + MEM_freeN((void *)data_path); + } - if (but->optype) { - char shortcut_str[128]; + const char *prop_id = RNA_property_identifier(but->rnaprop); + const char *final_data_path = BLI_sprintfN("%s.%s", member_id_data_path, prop_id); - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + if (member_id != member_id_data_path) { + MEM_freeN((void *)member_id_data_path); + } + + /* Create ID property of data path, to pass to the operator. */ + IDProperty *prop; + IDPropertyTemplate val = {0}; + prop = IDP_New(IDP_GROUP, &val, __func__); + IDP_AddToGroup(prop, IDP_NewString(final_data_path, "data_path", strlen(final_data_path) + 1)); + + MEM_freeN((void *)final_data_path); + + return prop; +} - /* complex code to change name of button */ - if (WM_key_event_operator_string(C, - but->optype->idname, - but->opcontext, - prop, - true, - shortcut_str, - sizeof(shortcut_str))) { - ui_but_add_shortcut(but, shortcut_str, true); +static const char *shortcut_get_operator_property(bContext *C, uiBut *but, IDProperty **prop) +{ + if (but->optype) { + /* Operator */ + *prop = (but->opptr) ? IDP_CopyProperty(but->opptr->data) : NULL; + return but->optype->idname; + } + else if (but->rnaprop) { + if (RNA_property_type(but->rnaprop) == PROP_BOOLEAN) { + /* Boolean */ + *prop = shortcut_property_from_rna(C, but); + return "WM_OT_context_toggle"; } - else { - /* simply strip the shortcut */ - ui_but_add_shortcut(but, NULL, true); + else if (RNA_property_type(but->rnaprop) == PROP_ENUM) { + /* Enum */ + *prop = shortcut_property_from_rna(C, but); + return "WM_OT_context_menu_enum"; } } + + *prop = NULL; + return NULL; +} + +static void shortcut_free_operator_property(IDProperty *prop) +{ + if (prop) { + IDP_FreeProperty(prop); + MEM_freeN(prop); + } +} + +static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) +{ + uiBut *but = (uiBut *)arg1; + char shortcut_str[128]; + + IDProperty *prop; + const char *idname = shortcut_get_operator_property(C, but, &prop); + if (idname == NULL) { + return; + } + + /* complex code to change name of button */ + if (WM_key_event_operator_string( + C, idname, but->opcontext, prop, true, shortcut_str, sizeof(shortcut_str))) { + ui_but_add_shortcut(but, shortcut_str, true); + } + else { + /* simply strip the shortcut */ + ui_but_add_shortcut(but, NULL, true); + } + + shortcut_free_operator_property(prop); } static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) @@ -94,15 +154,18 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) PointerRNA ptr; uiLayout *layout; uiStyle *style = UI_style_get_dpi(); - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + IDProperty *prop; + const char *idname = shortcut_get_operator_property(C, but, &prop); kmi = WM_key_event_operator(C, - but->optype->idname, + idname, but->opcontext, prop, EVT_TYPE_MASK_HOTKEY_INCLUDE, EVT_TYPE_MASK_HOTKEY_EXCLUDE, &km); + U.runtime.is_dirty = true; + BLI_assert(kmi != NULL); RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); @@ -118,6 +181,8 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) UI_block_bounds_set_popup(block, 6, (const int[2]){-50, 26}); + shortcut_free_operator_property(prop); + return block; } @@ -135,25 +200,24 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) PointerRNA ptr; uiLayout *layout; uiStyle *style = UI_style_get_dpi(); - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; int kmi_id; + IDProperty *prop; + const char *idname = shortcut_get_operator_property(C, but, &prop); /* XXX this guess_opname can potentially return a different keymap * than being found on adding later... */ - km = WM_keymap_guess_opname(C, but->optype->idname); - kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0); + km = WM_keymap_guess_opname(C, idname); + kmi = WM_keymap_add_item(km, idname, AKEY, KM_PRESS, 0, 0); kmi_id = kmi->id; - /* copy properties, prop can be NULL for reset */ - if (prop) { - prop = IDP_CopyProperty(prop); - } + /* This takes ownership of prop, or prop can be NULL for reset. */ WM_keymap_item_properties_reset(kmi, prop); /* update and get pointers again */ WM_keyconfig_update(wm); + U.runtime.is_dirty = true; - km = WM_keymap_guess_opname(C, but->optype->idname); + km = WM_keymap_guess_opname(C, idname); kmi = WM_keymap_item_find_id(km, kmi_id); RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); @@ -171,6 +235,7 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) #ifdef USE_KEYMAP_ADD_HACK g_kmi_id_hack = kmi_id; #endif + return block; } @@ -179,20 +244,21 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1) uiBut *but = (uiBut *)arg1; wmKeyMap *km; wmKeyMapItem *kmi; -#ifndef USE_KEYMAP_ADD_HACK - IDProperty *prop; -#endif int kmi_id; + IDProperty *prop; + const char *idname = shortcut_get_operator_property(C, but, &prop); + #ifdef USE_KEYMAP_ADD_HACK - km = WM_keymap_guess_opname(C, but->optype->idname); + km = WM_keymap_guess_opname(C, idname); kmi_id = g_kmi_id_hack; UNUSED_VARS(but); #else - prop = (but->opptr) ? but->opptr->data : NULL; - kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km); + kmi_id = WM_key_event_operator_id(C, idname, but->opcontext, prop, true, &km); #endif + shortcut_free_operator_property(prop); + kmi = WM_keymap_item_find_id(km, kmi_id); WM_keymap_remove_item(km, kmi); } @@ -200,7 +266,7 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1) static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) { uiBut *but = (uiBut *)arg1; - UI_popup_block_invoke(C, menu_change_shortcut, but); + UI_popup_block_invoke(C, menu_change_shortcut, but, NULL); } static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) @@ -208,10 +274,11 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) uiBut *but = (uiBut *)arg1; wmKeyMap *km; wmKeyMapItem *kmi; - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + IDProperty *prop; + const char *idname = shortcut_get_operator_property(C, but, &prop); kmi = WM_key_event_operator(C, - but->optype->idname, + idname, but->opcontext, prop, EVT_TYPE_MASK_HOTKEY_INCLUDE, @@ -220,7 +287,9 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) BLI_assert(kmi != NULL); WM_keymap_remove_item(km, kmi); + U.runtime.is_dirty = true; + shortcut_free_operator_property(prop); but_shortcut_name_func(C, but, 0); } @@ -323,6 +392,7 @@ static void popup_user_menu_add_or_replace_func(bContext *C, void *arg1, void *U { uiBut *but = arg1; bUserMenu *um = ED_screen_user_menu_ensure(C); + U.runtime.is_dirty = true; ui_but_user_menu_add(C, but, um); } @@ -330,6 +400,7 @@ static void popup_user_menu_remove_func(bContext *UNUSED(C), void *arg1, void *a { bUserMenu *um = arg1; bUserMenuItem *umi = arg2; + U.runtime.is_dirty = true; ED_screen_user_menu_item_remove(&um->items, umi); } @@ -890,16 +961,18 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) uiItemS(layout); } - /* Operator buttons */ - if (but->optype) { + /* Shortcut menu */ + IDProperty *prop; + const char *idname = shortcut_get_operator_property(C, but, &prop); + if (idname != NULL) { uiBlock *block = uiLayoutGetBlock(layout); uiBut *but2; - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; int w = uiLayoutGetWidth(layout); wmKeyMap *km; + /* We want to know if this op has a shortcut, be it hotkey or not. */ wmKeyMapItem *kmi = WM_key_event_operator( - C, but->optype->idname, but->opcontext, prop, EVT_TYPE_MASK_ALL, 0, &km); + C, idname, but->opcontext, prop, EVT_TYPE_MASK_ALL, 0, &km); /* We do have a shortcut, but only keyboard ones are editable that way... */ if (kmi) { @@ -971,7 +1044,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) } } /* only show 'assign' if there's a suitable key map for it to go in */ - else if (WM_keymap_guess_opname(C, but->optype->idname)) { + else if (WM_keymap_guess_opname(C, idname)) { but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, @@ -990,6 +1063,8 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) UI_but_func_set(but2, popup_add_shortcut_func, but, NULL); } + shortcut_free_operator_property(prop); + /* Set the operator pointer for python access */ uiLayoutSetContextFromBut(layout, but); @@ -1108,6 +1183,9 @@ void ui_popup_context_menu_for_panel(bContext *C, ARegion *ar, Panel *pa) if (!any_item_visible) { return; } + if (pa->type->parent != NULL) { + return; + } RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 111dfe01319..e4adf757c80 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -551,6 +551,32 @@ static bool ui_but_dragedit_update_mval(uiHandleButtonData *data, int mx) return true; } +static void ui_but_update_preferences_dirty(uiBut *but) +{ + /* Not very elegant, but ensures preference changes force re-save. */ + bool tag = false; + if (but->rnaprop) { + if (but->rnapoin.data == &U) { + /* Exclude navigation from setting dirty. */ + extern PropertyRNA rna_Preferences_active_section; + if (!ELEM(but->rnaprop, &rna_Preferences_active_section)) { + tag = true; + } + } + else { + StructRNA *base = RNA_struct_base(but->rnapoin.type); + if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences)) { + tag = true; + } + } + } + + if (tag) { + U.runtime.is_dirty = true; + WM_main_add_notifier(NC_WINDOW, NULL); + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -1334,6 +1360,9 @@ static bool ui_drag_toggle_set_xy_xy( if (do_check) { ui_but_update_edited(but); } + if (U.runtime.is_dirty == false) { + ui_but_update_preferences_dirty(but); + } changed = true; } } @@ -3769,7 +3798,7 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat } if (func || handlefunc) { - data->menu = ui_popup_block_create(C, data->region, but, func, handlefunc, arg); + data->menu = ui_popup_block_create(C, data->region, but, func, handlefunc, arg, NULL); if (but->block->handle) { data->menu->popup = but->block->handle->popup; } @@ -5622,6 +5651,13 @@ static int ui_do_but_UNITVEC( } } } + else if (event->type == ESCKEY || event->type == RIGHTMOUSE) { + if (event->val == KM_PRESS) { + data->cancel = true; + data->escapecancel = true; + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + } else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { button_activate_state(C, but, BUTTON_STATE_EXIT); } @@ -7566,6 +7602,10 @@ static void button_activate_exit( if (block->flag & UI_BLOCK_POPUP_MEMORY) { ui_popup_menu_memory_set(block, but); } + + if (U.runtime.is_dirty == false) { + ui_but_update_preferences_dirty(but); + } } /* disable tooltips until mousemove + last active flag */ diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 7e295f83390..e53e9694617 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -37,6 +37,7 @@ #include "BLI_utildefines.h" #include "BLI_fileops_types.h" #include "BLI_math_vector.h" +#include "BLI_math_color_blend.h" #include "DNA_brush_types.h" #include "DNA_curve_types.h" @@ -83,6 +84,7 @@ # define ICON_GRID_COLS 26 # define ICON_GRID_ROWS 30 +# define ICON_MONO_BORDER_OUTSET 2 # define ICON_GRID_MARGIN 10 # define ICON_GRID_W 32 # define ICON_GRID_H 32 @@ -138,7 +140,8 @@ typedef struct DrawInfo { } DrawInfo; typedef struct IconTexture { - GLuint id; + GLuint id[2]; + int num_textures; int w; int h; float invw; @@ -154,12 +157,13 @@ typedef struct IconType { /* static here to cache results of icon directory scan, so it's not * scanning the filesystem each time the menu is drawn */ static struct ListBase iconfilelist = {NULL, NULL}; -static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f}; +static IconTexture icongltex = {{0, 0}, 0, 0, 0, 0.0f, 0.0f}; #ifndef WITH_HEADLESS static const IconType icontypes[] = { # define DEF_ICON(name) {ICON_TYPE_MONO_TEXTURE, 0}, +# define DEF_ICON_SCENE(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_SCENE}, # define DEF_ICON_COLLECTION(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_COLLECTION}, # define DEF_ICON_OBJECT(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_OBJECT}, # define DEF_ICON_OBJECT_DATA(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_OBJECT_DATA}, @@ -713,38 +717,146 @@ static void icon_verify_datatoc(IconImage *iimg) } } -static void init_internal_icons(void) +static ImBuf *create_mono_icon_with_border(ImBuf *buf, + int resolution_divider, + float border_intensity) { - // bTheme *btheme = UI_GetTheme(); - ImBuf *b16buf = NULL, *b32buf = NULL; - int x, y; + ImBuf *result = IMB_dupImBuf(buf); + const float border_sharpness = 16.0 / (resolution_divider * resolution_divider); -# if 0 // temp disabled - if ((btheme != NULL) && btheme->tui.iconfile[0]) { - char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons"); - char iconfilestr[FILE_MAX]; + float blurred_alpha_buffer[(ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) * + (ICON_GRID_H + 2 * ICON_MONO_BORDER_OUTSET)]; + const int icon_width = (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) / resolution_divider; + const int icon_height = (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) / resolution_divider; - if (icondir) { - BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile); + for (int y = 0; y < ICON_GRID_ROWS; y++) { + for (int x = 0; x < ICON_GRID_COLS; x++) { + IconType icontype = icontypes[y * ICON_GRID_COLS + x]; + if (icontype.type != ICON_TYPE_MONO_TEXTURE) { + continue; + } - /* if the image is missing bbuf will just be NULL */ - bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL); + int sx = x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN - ICON_MONO_BORDER_OUTSET; + int sy = y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN - ICON_MONO_BORDER_OUTSET; + sx = sx / resolution_divider; + sy = sy / resolution_divider; + + /* blur the alpha channel and store it in blurred_alpha_buffer */ + int blur_size = 2 / resolution_divider; + for (int bx = 0; bx < icon_width; bx++) { + const int asx = MAX2(bx - blur_size, 0); + const int aex = MIN2(bx + blur_size + 1, icon_width); + for (int by = 0; by < icon_height; by++) { + const int asy = MAX2(by - blur_size, 0); + const int aey = MIN2(by + blur_size + 1, icon_height); + + // blur alpha channel + const int write_offset = by * (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) + bx; + float alpha_accum = 0.0; + unsigned int alpha_samples = 0; + for (int ax = asx; ax < aex; ax++) { + for (int ay = asy; ay < aey; ay++) { + const int offset_read = (sy + ay) * buf->x + (sx + ax); + unsigned int color_read = buf->rect[offset_read]; + const float alpha_read = ((color_read & 0xff000000) >> 24) / 255.0; + alpha_accum += alpha_read; + alpha_samples += 1; + } + } + blurred_alpha_buffer[write_offset] = alpha_accum / alpha_samples; + } + } - if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) { - printf( - "\n***WARNING***\n" - "Icons file '%s' too small.\n" - "Using built-in Icons instead\n", - iconfilestr); - IMB_freeImBuf(bbuf); - bbuf = NULL; + /* apply blurred alpha */ + for (int bx = 0; bx < icon_width; bx++) { + for (int by = 0; by < icon_height; by++) { + const int blurred_alpha_offset = by * (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) + bx; + const int offset_write = (sy + by) * buf->x + (sx + bx); + const float blurred_alpha = blurred_alpha_buffer[blurred_alpha_offset]; + float border_srgb[4] = { + 0, 0, 0, MIN2(1.0, blurred_alpha * border_sharpness) * border_intensity}; + + const unsigned int color_read = buf->rect[offset_write]; + const unsigned char *orig_color = (unsigned char *)&color_read; + + float border_rgba[4]; + float orig_rgba[4]; + float dest_rgba[4]; + float dest_srgb[4]; + + srgb_to_linearrgb_v4(border_rgba, border_srgb); + srgb_to_linearrgb_uchar4(orig_rgba, orig_color); + blend_color_interpolate_float(dest_rgba, orig_rgba, border_rgba, 1.0 - orig_rgba[3]); + linearrgb_to_srgb_v4(dest_srgb, dest_rgba); + + unsigned int alpha_mask = ((unsigned int)(dest_srgb[3] * 255)) << 24; + unsigned int cpack = rgb_to_cpack(dest_srgb[0], dest_srgb[1], dest_srgb[2]) | alpha_mask; + result->rect[offset_write] = cpack; + } } } - else { - printf("%s: 'icons' data path not found, continuing\n", __func__); + } + return result; +} + +/* Generate the mipmap levels for the icon textures + * During creation the source16 ImBuf will be freed to reduce memory overhead + * A new ImBuf will be returned that needs is owned by the caller. + * + * FIXME: Mipmap levels are generated until the width of the image is 1, which + * are too many levels than that are needed.*/ +static ImBuf *create_mono_icon_mipmaps(ImBuf *source32, ImBuf *source16, int level) +{ + if (level == 0) { + glTexImage2D(GL_TEXTURE_2D, + level, + GL_RGBA8, + source32->x, + source32->y, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + source32->rect); + return create_mono_icon_mipmaps(source32, source16, level + 1); + } + else { + glTexImage2D(GL_TEXTURE_2D, + level, + GL_RGBA8, + source16->x, + source16->y, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + source16->rect); + if (source16->x > 1) { + ImBuf *nbuf = IMB_onehalf(source16); + IMB_freeImBuf(source16); + source16 = create_mono_icon_mipmaps(source32, nbuf, level + 1); } + return source16; } -# endif +} + +static void free_icons_textures(void) +{ + if (icongltex.num_textures > 0) { + glDeleteTextures(icongltex.num_textures, icongltex.id); + icongltex.id[0] = 0; + icongltex.id[1] = 0; + icongltex.num_textures = 0; + } +} + +/* Reload the textures for internal icons. + * This function will release the previous textures. */ +void UI_icons_reload_internal_textures(void) +{ + bTheme *btheme = UI_GetTheme(); + ImBuf *b16buf = NULL, *b32buf = NULL, *b16buf_border = NULL, *b32buf_border = NULL; + const float icon_border_intensity = btheme->tui.icon_border_intensity; + bool need_icons_with_border = icon_border_intensity > 0.0f; + if (b16buf == NULL) { b16buf = IMB_ibImageFromMemory((const uchar *)datatoc_blender_icons16_png, datatoc_blender_icons16_png_size, @@ -753,6 +865,10 @@ static void init_internal_icons(void) "<blender icons>"); } if (b16buf) { + if (need_icons_with_border) { + b16buf_border = create_mono_icon_with_border(b16buf, 2, icon_border_intensity); + IMB_premultiply_alpha(b16buf_border); + } IMB_premultiply_alpha(b16buf); } @@ -764,88 +880,97 @@ static void init_internal_icons(void) "<blender icons>"); } if (b32buf) { + if (need_icons_with_border) { + b32buf_border = create_mono_icon_with_border(b32buf, 1, icon_border_intensity); + IMB_premultiply_alpha(b32buf_border); + } IMB_premultiply_alpha(b32buf); } if (b16buf && b32buf) { /* Free existing texture if any. */ - if (icongltex.id) { - glDeleteTextures(1, &icongltex.id); - icongltex.id = 0; - } + free_icons_textures(); /* Allocate OpenGL texture. */ - glGenTextures(1, &icongltex.id); - - if (icongltex.id) { - int level = 2; + icongltex.num_textures = need_icons_with_border ? 2 : 1; + glGenTextures(icongltex.num_textures, icongltex.id); + if (icongltex.id[0]) { icongltex.w = b32buf->x; icongltex.h = b32buf->y; icongltex.invw = 1.0f / b32buf->x; icongltex.invh = 1.0f / b32buf->y; - glBindTexture(GL_TEXTURE_2D, icongltex.id); - - glTexImage2D(GL_TEXTURE_2D, - 0, - GL_RGBA8, - b32buf->x, - b32buf->y, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - b32buf->rect); - glTexImage2D(GL_TEXTURE_2D, - 1, - GL_RGBA8, - b16buf->x, - b16buf->y, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - b16buf->rect); - - while (b16buf->x > 1) { - ImBuf *nbuf = IMB_onehalf(b16buf); - glTexImage2D(GL_TEXTURE_2D, - level, - GL_RGBA8, - nbuf->x, - nbuf->y, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - nbuf->rect); - level++; - IMB_freeImBuf(b16buf); - b16buf = nbuf; - } - + glBindTexture(GL_TEXTURE_2D, icongltex.id[0]); + b16buf = create_mono_icon_mipmaps(b32buf, b16buf, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + } + if (need_icons_with_border && icongltex.id[1]) { + glBindTexture(GL_TEXTURE_2D, icongltex.id[1]); + b16buf_border = create_mono_icon_mipmaps(b32buf_border, b16buf_border, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); } + } - /* Define icons. */ - for (y = 0; y < ICON_GRID_ROWS; y++) { - /* Row W has monochrome icons. */ - for (x = 0; x < ICON_GRID_COLS; x++) { - IconType icontype = icontypes[y * ICON_GRID_COLS + x]; - if (!ELEM(icontype.type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) { - continue; - } + IMB_freeImBuf(b16buf); + IMB_freeImBuf(b32buf); + IMB_freeImBuf(b16buf_border); + IMB_freeImBuf(b32buf_border); +} + +static void init_internal_icons(void) +{ + int x, y; + +# if 0 // temp disabled + if ((btheme != NULL) && btheme->tui.iconfile[0]) { + char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons"); + char iconfilestr[FILE_MAX]; + + if (icondir) { + BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile); + + /* if the image is missing bbuf will just be NULL */ + bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL); - def_internal_icon(b32buf, - BIFICONID_FIRST + y * ICON_GRID_COLS + x, - x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN, - y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN, - ICON_GRID_W, - icontype.type, - icontype.theme_color); + if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) { + printf( + "\n***WARNING***\n" + "Icons file '%s' too small.\n" + "Using built-in Icons instead\n", + iconfilestr); + IMB_freeImBuf(bbuf); + bbuf = NULL; } } + else { + printf("%s: 'icons' data path not found, continuing\n", __func__); + } + } +# endif + + /* Define icons. */ + for (y = 0; y < ICON_GRID_ROWS; y++) { + /* Row W has monochrome icons. */ + for (x = 0; x < ICON_GRID_COLS; x++) { + IconType icontype = icontypes[y * ICON_GRID_COLS + x]; + if (!ELEM(icontype.type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) { + continue; + } + + def_internal_icon(NULL, + BIFICONID_FIRST + y * ICON_GRID_COLS + x, + x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN, + y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN, + ICON_GRID_W, + icontype.type, + icontype.theme_color); + } } def_internal_vicon(ICON_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw); @@ -882,9 +1007,6 @@ static void init_internal_icons(void) def_internal_vicon(ICON_COLORSET_18_VEC, vicon_colorset_draw_18); def_internal_vicon(ICON_COLORSET_19_VEC, vicon_colorset_draw_19); def_internal_vicon(ICON_COLORSET_20_VEC, vicon_colorset_draw_20); - - IMB_freeImBuf(b16buf); - IMB_freeImBuf(b32buf); } # endif /* WITH_HEADLESS */ @@ -990,11 +1112,7 @@ ListBase *UI_iconfile_list(void) void UI_icons_free(void) { #ifndef WITH_HEADLESS - if (icongltex.id) { - glDeleteTextures(1, &icongltex.id); - icongltex.id = 0; - } - + free_icons_textures(); free_iconfile_list(&iconfilelist); BKE_icons_free(); #endif @@ -1104,10 +1222,22 @@ int UI_icon_get_height(int icon_id) return 0; } +bool UI_icon_get_theme_color(int icon_id, uchar color[4]) +{ + Icon *icon = BKE_icon_get(icon_id); + if (icon == NULL) { + return false; + } + + DrawInfo *di = icon_ensure_drawinfo(icon); + return UI_GetIconThemeColor4ubv(di->data.texture.theme_color, color); +} + void UI_icons_init() { #ifndef WITH_HEADLESS init_iconfile_list(&iconfilelist); + UI_icons_reload_internal_textures(); init_internal_icons(); init_brush_icons(); init_event_icons(); @@ -1348,7 +1478,6 @@ static void icon_draw_rect(float x, int rh, uint *rect, float alpha, - const float rgb[3], const float desaturate) { ImBuf *ima = NULL; @@ -1366,12 +1495,6 @@ static void icon_draw_rect(float x, /* modulate color */ float col[4] = {1.0f, 1.0f, 1.0f, alpha}; - if (rgb) { - col[0] = rgb[0]; - col[1] = rgb[1]; - col[2] = rgb[2]; - } - /* rect contains image in 'rendersize', we only scale if needed */ if (rw != w || rh != h) { /* preserve aspect ratio and center */ @@ -1439,12 +1562,17 @@ typedef struct IconDrawCall { float color[4]; } IconDrawCall; -static struct { +typedef struct IconTextureDrawCall { IconDrawCall drawcall_cache[ICON_DRAW_CACHE_SIZE]; int calls; /* Number of calls batched together */ +} IconTextureDrawCall; + +static struct { + IconTextureDrawCall normal; + IconTextureDrawCall border; bool enabled; float mat[4][4]; -} g_icon_draw_cache = {{{{0}}}}; +} g_icon_draw_cache = {{{{{0}}}}}; void UI_icon_draw_cache_begin(void) { @@ -1452,19 +1580,15 @@ void UI_icon_draw_cache_begin(void) g_icon_draw_cache.enabled = true; } -static void icon_draw_cache_flush_ex(void) +static void icon_draw_cache_texture_flush_ex(GLuint texture, + IconTextureDrawCall *texture_draw_calls) { - if (g_icon_draw_cache.calls == 0) { + if (texture_draw_calls->calls == 0) { return; } - /* We need to flush widget base first to ensure correct ordering. */ - UI_widgetbase_draw_cache_flush(); - - GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, icongltex.id); + glBindTexture(GL_TEXTURE_2D, texture); GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR); GPU_shader_bind(shader); @@ -1473,16 +1597,43 @@ static void icon_draw_cache_flush_ex(void) int data_loc = GPU_shader_get_uniform_ensure(shader, "calls_data[0]"); glUniform1i(img_loc, 0); - glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)g_icon_draw_cache.drawcall_cache); + glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)texture_draw_calls->drawcall_cache); - GPU_draw_primitive(GPU_PRIM_TRIS, 6 * g_icon_draw_cache.calls); + GPU_draw_primitive(GPU_PRIM_TRIS, 6 * texture_draw_calls->calls); glBindTexture(GL_TEXTURE_2D, 0); - g_icon_draw_cache.calls = 0; + texture_draw_calls->calls = 0; +} - GPU_blend_set_func_separate( - GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); +static void icon_draw_cache_flush_ex(bool only_full_caches) +{ + bool should_draw = false; + if (only_full_caches) { + should_draw = g_icon_draw_cache.normal.calls == ICON_DRAW_CACHE_SIZE || + g_icon_draw_cache.border.calls == ICON_DRAW_CACHE_SIZE; + } + else { + should_draw = g_icon_draw_cache.normal.calls || g_icon_draw_cache.border.calls; + } + + if (should_draw) { + /* We need to flush widget base first to ensure correct ordering. */ + UI_widgetbase_draw_cache_flush(); + + GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + + if (!only_full_caches || g_icon_draw_cache.normal.calls == ICON_DRAW_CACHE_SIZE) { + icon_draw_cache_texture_flush_ex(icongltex.id[0], &g_icon_draw_cache.normal); + } + + if (!only_full_caches || g_icon_draw_cache.border.calls == ICON_DRAW_CACHE_SIZE) { + icon_draw_cache_texture_flush_ex(icongltex.id[1], &g_icon_draw_cache.border); + } + + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + } } void UI_icon_draw_cache_end(void) @@ -1491,12 +1642,12 @@ void UI_icon_draw_cache_end(void) g_icon_draw_cache.enabled = false; /* Don't change blend state if it's not needed. */ - if (g_icon_draw_cache.calls == 0) { + if (g_icon_draw_cache.border.calls == 0 && g_icon_draw_cache.normal.calls == 0) { return; } GPU_blend(true); - icon_draw_cache_flush_ex(); + icon_draw_cache_flush_ex(false); GPU_blend(false); } @@ -1509,14 +1660,18 @@ static void icon_draw_texture_cached(float x, int UNUSED(iw), int ih, float alpha, - const float rgb[3]) + const float rgb[3], + bool with_border) { float mvp[4][4]; GPU_matrix_model_view_projection_get(mvp); - IconDrawCall *call = &g_icon_draw_cache.drawcall_cache[g_icon_draw_cache.calls]; - g_icon_draw_cache.calls++; + IconTextureDrawCall *texture_call = with_border ? &g_icon_draw_cache.border : + &g_icon_draw_cache.normal; + + IconDrawCall *call = &texture_call->drawcall_cache[texture_call->calls]; + texture_call->calls++; /* Manual mat4*vec2 */ call->pos.xmin = x * mvp[0][0] + y * mvp[1][0] + mvp[3][0]; @@ -1536,8 +1691,8 @@ static void icon_draw_texture_cached(float x, copy_v4_fl(call->color, alpha); } - if (g_icon_draw_cache.calls == ICON_DRAW_CACHE_SIZE) { - icon_draw_cache_flush_ex(); + if (texture_call->calls == ICON_DRAW_CACHE_SIZE) { + icon_draw_cache_flush_ex(true); } } @@ -1550,10 +1705,11 @@ static void icon_draw_texture(float x, int iw, int ih, float alpha, - const float rgb[3]) + const float rgb[3], + bool with_border) { if (g_icon_draw_cache.enabled) { - icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb); + icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb, with_border); return; } @@ -1570,7 +1726,7 @@ static void icon_draw_texture(float x, y2 = (iy + ih) * icongltex.invh; glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, icongltex.id); + glBindTexture(GL_TEXTURE_2D, with_border ? icongltex.id[1] : icongltex.id[0]); GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR); GPU_shader_bind(shader); @@ -1614,11 +1770,11 @@ static void icon_draw_size(float x, int icon_id, float aspect, float alpha, - const float rgb[3], enum eIconSizes size, int draw_size, const float desaturate, - const char mono_rgba[4]) + const char mono_rgba[4], + const bool mono_border) { bTheme *btheme = UI_GetTheme(); Icon *icon = NULL; @@ -1675,7 +1831,7 @@ static void icon_draw_size(float x, GPU_blend_set_func_separate( GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->rect, alpha, rgb, desaturate); + icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->rect, alpha, desaturate); GPU_blend_set_func_separate( GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); } @@ -1695,36 +1851,42 @@ static void icon_draw_size(float x, di->data.texture.w, di->data.texture.h, alpha, - rgb); + NULL, + false); } else if (di->type == ICON_TYPE_MONO_TEXTURE) { - /* icon that matches text color, assumed to be white */ + /* Monochrome icon that uses text or theme color. */ + bool with_border = mono_border && (btheme->tui.icon_border_intensity > 0.0f); float color[4]; - if (!UI_GetIconThemeColor4fv(di->data.texture.theme_color, color)) { - if (mono_rgba) { - rgba_uchar_to_float(color, (const uchar *)mono_rgba); - } - else { - UI_GetThemeColor4fv(TH_TEXT, color); - } + if (mono_rgba) { + rgba_uchar_to_float(color, (const uchar *)mono_rgba); } - - if (rgb) { - mul_v3_v3(color, rgb); + else { + UI_GetThemeColor4fv(TH_TEXT, color); } mul_v4_fl(color, alpha); - icon_draw_texture(x, - y, - (float)w, - (float)h, - di->data.texture.x, - di->data.texture.y, - di->data.texture.w, - di->data.texture.h, + float border_outset = 0.0; + unsigned int border_texel = 0; +#ifndef WITH_HEADLESS + if (with_border) { + const float scale = (float)ICON_GRID_W / (float)ICON_DEFAULT_WIDTH; + border_texel = ICON_MONO_BORDER_OUTSET; + border_outset = ICON_MONO_BORDER_OUTSET / (scale * aspect); + } +#endif + icon_draw_texture(x - border_outset, + y - border_outset, + (float)w + 2 * border_outset, + (float)h + 2 * border_outset, + di->data.texture.x - border_texel, + di->data.texture.y - border_texel, + di->data.texture.w + 2 * border_texel, + di->data.texture.h + 2 * border_texel, color[3], - color); + color, + with_border); } else if (di->type == ICON_TYPE_BUFFER) { @@ -1738,7 +1900,7 @@ static void icon_draw_size(float x, return; } - icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, desaturate); + icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, desaturate); } else if (di->type == ICON_TYPE_PREVIEW) { PreviewImage *pi = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : @@ -1755,7 +1917,7 @@ static void icon_draw_size(float x, GPU_blend_set_func_separate( GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); icon_draw_rect( - x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, rgb, desaturate); + x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, desaturate); GPU_blend_set_func_separate( GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); } @@ -2057,7 +2219,7 @@ int UI_idcode_icon_get(const int idcode) case ID_PC: return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */ case ID_LP: - return ICON_LIGHTPROBE_CUBEMAP; + return ICON_OUTLINER_DATA_LIGHTPROBE; case ID_SCE: return ICON_SCENE_DATA; case ID_SPK: @@ -2077,71 +2239,40 @@ int UI_idcode_icon_get(const int idcode) } } -static void icon_draw_at_size(float x, - float y, - int icon_id, - float aspect, - float alpha, - enum eIconSizes size, - const float desaturate, - const char mono_color[4]) -{ - int draw_size = get_draw_size(size); - icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, desaturate, mono_color); -} - -void UI_icon_draw_aspect( - float x, float y, int icon_id, float aspect, float alpha, const char mono_color[4]) -{ - icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, 0.0f, mono_color); -} - -void UI_icon_draw_aspect_color( - float x, float y, int icon_id, float aspect, const float rgb[3], const char mono_color[4]) -{ - int draw_size = get_draw_size(ICON_SIZE_ICON); - icon_draw_size(x, y, icon_id, aspect, 1.0f, rgb, ICON_SIZE_ICON, draw_size, false, mono_color); -} - -void UI_icon_draw_desaturate(float x, - float y, - int icon_id, - float aspect, - float alpha, - float desaturate, - const char mono_color[4]) -{ - icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, desaturate, mono_color); -} - /* draws icon with dpi scale factor */ void UI_icon_draw(float x, float y, int icon_id) { - UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, 1.0f, NULL); + UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false); } void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha) { - UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, alpha, NULL); -} - -void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha) -{ - icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, false, NULL); + UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false); } -void UI_icon_draw_preview(float x, float y, int icon_id) +void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size) { - icon_draw_at_size(x, y, icon_id, 1.0f, 1.0f, ICON_SIZE_PREVIEW, false, NULL); + icon_draw_size(x, y, icon_id, aspect, alpha, ICON_SIZE_PREVIEW, size, false, NULL, false); } -void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect) +void UI_icon_draw_ex(float x, + float y, + int icon_id, + float aspect, + float alpha, + float desaturate, + const char mono_color[4], + const bool mono_border) { - icon_draw_at_size(x, y, icon_id, aspect, 1.0f, ICON_SIZE_PREVIEW, false, NULL); -} - -void UI_icon_draw_preview_aspect_size( - float x, float y, int icon_id, float aspect, float alpha, int size) -{ - icon_draw_size(x, y, icon_id, aspect, alpha, NULL, ICON_SIZE_PREVIEW, size, false, NULL); + int draw_size = get_draw_size(ICON_SIZE_ICON); + icon_draw_size(x, + y, + icon_id, + aspect, + alpha, + ICON_SIZE_ICON, + draw_size, + desaturate, + mono_color, + mono_border); } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 4af7fdd779f..33288df15ba 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -539,13 +539,12 @@ struct uiKeyNavLock { typedef uiBlock *(*uiBlockHandleCreateFunc)(struct bContext *C, struct uiPopupBlockHandle *handle, void *arg1); -typedef void (*uiBlockHandleFreeFunc)(struct uiPopupBlockHandle *handle, void *arg1); struct uiPopupBlockCreate { uiBlockCreateFunc create_func; uiBlockHandleCreateFunc handle_create_func; - uiBlockHandleFreeFunc free_func; void *arg; + void (*arg_free)(void *arg); int event_xy[2]; @@ -662,7 +661,8 @@ uiPopupBlockHandle *ui_popup_block_create(struct bContext *C, uiBut *but, uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, - void *arg); + void *arg, + void (*arg_free)(void *arg)); uiPopupBlockHandle *ui_popup_menu_create(struct bContext *C, struct ARegion *butregion, uiBut *but, diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 15e507483ad..37ef0948dee 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -764,7 +764,8 @@ static void ui_item_enum_expand_elem_exec(uiLayout *layout, if (RNA_property_flag(prop) & PROP_ENUM_FLAG) { /* If this is set, assert since we're clobbering someone elses callback. */ - BLI_assert(but->func == NULL); + /* Buttons get their block's func by default, so we cannot assert in that case either. */ + BLI_assert(ELEM(but->func, NULL, block->func)); UI_but_func_set(but, ui_item_enum_expand_handle, but, POINTER_FROM_INT(value)); } diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 87e58a4b3b5..46b1279643e 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -258,43 +258,16 @@ static void panels_collapse_all(ScrArea *sa, ARegion *ar, const Panel *from_pa) } } -static void ui_panel_copy_offset(Panel *pa, Panel *papar) -{ - /* with respect to sizes... papar is parent */ - - pa->ofsx = papar->ofsx; - pa->ofsy = papar->ofsy + papar->sizey - pa->sizey; -} - -/** - * XXX Disabled paneltab handling for now. Old 2.4x feature, - * *DO NOT* confuse it with new tool tabs in 2.70. ;) - * See also T41704. - */ -/* #define UI_USE_PANELTAB */ - Panel *UI_panel_find_by_type(ListBase *lb, PanelType *pt) { Panel *pa; const char *idname = pt->idname; -#ifdef UI_USE_PANELTAB - const char *tabname = pt->idname; - for (pa = lb->first; pa; pa = pa->next) { - if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) { - if (STREQLEN(pa->tabname, tabname, sizeof(pa->tabname))) { - return pa; - } - } - } -#else for (pa = lb->first; pa; pa = pa->next) { if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) { return pa; } } -#endif - return NULL; } @@ -307,10 +280,6 @@ Panel *UI_panel_begin( Panel *palast, *panext; const char *drawname = CTX_IFACE_(pt->translation_context, pt->label); const char *idname = pt->idname; -#ifdef UI_USE_PANELTAB - const char *tabname = pt->idname; - const char *hookname = NULL; -#endif const bool newpanel = (pa == NULL); int align = panel_aligned(sa, ar); @@ -341,28 +310,6 @@ Panel *UI_panel_begin( pa->runtime_flag |= PNL_NEW_ADDED; BLI_addtail(lb, pa); - -#ifdef UI_USE_PANELTAB - BLI_strncpy(pa->tabname, tabname, sizeof(pa->tabname)); - - /* make new Panel tabbed? */ - if (hookname) { - Panel *patab; - for (patab = lb->first; patab; patab = patab->next) { - if ((patab->runtime_flag & PNL_ACTIVE) && patab->paneltab == NULL) { - if (STREQLEN(hookname, patab->panelname, sizeof(patab->panelname))) { - if (STREQLEN(tabname, patab->tabname, sizeof(patab->tabname))) { - pa->paneltab = patab; - ui_panel_copy_offset(pa, patab); - break; - } - } - } - } - } -#else - BLI_strncpy(pa->tabname, idname, sizeof(pa->tabname)); -#endif } /* Do not allow closed panels without headers! Else user could get "disappeared" UI! */ @@ -411,9 +358,6 @@ Panel *UI_panel_begin( *r_open = false; - if (pa->paneltab) { - return pa; - } if (pa->flag & PNL_CLOSED) { return pa; } @@ -706,9 +650,6 @@ void ui_draw_aligned_panel(uiStyle *style, * can't be dragged. This may be changed in future. */ show_background); - if (panel->paneltab) { - return; - } if (panel->type && (panel->type->flag & PNL_NO_HEADER)) { return; } @@ -765,12 +706,14 @@ void ui_draw_aligned_panel(uiStyle *style, panel_title_color_get(show_background, col_title); GPU_blend(true); - UI_icon_draw_aspect(headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect), - headrect.ymin + (5.0f / block->aspect), - (panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED, - (block->aspect / UI_DPI_FAC), - 1.0f, - (const char *)col_title); + UI_icon_draw_ex(headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect), + headrect.ymin + (5.0f / block->aspect), + (panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED, + (block->aspect * U.inv_dpi_fac), + 1.0f, + 0.0f, + (const char *)col_title, + false); GPU_blend(false); } @@ -934,12 +877,6 @@ static int get_panel_real_ofsy(Panel *pa) if (pa->flag & PNL_CLOSEDY) { return pa->ofsy + pa->sizey; } - else if (pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDY)) { - return pa->ofsy + pa->sizey; - } - else if (pa->paneltab) { - return pa->paneltab->ofsy; - } else { return pa->ofsy; } @@ -950,9 +887,6 @@ static int get_panel_real_ofsx(Panel *pa) if (pa->flag & PNL_CLOSEDX) { return pa->ofsx + get_panel_header(pa); } - else if (pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDX)) { - return pa->ofsx + get_panel_header(pa); - } else { return pa->ofsx + pa->sizex; } @@ -1067,7 +1001,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo /* count active, not tabbed panels */ for (pa = ar->panels.first; pa; pa = pa->next) { - if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) { + if (pa->runtime_flag & PNL_ACTIVE) { tot++; } } @@ -1078,7 +1012,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo /* extra; change close direction? */ for (pa = ar->panels.first; pa; pa = pa->next) { - if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) { + if (pa->runtime_flag & PNL_ACTIVE) { if ((pa->flag & PNL_CLOSEDX) && (align == BUT_VERTICAL)) { pa->flag ^= PNL_CLOSED; } @@ -1093,7 +1027,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo ps = panelsort; for (pa = ar->panels.first; pa; pa = pa->next) { - if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) { + if (pa->runtime_flag & PNL_ACTIVE) { ps->pa = MEM_dupallocN(pa); ps->orig = pa; ps++; @@ -1160,9 +1094,6 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo /* set locations for tabbed and sub panels */ for (pa = ar->panels.first; pa; pa = pa->next) { if (pa->runtime_flag & PNL_ACTIVE) { - if (pa->paneltab) { - ui_panel_copy_offset(pa, pa->paneltab); - } if (pa->children.first) { align_sub_panels(pa); } @@ -1265,7 +1196,7 @@ void UI_panels_end(const bContext *C, ARegion *ar, int *r_x, int *r_y) { ScrArea *sa = CTX_wm_area(C); uiBlock *block; - Panel *panot, *panew, *patest, *pa, *firstpa; + Panel *pa, *firstpa; /* offset contents */ for (block = ar->uiblocks.first; block; block = block->next) { @@ -1274,31 +1205,6 @@ void UI_panels_end(const bContext *C, ARegion *ar, int *r_x, int *r_y) } } - /* consistency; are panels not made, whilst they have tabs */ - for (panot = ar->panels.first; panot; panot = panot->next) { - if ((panot->runtime_flag & PNL_ACTIVE) == 0) { /* not made */ - - for (panew = ar->panels.first; panew; panew = panew->next) { - if ((panew->runtime_flag & PNL_ACTIVE)) { - if (panew->paneltab == panot) { /* panew is tab in notmade pa */ - break; - } - } - } - /* now panew can become the new parent, check all other tabs */ - if (panew) { - for (patest = ar->panels.first; patest; patest = patest->next) { - if (patest->paneltab == panot) { - patest->paneltab = panew; - } - } - panot->paneltab = panew; - panew->paneltab = NULL; - ED_region_tag_redraw(ar); /* the buttons panew were not made */ - } - } - } - /* re-align, possibly with animation */ if (panels_need_realign(sa, ar, &pa)) { if (pa) { @@ -1380,7 +1286,7 @@ static void check_panel_overlap(ARegion *ar, Panel *panel) for (pa = ar->panels.first; pa; pa = pa->next) { pa->flag &= ~PNL_OVERLAP; if (panel && (pa != panel)) { - if (pa->paneltab == NULL && (pa->runtime_flag & PNL_ACTIVE)) { + if (pa->runtime_flag & PNL_ACTIVE) { float safex = 0.2, safey = 0.2; if (pa->flag & PNL_CLOSEDX) { @@ -1623,11 +1529,11 @@ static void ui_handle_panel_header( { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - Panel *pa; #ifdef USE_PIN_HIDDEN - const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->flag & PNL_PIN); + const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->type->parent == NULL) && + (block->panel->flag & PNL_PIN); #else - const bool show_pin = UI_panel_category_is_visible(ar); + const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->type->parent == NULL); #endif const bool is_subpanel = (block->panel->type && block->panel->type->parent); const bool show_drag = !is_subpanel; @@ -1658,8 +1564,10 @@ static void ui_handle_panel_header( button = 1; } else if (ELEM(event, 0, RETKEY, LEFTMOUSE) && shift) { - block->panel->flag ^= PNL_PIN; - button = 2; + if (block->panel->type->parent == NULL) { + block->panel->flag ^= PNL_PIN; + button = 2; + } } else if (block->panel->flag & PNL_CLOSEDX) { if (my >= block->rect.ymax) { @@ -1720,17 +1628,6 @@ static void ui_handle_panel_header( ui_panel_drag_collapse_handler_add(C, true); } } - - for (pa = ar->panels.first; pa; pa = pa->next) { - if (pa->paneltab == block->panel) { - if (block->panel->flag & PNL_CLOSED) { - pa->flag |= PNL_CLOSED; - } - else { - pa->flag &= ~PNL_CLOSED; - } - } - } } if (align) { @@ -2067,7 +1964,11 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active) ui_fontscale(&fstyle_points, aspect / (U.pixelsize * 1.1f)); BLF_size(fontid, fstyle_points, U.dpi); - BLI_assert(UI_panel_category_is_visible(ar)); + /* Check the region type supports categories to avoid an assert + * for showing 3D view panels in the properties space. */ + if ((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) { + BLI_assert(UI_panel_category_is_visible(ar)); + } /* calculate tab rect's and check if we need to scale down */ for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) { @@ -2378,7 +2279,7 @@ int ui_handler_panel_region(bContext *C, /* checks for mouse position inside */ pa = block->panel; - if (!pa || pa->paneltab != NULL) { + if (!pa) { continue; } /* XXX - accessed freed panels when scripts reload, need to fix. */ diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c index dcbbde259f2..330a9d48ff4 100644 --- a/source/blender/editors/interface/interface_region_menu_pie.c +++ b/source/blender/editors/interface/interface_region_menu_pie.c @@ -208,7 +208,7 @@ void UI_pie_menu_end(bContext *C, uiPieMenu *pie) wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *menu; - menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie); + menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie, NULL); menu->popup = true; menu->towardstime = PIL_check_seconds_timer(); diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c index b97cbcdfef5..ab3a86ec9e1 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.c +++ b/source/blender/editors/interface/interface_region_menu_popup.c @@ -351,7 +351,7 @@ uiPopupBlockHandle *ui_popup_menu_create( pup->menu_func = menu_func; pup->menu_arg = arg; - handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup); + handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup, NULL); if (!but) { handle->popup = true; @@ -463,7 +463,7 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup) butregion = pup->butregion; } - menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup); + menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup, NULL); menu->popup = true; UI_popup_handlers_add(C, &window->modalhandlers, menu, 0); @@ -581,13 +581,17 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports) /** \name Popup Block API * \{ */ -void UI_popup_block_invoke_ex( - bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext) +void UI_popup_block_invoke_ex(bContext *C, + uiBlockCreateFunc func, + void *arg, + void (*arg_free)(void *arg), + const char *opname, + int opcontext) { wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *handle; - handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg); + handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, arg_free); handle->popup = true; handle->can_refresh = true; handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL; @@ -598,9 +602,12 @@ void UI_popup_block_invoke_ex( WM_event_add_mousemove(C); } -void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg) +void UI_popup_block_invoke(bContext *C, + uiBlockCreateFunc func, + void *arg, + void (*arg_free)(void *arg)) { - UI_popup_block_invoke_ex(C, func, arg, NULL, WM_OP_INVOKE_DEFAULT); + UI_popup_block_invoke_ex(C, func, arg, arg_free, NULL, WM_OP_INVOKE_DEFAULT); } void UI_popup_block_ex(bContext *C, @@ -613,7 +620,7 @@ void UI_popup_block_ex(bContext *C, wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *handle; - handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg); + handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, NULL); handle->popup = true; handle->retvalue = 1; handle->can_refresh = true; @@ -635,7 +642,7 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, int wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *handle; - handle = ui_popup_block_create(C, NULL, NULL, func, NULL, op); + handle = ui_popup_block_create(C, NULL, NULL, func, NULL, op, NULL); handle->popup = 1; handle->retvalue = 1; handle->can_refresh = true; diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c index f149ccd626c..22c62ecd6f7 100644 --- a/source/blender/editors/interface/interface_region_popover.c +++ b/source/blender/editors/interface/interface_region_popover.c @@ -244,7 +244,7 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v return block; } -static void ui_block_free_func_POPOVER(uiPopupBlockHandle *UNUSED(handle), void *arg_pup) +static void ui_block_free_func_POPOVER(void *arg_pup) { uiPopover *pup = arg_pup; if (pup->keymap != NULL) { @@ -282,8 +282,8 @@ uiPopupBlockHandle *ui_popover_panel_create( /* Create popup block. */ uiPopupBlockHandle *handle; - handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPOVER, pup); - handle->popup_create_vars.free_func = ui_block_free_func_POPOVER; + handle = ui_popup_block_create( + C, butregion, but, NULL, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER); handle->can_refresh = true; /* Add handlers. If attached to a button, the button will already @@ -386,8 +386,8 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap) WM_event_set_keymap_handler_post_callback(pup->keymap_handler, popover_keymap_fn, pup); } - handle = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPOVER, pup); - handle->popup_create_vars.free_func = ui_block_free_func_POPOVER; + handle = ui_popup_block_create( + C, NULL, NULL, NULL, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER); /* Add handlers. */ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0); diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index c4bcd7074d8..bd87439ca9e 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -748,7 +748,8 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, uiBut *but, uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, - void *arg) + void *arg, + void (*arg_free)(void *arg)) { wmWindow *window = CTX_wm_window(C); uiBut *activebut = UI_context_active_but_get(C); @@ -775,6 +776,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, handle->popup_create_vars.create_func = create_func; handle->popup_create_vars.handle_create_func = handle_create_func; handle->popup_create_vars.arg = arg; + handle->popup_create_vars.arg_free = arg_free; handle->popup_create_vars.but = but; handle->popup_create_vars.butregion = but ? butregion : NULL; copy_v2_v2_int(handle->popup_create_vars.event_xy, &window->eventstate->x); @@ -820,8 +822,8 @@ void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle) } } - if (handle->popup_create_vars.free_func) { - handle->popup_create_vars.free_func(handle, handle->popup_create_vars.arg); + if (handle->popup_create_vars.arg_free) { + handle->popup_create_vars.arg_free(handle->popup_create_vars.arg); } ui_popup_block_remove(C, handle); diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index 4a9c7b689c1..5b205de21b8 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -891,11 +891,11 @@ static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *gz) } gzop_actions[] = { { .part = gz->highlight_part, - .prefix = use_drag ? TIP_("Click") : NULL, + .prefix = use_drag ? CTX_TIP_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Click") : NULL, }, { .part = use_drag ? gz->drag_part : -1, - .prefix = use_drag ? TIP_("Drag") : NULL, + .prefix = use_drag ? CTX_TIP_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Drag") : NULL, }, }; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index e96141eaa05..9e91505f5e8 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -4042,6 +4042,11 @@ static uiBlock *curvemap_brush_tools_func(bContext *C, ARegion *ar, void *cumap_ return curvemap_tools_func(C, ar, cumap_v, false, UICURVE_FUNC_RESET_NEG); } +static uiBlock *curvemap_brush_tools_negslope_func(bContext *C, ARegion *ar, void *cumap_v) +{ + return curvemap_tools_func(C, ar, cumap_v, false, UICURVE_FUNC_RESET_POS); +} + static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2)) { ED_region_tag_redraw(CTX_wm_region(C)); @@ -4217,7 +4222,19 @@ static void curvemap_buttons_layout(uiLayout *layout, TIP_("Zoom out")); UI_but_func_set(bt, curvemap_buttons_zoom_out, cumap, NULL); - if (brush) { + if (brush && neg_slope) { + bt = uiDefIconBlockBut(block, + curvemap_brush_tools_negslope_func, + cumap, + 0, + ICON_DOWNARROW_HLT, + 0, + 0, + dx, + dx, + TIP_("Tools")); + } + else if (brush) { bt = uiDefIconBlockBut(block, curvemap_brush_tools_func, cumap, @@ -6744,12 +6761,17 @@ int uiTemplateRecentFiles(uiLayout *layout, int rows) for (recent = G.recent_files.first, i = 0; (i < rows) && (recent); recent = recent->next, i++) { const char *filename = BLI_path_basename(recent->filepath); - uiItemStringO(layout, - filename, - BLO_has_bfile_extension(filename) ? ICON_FILE_BLEND : ICON_FILE_BACKUP, - "WM_OT_open_mainfile", - "filepath", - recent->filepath); + PointerRNA ptr; + uiItemFullO(layout, + "WM_OT_open_mainfile", + filename, + BLO_has_bfile_extension(filename) ? ICON_FILE_BLEND : ICON_FILE_BACKUP, + NULL, + WM_OP_INVOKE_DEFAULT, + 0, + &ptr); + RNA_string_set(&ptr, "filepath", recent->filepath); + RNA_boolean_set(&ptr, "display_file_selector", false); } return i; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index a9cd2f9cee1..594793371ae 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1421,7 +1421,7 @@ static void widget_draw_preview(BIFIconID icon, float alpha, const rcti *rect) int x = rect->xmin + w / 2 - size / 2; int y = rect->ymin + h / 2 - size / 2; - UI_icon_draw_preview_aspect_size(x, y, icon, 1.0f, alpha, size); + UI_icon_draw_preview(x, y, icon, 1.0f, alpha, size); } } @@ -1450,7 +1450,7 @@ static void widget_draw_icon( return; } - aspect = but->block->aspect / UI_DPI_FAC; + aspect = but->block->aspect * U.inv_dpi_fac; height = ICON_DEFAULT_HEIGHT / aspect; /* calculate blend color */ @@ -1506,18 +1506,27 @@ static void widget_draw_icon( ys = (int)(ys + 0.1f); } + /* Get theme color. */ + char color[4] = {mono_color[0], mono_color[1], mono_color[2], mono_color[3]}; + bool has_theme = UI_icon_get_theme_color(icon, (uchar *)color); + /* to indicate draggable */ if (but->dragpoin && (but->flag & UI_ACTIVE)) { - float rgb[3] = {1.25f, 1.25f, 1.25f}; - UI_icon_draw_aspect_color(xs, ys, icon, aspect, rgb, mono_color); + UI_icon_draw_ex(xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme); + } + else if ((but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW))) { + UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme); } - else if ((but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW)) || !UI_but_is_tool(but)) { - UI_icon_draw_aspect(xs, ys, icon, aspect, alpha, mono_color); + else if (!UI_but_is_tool(but)) { + if (has_theme) { + alpha *= 0.8f; + } + UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme); } else { const bTheme *btheme = UI_GetTheme(); - UI_icon_draw_desaturate( - xs, ys, icon, aspect, alpha, 1.0 - btheme->tui.icon_saturation, mono_color); + const float desaturate = 1.0 - btheme->tui.icon_saturation; + UI_icon_draw_ex(xs, ys, icon, aspect, alpha, desaturate, color, has_theme); } } @@ -1528,7 +1537,7 @@ static void widget_draw_submenu_tria(const uiBut *but, const rcti *rect, const uiWidgetColors *wcol) { - const float aspect = but->block->aspect / UI_DPI_FAC; + const float aspect = but->block->aspect * U.inv_dpi_fac; const int tria_height = (int)(ICON_DEFAULT_HEIGHT / aspect); const int tria_width = (int)(ICON_DEFAULT_WIDTH / aspect) - 2 * U.pixelsize; const int xs = rect->xmax - tria_width; @@ -1584,7 +1593,8 @@ static void ui_text_clip_right_ex(const uiFontStyle *fstyle, BLI_assert(str[0]); /* If the trailing ellipsis takes more than 20% of all available width, just cut the string - * (as using the ellipsis would remove even more useful chars, and we cannot show much already!). + * (as using the ellipsis would remove even more useful chars, and we cannot show much + * already!). */ if (sep_strwidth / okwidth > 0.2f) { l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, &tmp); @@ -1699,7 +1709,8 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle, /* Corner case, the str already takes all available mem, * and the ellipsis chars would actually add more chars. * Better to just trim one or two letters to the right in this case... - * Note: with a single-char ellipsis, this should never happen! But better be safe here... + * Note: with a single-char ellipsis, this should never happen! But better be safe + * here... */ ui_text_clip_right_ex( fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len); @@ -2346,7 +2357,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, const BIFIconID icon = widget_icon_id(but); int icon_size_init = is_tool ? ICON_DEFAULT_HEIGHT_TOOLBAR : ICON_DEFAULT_HEIGHT; - const float icon_size = icon_size_init / (but->block->aspect / UI_DPI_FAC); + const float icon_size = icon_size_init / (but->block->aspect * U.inv_dpi_fac); const float icon_padding = 2 * UI_DPI_FAC; #ifdef USE_UI_TOOLBAR_HACK @@ -3494,8 +3505,11 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s wcol->item[3] = 255; if (horizontal) { - shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'l'); - shape_preset_init_scroll_circle(&wtb.tria2, slider, 0.6f, 'r'); + rcti slider_inset = *slider; + slider_inset.xmin += 0.05 * U.widget_unit; + slider_inset.xmax -= 0.05 * U.widget_unit; + shape_preset_init_scroll_circle(&wtb.tria1, &slider_inset, 0.6f, 'l'); + shape_preset_init_scroll_circle(&wtb.tria2, &slider_inset, 0.6f, 'r'); } else { shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'b'); @@ -4631,6 +4645,9 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct break; case UI_BTYPE_COLORBAND: + /* do not draw right to edge of rect */ + rect->xmin += (0.25f * UI_UNIT_X); + rect->xmax -= (0.3f * UI_UNIT_X); ui_draw_but_COLORBAND(but, &tui->wcol_regular, rect); break; @@ -4655,6 +4672,9 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct break; case UI_BTYPE_CURVE: + /* do not draw right to edge of rect */ + rect->xmin += (0.2f * UI_UNIT_X); + rect->xmax -= (0.2f * UI_UNIT_X); ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect); break; @@ -5198,7 +5218,7 @@ void ui_draw_menu_item( GPU_blend(true); /* XXX scale weak get from fstyle? */ - UI_icon_draw_aspect(xs, ys, iconid, aspect, 1.0f, wt->wcol.text); + UI_icon_draw_ex(xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false); GPU_blend(false); } } diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 8ed7dd87e9f..14fad2f3072 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -309,6 +309,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) case TH_GRID: cp = ts->grid; break; + case TH_SCRUBBING_BACKGROUND: + cp = ts->scrubbing_background; + break; case TH_VIEW_OVERLAY: cp = ts->view_overlay; break; @@ -865,6 +868,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) cp = btheme->tui.gizmo_b; break; + case TH_ICON_SCENE: + cp = btheme->tui.icon_scene; + break; case TH_ICON_COLLECTION: cp = btheme->tui.icon_collection; break; @@ -881,6 +887,10 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) cp = btheme->tui.icon_shading; break; + case TH_SCROLL_TEXT: + cp = btheme->tui.wcol_scroll.text; + break; + case TH_INFO_SELECTED: cp = ts->info_selected; break; @@ -1347,7 +1357,7 @@ void UI_GetThemeColorType4ubv(int colorid, int spacetype, uchar col[4]) col[3] = cp[3]; } -bool UI_GetIconThemeColor4fv(int colorid, float col[4]) +bool UI_GetIconThemeColor4ubv(int colorid, uchar col[4]) { if (colorid == 0) { return false; @@ -1357,17 +1367,15 @@ bool UI_GetIconThemeColor4fv(int colorid, float col[4]) * to stay monochrome and out of the way except a few places where it * is important to communicate different data types. */ if (!((theme_spacetype == SPACE_OUTLINER && theme_regionid == RGN_TYPE_WINDOW) || - (theme_spacetype == SPACE_PROPERTIES && theme_regionid == RGN_TYPE_NAV_BAR) || - (theme_regionid == RGN_TYPE_TEMPORARY))) { + (theme_spacetype == SPACE_PROPERTIES && theme_regionid == RGN_TYPE_NAV_BAR))) { return false; } - const uchar *cp; - cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); - col[0] = ((float)cp[0]) / 255.0f; - col[1] = ((float)cp[1]) / 255.0f; - col[2] = ((float)cp[2]) / 255.0f; - col[3] = ((float)cp[3]) / 255.0f; + const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); + col[0] = cp[0]; + col[1] = cp[1]; + col[2] = cp[2]; + col[3] = cp[3]; return true; } diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index 9de7a33b757..f2d4faff479 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -138,7 +138,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr if (check_scrollers) { /* check size if hiding flag is set: */ if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) { - if (!(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL)) { + if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) { if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) { v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR; } @@ -148,7 +148,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr } } if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) { - if (!(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL)) { + if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) { if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) { v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR; } @@ -166,10 +166,11 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr * - if they overlap, they must not occupy the corners (which are reserved for other widgets) */ if (scroll) { - const int scroll_width = (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) ? V2D_SCROLL_WIDTH_TEXT : - V2D_SCROLL_WIDTH; - const int scroll_height = (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) ? - V2D_SCROLL_HEIGHT_TEXT : + const int scroll_width = (v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) ? + V2D_SCROLL_WIDTH_HANDLES : + V2D_SCROLL_WIDTH; + const int scroll_height = (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) ? + V2D_SCROLL_HEIGHT_HANDLES : V2D_SCROLL_HEIGHT; /* vertical scroller */ @@ -185,6 +186,13 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr v2d->vert.xmin = v2d->vert.xmax - scroll_width; } + /* Currently, all regions that have vertical scale handles, + * also have the scrubbing area at the top. + * So the scrollbar has to move down a bit. */ + if (scroll & V2D_SCROLL_VERTICAL_HANDLES) { + v2d->vert.ymax -= UI_SCRUBBING_MARGIN_Y; + } + /* horizontal scroller */ if (scroll & (V2D_SCROLL_BOTTOM)) { /* on bottom edge of region */ @@ -1589,7 +1597,7 @@ void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs) * (workaround to make sure that button windows don't show these, * and only the time-grids with their zoomability can do so) */ - if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) && + if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) && (BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE)) { state |= UI_SCROLL_ARROWS; } @@ -1623,7 +1631,7 @@ void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs) * (workaround to make sure that button windows don't show these, * and only the time-grids with their zoomability can do so) */ - if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) && + if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) && (BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE)) { state |= UI_SCROLL_ARROWS; } diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index ab8d1cf9bf6..68ee38bc99f 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -2032,8 +2032,8 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent * * NOTE: see view2d.c for latest conditions, and keep this in sync with that */ if (ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) { - if (((vsm->scroller == 'h') && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0) || - ((vsm->scroller == 'v') && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0)) { + if (((vsm->scroller == 'h') && (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) == 0) || + ((vsm->scroller == 'v') && (v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) == 0)) { /* switch to bar (i.e. no scaling gets handled) */ vsm->zone = SCROLLHANDLE_BAR; } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index c0f3b1f8338..1f825c0bb31 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -1992,9 +1992,9 @@ static int mask_hide_view_clear_exec(bContext *C, wmOperator *op) for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - if (masklay->restrictflag & OB_RESTRICT_VIEW) { + if (masklay->restrictflag & OB_RESTRICT_VIEWPORT) { ED_mask_layer_select_set(masklay, select); - masklay->restrictflag &= ~OB_RESTRICT_VIEW; + masklay->restrictflag &= ~OB_RESTRICT_VIEWPORT; changed = true; } } @@ -2045,7 +2045,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op) if (ED_mask_layer_select_check(masklay)) { ED_mask_layer_select_set(masklay, false); - masklay->restrictflag |= OB_RESTRICT_VIEW; + masklay->restrictflag |= OB_RESTRICT_VIEWPORT; changed = true; if (masklay == BKE_mask_layer_active(mask)) { BKE_mask_layer_active_set(mask, NULL); @@ -2054,7 +2054,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op) } else { if (!ED_mask_layer_select_check(masklay)) { - masklay->restrictflag |= OB_RESTRICT_VIEW; + masklay->restrictflag |= OB_RESTRICT_VIEWPORT; changed = true; if (masklay == BKE_mask_layer_active(mask)) { BKE_mask_layer_active_set(mask, NULL); diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 57bf67e825e..9a779db4812 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../../blentranslation ../../bmesh ../../depsgraph + ../../draw ../../gpu ../../imbuf ../../makesdna diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 990250792a1..fdbcc3449b2 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -461,13 +461,13 @@ bool do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op) } else { MPoly *mpoly; - uint *rt; + uint *rt, *buf, buf_len; int a, index; char *selar = MEM_callocN(me->totpoly + 1, "selar"); - uint buf_len; - uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); + ED_view3d_select_id_validate(vc); + buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); rt = buf; diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index f5810d9ff61..1cd4e95314b 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -907,7 +907,8 @@ void MESH_OT_bevel(wmOperatorType *ot) /* identifiers */ ot->name = "Bevel"; - ot->description = "Cut into selected items at an angle to create flat or rounded bevel or chamfer"; + ot->description = + "Cut into selected items at an angle to create flat or rounded bevel or chamfer"; ot->idname = "MESH_OT_bevel"; /* api callbacks */ diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 82cff8363f8..0da4d20c6b5 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -36,6 +36,7 @@ #include "RNA_access.h" #include "WM_types.h" +#include "WM_api.h" #include "ED_mesh.h" #include "ED_screen.h" @@ -860,6 +861,9 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w EDBM_mesh_normals_update(vc.em); EDBM_update_generic(vc.em, true, true); + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); } MEM_freeN(objects); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index cc0c2f5bbe4..e45c15b3e53 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -2811,6 +2811,7 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf) {KNF_MODAL_CUT_THROUGH_TOGGLE, "CUT_THROUGH_TOGGLE", 0, "Toggle Cut Through", ""}, {KNF_MODAL_NEW_CUT, "NEW_CUT", 0, "End Current Cut", ""}, {KNF_MODAL_ADD_CUT, "ADD_CUT", 0, "Add Cut", ""}, + {KNF_MODAL_ADD_CUT_CLOSED, "ADD_CUT_CLOSED", 0, "Add Cut Closed", ""}, {KNF_MODAL_PANNING, "PANNING", 0, "Panning", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 528235e693a..59355890428 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -79,11 +79,11 @@ typedef struct RingSelOpData { Depsgraph *depsgraph; - Object **objects; - uint objects_len; + Base **bases; + uint bases_len; /* These values switch objects based on the object under the cursor. */ - uint ob_index; + uint base_index; Object *ob; BMEditMesh *em; BMEdge *eed; @@ -111,8 +111,8 @@ static void edgering_select(RingSelOpData *lcd) } if (!lcd->extend) { - for (uint ob_index = 0; ob_index < lcd->objects_len; ob_index++) { - Object *ob_iter = lcd->objects[ob_index]; + for (uint base_index = 0; base_index < lcd->bases_len; base_index++) { + Object *ob_iter = lcd->bases[base_index]->object; BMEditMesh *em = BKE_editmesh_from_object(ob_iter); EDBM_flag_disable_all(em, BM_ELEM_SELECT); DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT); @@ -252,7 +252,7 @@ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op) EDBM_preselect_edgering_destroy(lcd->presel_edgering); - MEM_freeN(lcd->objects); + MEM_freeN(lcd->bases); ED_region_tag_redraw(lcd->ar); @@ -307,21 +307,21 @@ static void ringcut_cancel(bContext *C, wmOperator *op) } static void loopcut_update_edge(RingSelOpData *lcd, - uint ob_index, + uint base_index, BMEdge *e, const int previewlines) { if (e != lcd->eed) { lcd->eed = e; lcd->ob = lcd->vc.obedit; - lcd->ob_index = ob_index; + lcd->base_index = base_index; lcd->em = lcd->vc.em; ringsel_find_edge(lcd, previewlines); } else if (e == NULL) { lcd->ob = NULL; lcd->em = NULL; - lcd->ob_index = UINT_MAX; + lcd->base_index = UINT_MAX; } } @@ -331,27 +331,26 @@ static void loopcut_mouse_move(RingSelOpData *lcd, const int previewlines) Object *ob; BMEdge *eed; float dist; - int ob_index; + int base_index; } best = { .dist = ED_view3d_select_dist_px(), }; - for (uint ob_index = 0; ob_index < lcd->objects_len; ob_index++) { - Object *ob_iter = lcd->objects[ob_index]; - ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter); - BMEdge *eed_test = EDBM_edge_find_nearest_ex(&lcd->vc, &best.dist, NULL, false, false, NULL); - if (eed_test) { - best.ob = ob_iter; - best.eed = eed_test; - best.ob_index = ob_index; - } + uint base_index; + BMEdge *eed_test = EDBM_edge_find_nearest_ex( + &lcd->vc, &best.dist, NULL, false, false, NULL, lcd->bases, lcd->bases_len, &base_index); + + if (eed_test) { + best.ob = lcd->bases[base_index]->object; + best.eed = eed_test; + best.base_index = base_index; } if (best.eed) { ED_view3d_viewcontext_init_object(&lcd->vc, best.ob); } - loopcut_update_edge(lcd, best.ob_index, best.eed, previewlines); + loopcut_update_edge(lcd, best.base_index, best.eed, previewlines); } /* called by both init() and exec() */ @@ -361,22 +360,22 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) /* Use for redo - intentionally wrap int to uint. */ const struct { - uint ob_index; + uint base_index; uint e_index; } exec_data = { - .ob_index = (uint)RNA_int_get(op->ptr, "object_index"), + .base_index = (uint)RNA_int_get(op->ptr, "object_index"), .e_index = (uint)RNA_int_get(op->ptr, "edge_index"), }; ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode( - view_layer, CTX_wm_view3d(C), &objects_len); + uint bases_len; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( + view_layer, CTX_wm_view3d(C), &bases_len); if (is_interactive) { - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *ob_iter = objects[ob_index]; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *ob_iter = bases[base_index]->object; if (modifiers_isDeformedByLattice(ob_iter) || modifiers_isDeformedByArmature(ob_iter)) { BKE_report( op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display"); @@ -390,12 +389,12 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) /* for re-execution, check edge index is in range before we setup ringsel */ bool ok = true; if (is_interactive == false) { - if (exec_data.ob_index >= objects_len) { + if (exec_data.base_index >= bases_len) { return OPERATOR_CANCELLED; ok = false; } else { - Object *ob_iter = objects[exec_data.ob_index]; + Object *ob_iter = bases[exec_data.base_index]->object; BMEditMesh *em = BKE_editmesh_from_object(ob_iter); if (exec_data.e_index >= em->bm->totedge) { ok = false; @@ -404,7 +403,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) } if (!ok || !ringsel_init(C, op, true)) { - MEM_freeN(objects); + MEM_freeN(bases); return OPERATOR_CANCELLED; } @@ -416,8 +415,8 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) RingSelOpData *lcd = op->customdata; - lcd->objects = objects; - lcd->objects_len = objects_len; + lcd->bases = bases; + lcd->bases_len = bases_len; if (is_interactive) { copy_v2_v2_int(lcd->vc.mval, event->mval); @@ -425,13 +424,13 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) } else { - Object *ob_iter = objects[exec_data.ob_index]; + Object *ob_iter = bases[exec_data.base_index]->object; ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter); BMEdge *e; BM_mesh_elem_table_ensure(lcd->vc.em->bm, BM_EDGE); e = BM_edge_at_index(lcd->vc.em->bm, exec_data.e_index); - loopcut_update_edge(lcd, exec_data.ob_index, e, 0); + loopcut_update_edge(lcd, exec_data.base_index, e, 0); } #ifdef USE_LOOPSLIDE_HACK @@ -503,7 +502,7 @@ static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op) if (lcd->eed) { /* set for redo */ BM_mesh_elem_index_ensure(lcd->em->bm, BM_EDGE); - RNA_int_set(op->ptr, "object_index", lcd->ob_index); + RNA_int_set(op->ptr, "object_index", lcd->base_index); RNA_int_set(op->ptr, "edge_index", BM_elem_index_get(lcd->eed)); /* execute */ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 9df03a81762..5344537e2d1 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -67,6 +67,8 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +#include "DRW_engine.h" + #include "mesh_intern.h" /* own include */ /* use bmesh operator flags for a few operators */ @@ -196,7 +198,87 @@ void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag) /** \name Back-Buffer OpenGL Selection * \{ */ -/* set in drawobject.c ... for colorindices */ +struct EDBMBaseOffset { + uint face; + uint edge; + uint vert; +}; + +static struct EDBMBaseOffset *base_array_index_offsets = NULL; + +static void edbm_select_pick_cache_alloc(uint bases_len) +{ + BLI_assert(base_array_index_offsets == NULL); + base_array_index_offsets = MEM_mallocN(sizeof(struct EDBMBaseOffset) * bases_len, __func__); +} + +static void edbm_select_pick_cache_free(void) +{ + MEM_SAFE_FREE(base_array_index_offsets); +} + +static bool check_ob_drawface_dot(short select_mode, View3D *vd, char dt) +{ + if ((select_mode & SCE_SELECT_FACE) == 0) { + return false; + } + + /* if its drawing textures with zbuf sel, then don't draw dots */ + if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) { + return false; + } + + return true; +} + +static void edbm_select_pick_draw_bases(ViewContext *vc, + Base **bases, + uint bases_len, + short select_mode) +{ + Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id); + DRW_framebuffer_select_id_setup(vc->ar, true); + + uint offset = 0; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, bases[base_index]->object); + struct EDBMBaseOffset *base_ofs = &base_array_index_offsets[base_index]; + + bool draw_facedot = check_ob_drawface_dot(select_mode, vc->v3d, ob_eval->dt); + + DRW_draw_select_id_object(scene_eval, + vc->rv3d, + ob_eval, + select_mode, + draw_facedot, + offset, + &base_ofs->vert, + &base_ofs->edge, + &base_ofs->face); + + offset = base_ofs->vert; + } + + DRW_framebuffer_select_id_release(vc->ar); +} + +static uint edbm_select_pick_base_index_find(uint bases_len, uint elem_index, uint *r_offset) +{ + *r_offset = 0; + uint base_index = 0; + for (; base_index < bases_len; base_index++) { + struct EDBMBaseOffset *base_ofs = &base_array_index_offsets[base_index]; + if (base_ofs->vert > elem_index) { + break; + } + *r_offset = base_ofs->vert; + } + + *r_offset += 1; + return base_index; +} + +/* set in view3d_draw_legacy.c ... for colorindices */ unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0; /* facilities for box select and circle select */ @@ -217,6 +299,7 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma return false; } + ED_view3d_select_id_validate(vc); buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; @@ -303,6 +386,7 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, return false; } + ED_view3d_select_id_validate(vc); buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; @@ -354,6 +438,8 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) xmax = xs + rads; ymin = ys - rads; ymax = ys + rads; + + ED_view3d_select_id_validate(vc); buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL); if ((buf == NULL) || (bm_vertoffs == 0)) { return false; @@ -470,29 +556,46 @@ static void findnearestvert__doClosest(void *userData, BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, float *r_dist, const bool use_select_bias, - bool use_cycle) + bool use_cycle, + Base **bases, + uint bases_len, + uint *r_base_index) { - BMesh *bm = vc->em->bm; + uint base_index = 0; if (!XRAY_FLAG_ENABLED(vc->v3d)) { uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); - unsigned int index; + uint index, offset; BMVert *eve; /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ { - FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX) - ; - ED_view3d_select_id_validate_with_select_mode(vc, select_mode); + FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX); + + edbm_select_pick_cache_alloc(bases_len); + edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode); + + index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px); + + if (index) { + base_index = edbm_select_pick_base_index_find(bases_len, index, &offset); + ED_view3d_viewcontext_init_object(vc, bases[base_index]->object); + eve = BM_vert_at_index_find_or_table(vc->em->bm, index - offset); + } + else { + eve = NULL; + } - index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_wireoffs, 0xFFFFFF, &dist_px); - eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; + edbm_select_pick_cache_free(); FAKE_SELECT_MODE_END(vc, fake_select_mode); } if (eve) { if (dist_px < *r_dist) { + if (r_base_index) { + *r_base_index = base_index; + } *r_dist = dist_px; return eve; } @@ -509,7 +612,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, if ((use_cycle == false) || (prev_select_elem && - (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index)))) { + (prev_select_elem != BM_vert_at_index_find_or_table(vc->em->bm, prev_select_index)))) { prev_select_index = 0; prev_select_elem = NULL; } @@ -518,14 +621,26 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, data.mval_fl[1] = vc->mval[1]; data.use_select_bias = use_select_bias; data.use_cycle = use_cycle; - data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; data.cycle_index_prev = prev_select_index; - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag); + for (; base_index < bases_len; base_index++) { + Base *base_iter = bases[base_index]; + ED_view3d_viewcontext_init_object(vc, base_iter->object); + data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = + *r_dist; - hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit; - *r_dist = hit->dist; + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag); + + hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit; + + if (hit->dist < *r_dist) { + if (r_base_index) { + *r_base_index = base_index; + } + *r_dist = hit->dist; + } + } prev_select_elem = hit->vert; prev_select_index = hit->index; @@ -536,7 +651,8 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist) { - return EDBM_vert_find_nearest_ex(vc, r_dist, false, false); + Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); + return EDBM_vert_find_nearest_ex(vc, r_dist, false, false, &base, 1, NULL); } /* find the distance to the edge we already have */ @@ -659,23 +775,37 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, float *r_dist_center, const bool use_select_bias, const bool use_cycle, - BMEdge **r_eed_zbuf) + BMEdge **r_eed_zbuf, + Base **bases, + uint bases_len, + uint *r_base_index) { - BMesh *bm = vc->em->bm; + uint base_index = 0; if (!XRAY_FLAG_ENABLED(vc->v3d)) { uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); - unsigned int index; + uint index, offset; BMEdge *eed; /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ { - FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_EDGE) - ; - ED_view3d_select_id_validate_with_select_mode(vc, select_mode); + FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE); + + edbm_select_pick_cache_alloc(bases_len); + edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode); + + index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px); - index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_solidoffs, bm_wireoffs, &dist_px); - eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; + if (index) { + base_index = edbm_select_pick_base_index_find(bases_len, index, &offset); + ED_view3d_viewcontext_init_object(vc, bases[base_index]->object); + eed = BM_edge_at_index_find_or_table(vc->em->bm, index - offset); + } + else { + eed = NULL; + } + + edbm_select_pick_cache_free(); FAKE_SELECT_MODE_END(vc, fake_select_mode); } @@ -704,6 +834,9 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, if (eed) { if (dist_px < *r_dist) { + if (r_base_index) { + *r_base_index = base_index; + } *r_dist = dist_px; return eed; } @@ -721,7 +854,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, if ((use_cycle == false) || (prev_select_elem && - (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index)))) { + (prev_select_elem != BM_edge_at_index_find_or_table(vc->em->bm, prev_select_index)))) { prev_select_index = 0; prev_select_elem = NULL; } @@ -731,14 +864,27 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, data.mval_fl[1] = vc->mval[1]; data.use_select_bias = use_select_bias; data.use_cycle = use_cycle; - data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; data.cycle_index_prev = prev_select_index; - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag); + for (; base_index < bases_len; base_index++) { + Base *base_iter = bases[base_index]; + ED_view3d_viewcontext_init_object(vc, base_iter->object); + data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = + *r_dist; + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag); + + hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; + + if (hit->dist < *r_dist) { + if (r_base_index) { + *r_base_index = base_index; + } + *r_dist = hit->dist; + } + } - hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; - *r_dist = hit->dist; if (r_dist_center) { *r_dist_center = hit->dist_center; } @@ -752,7 +898,8 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) { - return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL); + Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); + return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL, &base, 1, NULL); } /* find the distance to the face we already have */ @@ -832,22 +979,36 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, float *r_dist_center, const bool use_select_bias, const bool use_cycle, - BMFace **r_efa_zbuf) + BMFace **r_efa_zbuf, + Base **bases, + uint bases_len, + uint *r_base_index) { - BMesh *bm = vc->em->bm; + uint base_index = 0; if (!XRAY_FLAG_ENABLED(vc->v3d)) { float dist_test = 0.0f; - unsigned int index; + uint index, offset; BMFace *efa; { - FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_FACE) - ; - ED_view3d_select_id_validate_with_select_mode(vc, select_mode); + FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE); + + edbm_select_pick_cache_alloc(bases_len); + edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode); index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]); - efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; + + if (index) { + base_index = edbm_select_pick_base_index_find(bases_len, index, &offset); + ED_view3d_viewcontext_init_object(vc, bases[base_index]->object); + efa = BM_face_at_index_find_or_table(vc->em->bm, index - offset); + } + else { + efa = NULL; + } + + edbm_select_pick_cache_free(); FAKE_SELECT_MODE_END(vc, fake_select_mode); } @@ -876,6 +1037,9 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, if (efa) { if (dist_test < *r_dist) { + if (r_base_index) { + *r_base_index = base_index; + } *r_dist = dist_test; return efa; } @@ -892,7 +1056,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, if ((use_cycle == false) || (prev_select_elem && - (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index)))) { + (prev_select_elem != BM_face_at_index_find_or_table(vc->em->bm, prev_select_index)))) { prev_select_index = 0; prev_select_elem = NULL; } @@ -901,14 +1065,28 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, data.mval_fl[1] = vc->mval[1]; data.use_select_bias = use_select_bias; data.use_cycle = use_cycle; - data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; data.cycle_index_prev = prev_select_index; - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag); + for (; base_index < bases_len; base_index++) { + Base *base_iter = bases[base_index]; + ED_view3d_viewcontext_init_object(vc, base_iter->object); + + data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = + *r_dist; + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag); + + hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit; + + if (hit->dist < *r_dist) { + if (r_base_index) { + *r_base_index = base_index; + } + *r_dist = hit->dist; + } + } - hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit; - *r_dist = hit->dist; if (r_dist_center) { *r_dist_center = hit->dist; } @@ -922,7 +1100,8 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) { - return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL); + Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact); + return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL, &base, 1, NULL); } #undef FIND_NEAR_SELECT_BIAS @@ -965,75 +1144,64 @@ static bool unified_findnearest(ViewContext *vc, } f, f_zbuf; } hit = {{NULL}}; - /* TODO(campbell): perform selection as one pass - * instead of many smaller passes (which doesn't work for zbuf occlusion). */ - /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ + short selectmode = vc->scene->toolsettings->selectmode; - if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) { + if ((dist > 0.0f) && (selectmode & SCE_SELECT_FACE)) { float dist_center = 0.0f; float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL; - for (uint base_index = 0; base_index < bases_len; base_index++) { - Base *base_iter = bases[base_index]; - Object *obedit = base_iter->object; - ED_view3d_viewcontext_init_object(vc, obedit); - BLI_assert(vc->em->selectmode == em->selectmode); - BMFace *efa_zbuf = NULL; - BMFace *efa_test = EDBM_face_find_nearest_ex( - vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf); - if (efa_test && dist_center_p) { - dist = min_ff(dist_margin, dist_center); - } - if (efa_test) { - hit.f.base_index = base_index; - hit.f.ele = efa_test; - } - if (efa_zbuf) { - hit.f_zbuf.base_index = base_index; - hit.f_zbuf.ele = efa_zbuf; - } - } /* bases */ + uint base_index = 0; + BMFace *efa_zbuf = NULL; + BMFace *efa_test = EDBM_face_find_nearest_ex( + vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf, bases, bases_len, &base_index); + + if (efa_test && dist_center_p) { + dist = min_ff(dist_margin, dist_center); + } + if (efa_test) { + hit.f.base_index = base_index; + hit.f.ele = efa_test; + } + if (efa_zbuf) { + hit.f_zbuf.base_index = base_index; + hit.f_zbuf.ele = efa_zbuf; + } } - if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { + if ((dist > 0.0f) && (selectmode & SCE_SELECT_EDGE)) { float dist_center = 0.0f; float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL; - for (uint base_index = 0; base_index < bases_len; base_index++) { - Base *base_iter = bases[base_index]; - Object *obedit = base_iter->object; - ED_view3d_viewcontext_init_object(vc, obedit); - BMEdge *eed_zbuf = NULL; - BMEdge *eed_test = EDBM_edge_find_nearest_ex( - vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf); - if (eed_test && dist_center_p) { - dist = min_ff(dist_margin, dist_center); - } - if (eed_test) { - hit.e.base_index = base_index; - hit.e.ele = eed_test; - } - if (eed_zbuf) { - hit.e_zbuf.base_index = base_index; - hit.e_zbuf.ele = eed_zbuf; - } - } /* bases */ + uint base_index = 0; + BMEdge *eed_zbuf = NULL; + BMEdge *eed_test = EDBM_edge_find_nearest_ex( + vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf, bases, bases_len, &base_index); + + if (eed_test && dist_center_p) { + dist = min_ff(dist_margin, dist_center); + } + if (eed_test) { + hit.e.base_index = base_index; + hit.e.ele = eed_test; + } + if (eed_zbuf) { + hit.e_zbuf.base_index = base_index; + hit.e_zbuf.ele = eed_zbuf; + } } - if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) { - for (uint base_index = 0; base_index < bases_len; base_index++) { - Base *base_iter = bases[base_index]; - Object *obedit = base_iter->object; - ED_view3d_viewcontext_init_object(vc, obedit); - BMVert *eve_test = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle); - if (eve_test) { - hit.v.base_index = base_index; - hit.v.ele = eve_test; - } - } /* bases */ + if ((dist > 0.0f) && (selectmode & SCE_SELECT_VERTEX)) { + uint base_index = 0; + BMVert *eve_test = EDBM_vert_find_nearest_ex( + vc, &dist, true, use_cycle, bases, bases_len, &base_index); + + if (eve_test) { + hit.v.base_index = base_index; + hit.v.ele = eve_test; + } } /* return only one of 3 pointers, for frontbuffer redraws */ diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 2181bf01583..331be744932 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -1124,7 +1124,7 @@ static int edbm_mark_sharp_exec(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; - if (bm->totedgesel == 0) { + if ((use_verts && bm->totvertsel == 0) || (!use_verts && bm->totedgesel == 0)) { continue; } @@ -8955,7 +8955,6 @@ void MESH_OT_smoothen_normals(struct wmOperatorType *ot) static int edbm_mod_weighted_strength_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; @@ -8974,7 +8973,7 @@ static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op) const int cd_prop_int_offset = CustomData_get_n_offset( &bm->pdata, CD_PROP_INT, cd_prop_int_index); - const int face_strength = scene->toolsettings->face_strength; + const int face_strength = RNA_enum_get(op->ptr, "face_strength"); const bool set = RNA_boolean_get(op->ptr, "set"); BM_mesh_elem_index_ensure(bm, BM_FACE); @@ -9003,6 +9002,13 @@ static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static const EnumPropertyItem prop_mesh_face_strength_types[] = { + {FACE_STRENGTH_WEAK, "WEAK", 0, "Weak", ""}, + {FACE_STRENGTH_MEDIUM, "MEDIUM", 0, "Medium", ""}, + {FACE_STRENGTH_STRONG, "STRONG", 0, "Strong", ""}, + {0, NULL, 0, NULL, NULL}, +}; + void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot) { /* identifiers */ @@ -9018,5 +9024,12 @@ void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; ot->prop = RNA_def_boolean(ot->srna, "set", 0, "Set value", "Set Value of faces"); - RNA_def_property_flag(ot->prop, PROP_HIDDEN); + + ot->prop = RNA_def_enum( + ot->srna, + "face_strength", + prop_mesh_face_strength_types, + FACE_STRENGTH_MEDIUM, + "Face Strength", + "Strength to use for assigning or selecting face influence for weighted normal modifier"); } diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index c32fef42d27..e29cfa6b6e0 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -1109,13 +1109,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, } ED_view3d_viewcontext_init(C, &vc); + ED_view3d_select_id_validate(&vc); if (dist_px) { /* sample rect to increase chances of selecting, so that when clicking * on an edge in the backbuf, we can still select a face */ - - ED_view3d_select_id_validate(&vc); - *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totpoly + 1, &dist_px); } else { @@ -1291,14 +1289,12 @@ bool ED_mesh_pick_vert( } ED_view3d_viewcontext_init(C, &vc); + ED_view3d_select_id_validate(&vc); if (use_zbuf) { if (dist_px > 0) { /* sample rect to increase chances of selecting, so that when clicking * on an face in the backbuf, we can still select a vert */ - - ED_view3d_select_id_validate(&vc); - *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totvert + 1, &dist_px); } else { diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index 54143822b61..18ff7ae1a5e 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -738,7 +738,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese } const uint hit_object = hitresult & 0xFFFF; - if (vc.obedit->select_id != hit_object) { + if (vc.obedit->runtime.select_id != hit_object) { continue; } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index f8a13579732..f8760f93f2f 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -161,6 +161,18 @@ static EnumPropertyItem lightprobe_type_items[] = { {0, NULL, 0, NULL, NULL}, }; +enum ObjectAlign { + ALIGN_WORLD, + ALIGN_VIEW, + ALIGN_CURSOR, +} ALIGN_OPTIONS; + +static const EnumPropertyItem align_options[] = { + {ALIGN_WORLD, "WORLD", 0, "World", "Align the new object to the world"}, + {ALIGN_VIEW, "VIEW", 0, "View", "Align the new object to the view"}, + {ALIGN_CURSOR, "CURSOR", 0, "3D Cursor", "Use the 3D cursor orientation for the new object"}, + {0, NULL, 0, NULL, NULL}}; + /************************** Exported *****************************/ void ED_object_location_from_view(bContext *C, float loc[3]) @@ -291,16 +303,15 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode) { PropertyRNA *prop; - /* note: this property gets hidden for add-camera operator */ - prop = RNA_def_boolean( - ot->srna, "view_align", 0, "Align to View", "Align the new object to the view"); - RNA_def_property_update_runtime(prop, view_align_update); - if (do_editmode) { prop = RNA_def_boolean( ot->srna, "enter_editmode", 0, "Enter Editmode", "Enter editmode when adding this object"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } + /* note: this property gets hidden for add-camera operator */ + prop = RNA_def_enum( + ot->srna, "align", align_options, ALIGN_WORLD, "Align", "The alignment of the new object"); + RNA_def_property_update_runtime(prop, view_align_update); prop = RNA_def_float_vector_xyz(ot->srna, "location", @@ -392,23 +403,42 @@ bool ED_object_add_generic_get_opts(bContext *C, rot = _rot; } + prop = RNA_struct_find_property(op->ptr, "align"); + int alignment = RNA_property_enum_get(op->ptr, prop); + bool alignment_set = RNA_property_is_set(op->ptr, prop); + if (RNA_struct_property_is_set(op->ptr, "rotation")) { *is_view_aligned = false; } - else if (RNA_struct_property_is_set(op->ptr, "view_align")) { - *is_view_aligned = RNA_boolean_get(op->ptr, "view_align"); + else if (alignment_set) { + *is_view_aligned = alignment == ALIGN_VIEW; } else { *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0; - RNA_boolean_set(op->ptr, "view_align", *is_view_aligned); + if (*is_view_aligned) { + RNA_property_enum_set(op->ptr, prop, ALIGN_VIEW); + alignment = ALIGN_VIEW; + } + else if (U.flag & USER_ADD_CURSORALIGNED) { + RNA_property_enum_set(op->ptr, prop, ALIGN_CURSOR); + alignment = ALIGN_CURSOR; + } } - if (*is_view_aligned) { - ED_object_rotation_from_view(C, rot, view_align_axis); - RNA_float_set_array(op->ptr, "rotation", rot); - } - else { - RNA_float_get_array(op->ptr, "rotation", rot); + switch (alignment) { + case ALIGN_WORLD: + RNA_float_get_array(op->ptr, "rotation", rot); + break; + case ALIGN_VIEW: + ED_object_rotation_from_view(C, rot, view_align_axis); + RNA_float_set_array(op->ptr, "rotation", rot); + break; + case ALIGN_CURSOR: { + const Scene *scene = CTX_data_scene(C); + copy_v3_v3(rot, scene->cursor.rotation_euler); + RNA_float_set_array(op->ptr, "rotation", rot); + break; + } } } @@ -690,7 +720,7 @@ static int object_camera_add_exec(bContext *C, wmOperator *op) float loc[3], rot[3]; /* force view align for cameras */ - RNA_boolean_set(op->ptr, "view_align", true); + RNA_enum_set(op->ptr, "align", ALIGN_VIEW); if (!ED_object_add_generic_get_opts( C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) { @@ -732,7 +762,7 @@ void OBJECT_OT_camera_add(wmOperatorType *ot) ED_object_add_generic_props(ot, true); /* hide this for cameras, default */ - prop = RNA_struct_type_find_property(ot->srna, "view_align"); + prop = RNA_struct_type_find_property(ot->srna, "align"); RNA_def_property_flag(prop, PROP_HIDDEN); } @@ -1176,7 +1206,6 @@ static const char *get_light_defname(int type) static int object_light_add_exec(bContext *C, wmOperator *op) { - Scene *scene = CTX_data_scene(C); Object *ob; Light *la; int type = RNA_enum_get(op->ptr, "type"); @@ -1207,9 +1236,8 @@ static int object_light_add_exec(bContext *C, wmOperator *op) la = (Light *)ob->data; la->type = type; - if (BKE_scene_uses_cycles(scene)) { - ED_node_shader_default(C, &la->id); - la->use_nodes = true; + if (type == LA_SUN) { + la->energy = 1.0f; } return OPERATOR_FINISHED; @@ -1656,7 +1684,7 @@ static void make_object_duplilist_real( for (dob = lb_duplis->first; dob; dob = dob->next) { Object *ob_src = DEG_get_original_object(dob->ob); - Object *ob_dst = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, ob_src)); + Object *ob_dst = ID_NEW_SET(ob_src, BKE_object_copy(bmain, ob_src)); Base *base_dst; /* font duplis can have a totcol without material, we get them from parent @@ -2481,7 +2509,7 @@ static int add_named_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - basen->object->restrictflag &= ~OB_RESTRICT_VIEW; + basen->object->restrictflag &= ~OB_RESTRICT_VIEWPORT; if (event) { ARegion *ar = CTX_wm_region(C); diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 5ae757cac56..da95db92332 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -277,7 +277,8 @@ static bool write_internal_bake_pixels(Image *image, RE_bake_margin(ibuf, mask_buffer, margin); } - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_BITMAPDIRTY; + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + BKE_image_mark_dirty(image, ibuf); if (ibuf->rect_float) { ibuf->userflags |= IB_RECT_INVALID; diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 078135f46ff..abdf64af595 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -2025,8 +2025,8 @@ static const EnumPropertyItem *object_constraint_add_itemf(bContext *UNUSED(C), EnumPropertyItem *object_constraint_items = NULL; int totitem = 0; - while(item->identifier) { - if((item->value != CONSTRAINT_TYPE_KINEMATIC) && (item->value != CONSTRAINT_TYPE_SPLINEIK)) { + while (item->identifier) { + if ((item->value != CONSTRAINT_TYPE_KINEMATIC) && (item->value != CONSTRAINT_TYPE_SPLINEIK)) { RNA_enum_item_add(&object_constraint_items, &totitem, item); } item++; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 795e1dd66a5..9fba0d89c4a 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -314,7 +314,7 @@ void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout) continue; } - if (lc->collection->flag & COLLECTION_RESTRICT_VIEW) { + if (lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) { continue; } @@ -722,7 +722,7 @@ static bool editmode_toggle_poll(bContext *C) } /* if hidden but in edit mode, we still display */ - if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) { + if ((ob->restrictflag & OB_RESTRICT_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)) { return 0; } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 09bcc0a3058..1e85c895f71 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -356,7 +356,7 @@ static int screen_render_exec(bContext *C, wmOperator *op) /* cleanup sequencer caches before starting user triggered render. * otherwise, invalidated cache entries can make their way into - * the output rendering. We can't put that into RE_BlenderFrame, + * the output rendering. We can't put that into RE_RenderFrame, * since sequence rendering can call that recursively... (peter) */ BKE_sequencer_cache_cleanup(scene); @@ -364,18 +364,17 @@ static int screen_render_exec(bContext *C, wmOperator *op) BLI_threaded_malloc_begin(); if (is_animation) { - RE_BlenderAnim(re, - mainp, - scene, - single_layer, - camera_override, - scene->r.sfra, - scene->r.efra, - scene->r.frame_step); + RE_RenderAnim(re, + mainp, + scene, + single_layer, + camera_override, + scene->r.sfra, + scene->r.efra, + scene->r.frame_step); } else { - RE_BlenderFrame( - re, mainp, scene, single_layer, camera_override, scene->r.cfra, is_write_still); + RE_RenderFrame(re, mainp, scene, single_layer, camera_override, scene->r.cfra, is_write_still); } BLI_threaded_malloc_end(); @@ -671,23 +670,23 @@ static void render_startjob(void *rjv, short *stop, short *do_update, float *pro RE_SetReports(rj->re, rj->reports); if (rj->anim) { - RE_BlenderAnim(rj->re, + RE_RenderAnim(rj->re, + rj->main, + rj->scene, + rj->single_layer, + rj->camera_override, + rj->scene->r.sfra, + rj->scene->r.efra, + rj->scene->r.frame_step); + } + else { + RE_RenderFrame(rj->re, rj->main, rj->scene, rj->single_layer, rj->camera_override, - rj->scene->r.sfra, - rj->scene->r.efra, - rj->scene->r.frame_step); - } - else { - RE_BlenderFrame(rj->re, - rj->main, - rj->scene, - rj->single_layer, - rj->camera_override, - rj->scene->r.cfra, - rj->write_still); + rj->scene->r.cfra, + rj->write_still); } RE_SetReports(rj->re, NULL); @@ -976,7 +975,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even /* cleanup sequencer caches before starting user triggered render. * otherwise, invalidated cache entries can make their way into - * the output rendering. We can't put that into RE_BlenderFrame, + * the output rendering. We can't put that into RE_RenderFrame, * since sequence rendering can call that recursively... (peter) */ BKE_sequencer_cache_cleanup(scene); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 64f20a4a348..e082e961b45 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -270,7 +270,7 @@ static const char *preview_collection_name(const char pr_type) case MA_FLUID: return "Fluid"; case MA_SPHERE_A: - return "World Shader Ball"; + return "World Sphere"; case MA_LAMP: return "Lamp"; case MA_SKY: @@ -437,7 +437,14 @@ static Scene *preview_prepare_scene( sce->world->horb = 0.05f; } - set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method); + if (sp->pr_method == PR_ICON_RENDER && sp->pr_main == G_pr_main_grease_pencil) { + /* For grease pencil, always use sphere for icon renders. */ + set_preview_visibility(sce, view_layer, MA_SPHERE_A, sp->pr_method); + } + else { + /* Use specified preview shape for both preview panel and icon previews. */ + set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method); + } if (sp->pr_method != PR_ICON_RENDER) { if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) { diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 8c73f4cd649..c2f9beb5d78 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -50,6 +50,7 @@ #include "ED_screen.h" #include "ED_screen_types.h" #include "ED_space_api.h" +#include "ED_time_scrub_ui.h" #include "GPU_immediate.h" #include "GPU_immediate_util.h" @@ -202,7 +203,7 @@ static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, f alpha = min_ff(alpha, 0.75f); - UI_icon_draw_aspect(x, y, ICON_FULLSCREEN_EXIT, 0.7f / UI_DPI_FAC, alpha, NULL); + UI_icon_draw_ex(x, y, ICON_FULLSCREEN_EXIT, 0.7f * U.inv_dpi_fac, 0.0f, alpha, NULL, false); /* debug drawing : * The click_rect is the same as defined in fullscreen_click_rcti_init @@ -1058,11 +1059,11 @@ static void region_azones_scrollbars_initialize(ScrArea *sa, ARegion *ar) { const View2D *v2d = &ar->v2d; - if ((v2d->scroll & V2D_SCROLL_VERTICAL) && ((v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0)) { + if ((v2d->scroll & V2D_SCROLL_VERTICAL) && ((v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) == 0)) { region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_VERT); } if ((v2d->scroll & V2D_SCROLL_HORIZONTAL) && - ((v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0)) { + ((v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) == 0)) { region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_HOR); } } @@ -1604,14 +1605,19 @@ static void ed_default_handlers( wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D", 0, 0); WM_event_add_keymap_handler(handlers, keymap); } - if (flag & ED_KEYMAP_MARKERS) { + if (flag & ED_KEYMAP_ANIMATION) { + wmKeyMap *keymap; + /* time-markers */ - wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0); + keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0); WM_event_add_keymap_handler_poll(handlers, keymap, event_in_markers_region); - } - if (flag & ED_KEYMAP_ANIMATION) { + + /* time-scrubbing */ + keymap = WM_keymap_ensure(wm->defaultconf, "Scrubbing", 0, 0); + WM_event_add_keymap_handler_poll(handlers, keymap, ED_event_in_scrubbing_region); + /* frame changing and timeline operators (for time spaces) */ - wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0); + keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0); WM_event_add_keymap_handler(handlers, keymap); } if (flag & ED_KEYMAP_FRAMES) { @@ -1621,14 +1627,19 @@ static void ed_default_handlers( } if (flag & ED_KEYMAP_HEADER) { /* standard keymap for headers regions */ - wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Header", 0, 0); + wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0); WM_event_add_keymap_handler(handlers, keymap); } if (flag & ED_KEYMAP_FOOTER) { /* standard keymap for footer regions */ - wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Footer", 0, 0); + wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0); WM_event_add_keymap_handler(handlers, keymap); } + if (flag & ED_KEYMAP_NAVBAR) { + /* standard keymap for Navigation bar regions */ + wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); + } /* Keep last because of LMB/RMB handling, see: T57527. */ if (flag & ED_KEYMAP_GPENCIL) { @@ -2289,34 +2300,62 @@ static void ed_panel_draw(const bContext *C, * Matching against any of these strings will draw the panel. * Can be NULL to skip context checks. */ -void ED_region_panels_layout_ex( - const bContext *C, ARegion *ar, const char *contexts[], int contextnr, const bool vertical) +void ED_region_panels_layout_ex(const bContext *C, + ARegion *ar, + ListBase *paneltypes, + const char *contexts[], + int contextnr, + const bool vertical, + const char *category_override) { + /* collect panels to draw */ + WorkSpace *workspace = CTX_wm_workspace(C); + LinkNode *panel_types_stack = NULL; + for (PanelType *pt = paneltypes->last; pt; pt = pt->prev) { + /* Only draw top level panels. */ + if (pt->parent) { + continue; + } + + if (category_override) { + if (!STREQ(pt->category, category_override)) { + continue; + } + } + + /* verify context */ + if (contexts && pt->context[0] && !streq_array_any(pt->context, contexts)) { + continue; + } + + /* If we're tagged, only use compatible. */ + if (pt->owner_id[0] && BKE_workspace_owner_id_check(workspace, pt->owner_id) == false) { + continue; + } + + /* draw panel */ + if (pt->draw && (!pt->poll || pt->poll(C, pt))) { + BLI_linklist_prepend_alloca(&panel_types_stack, pt); + } + } + ar->runtime.category = NULL; - const WorkSpace *workspace = CTX_wm_workspace(C); ScrArea *sa = CTX_wm_area(C); - PanelType *pt; View2D *v2d = &ar->v2d; int x, y, w, em; - bool is_context_new = 0; - int scroll; /* XXX, should use some better check? */ /* For now also has hardcoded check for clip editor until it supports actual toolbar. */ - bool use_category_tabs = ((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) || - (ar->regiontype == RGN_TYPE_TOOLS && sa->spacetype == SPACE_CLIP); + bool use_category_tabs = (category_override == NULL) && + ((((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) || + (ar->regiontype == RGN_TYPE_TOOLS && sa->spacetype == SPACE_CLIP))); /* offset panels for small vertical tab area */ const char *category = NULL; const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH; int margin_x = 0; const bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE; - - BLI_SMALLSTACK_DECLARE(pt_stack, PanelType *); - - if (contextnr != -1) { - is_context_new = UI_view2d_tab_set(v2d, contextnr); - } + const bool is_context_new = (contextnr != -1) ? UI_view2d_tab_set(v2d, contextnr) : false; /* before setting the view */ if (vertical) { @@ -2334,45 +2373,21 @@ void ED_region_panels_layout_ex( v2d->scroll |= (V2D_SCROLL_BOTTOM); v2d->scroll &= ~(V2D_SCROLL_RIGHT); } - - scroll = v2d->scroll; - - /* collect panels to draw */ - for (pt = ar->type->paneltypes.last; pt; pt = pt->prev) { - /* Only draw top level panels. */ - if (pt->parent) { - continue; - } - - /* verify context */ - if (contexts && pt->context[0] && !streq_array_any(pt->context, contexts)) { - continue; - } - - /* If we're tagged, only use compatible. */ - if (pt->owner_id[0] && BKE_workspace_owner_id_check(workspace, pt->owner_id) == false) { - continue; - } - - /* draw panel */ - if (pt->draw && (!pt->poll || pt->poll(C, pt))) { - BLI_SMALLSTACK_PUSH(pt_stack, pt); - } - } + const int scroll = v2d->scroll; /* collect categories */ if (use_category_tabs) { UI_panel_category_clear_all(ar); /* gather unique categories */ - BLI_SMALLSTACK_ITER_BEGIN (pt_stack, pt) { + for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) { + PanelType *pt = pt_link->link; if (pt->category[0]) { if (!UI_panel_category_find(ar, pt->category)) { UI_panel_category_add(ar, pt->category); } } } - BLI_SMALLSTACK_ITER_END; if (!UI_panel_category_is_visible(ar)) { use_category_tabs = false; @@ -2400,7 +2415,8 @@ void ED_region_panels_layout_ex( /* set view2d view matrix - UI_block_begin() stores it */ UI_view2d_view_ortho(v2d); - BLI_SMALLSTACK_ITER_BEGIN (pt_stack, pt) { + for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) { + PanelType *pt = pt_link->link; Panel *panel = UI_panel_find_by_type(&ar->panels, pt); if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) { @@ -2411,7 +2427,6 @@ void ED_region_panels_layout_ex( ed_panel_draw(C, sa, ar, &ar->panels, pt, panel, w, em, vertical); } - BLI_SMALLSTACK_ITER_END; /* align panels and return size */ UI_panels_end(C, ar, &x, &y); @@ -2482,9 +2497,11 @@ void ED_region_panels_layout_ex( ar->runtime.category = category; } } + void ED_region_panels_layout(const bContext *C, ARegion *ar) { - ED_region_panels_layout_ex(C, ar, NULL, -1, true); + bool vertical = true; + ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, NULL, -1, vertical, NULL); } void ED_region_panels_draw(const bContext *C, ARegion *ar) @@ -2533,7 +2550,7 @@ void ED_region_panels_ex( const bContext *C, ARegion *ar, const char *contexts[], int contextnr, const bool vertical) { /* TODO: remove? */ - ED_region_panels_layout_ex(C, ar, contexts, contextnr, vertical); + ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, contexts, contextnr, vertical, NULL); ED_region_panels_draw(C, ar); } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 61fa05f243f..af90bbc9975 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -67,7 +67,6 @@ #include "WM_types.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "ED_anim_api.h" #include "ED_armature.h" @@ -343,7 +342,7 @@ bool ED_operator_console_active(bContext *C) static bool ed_object_hidden(Object *ob) { /* if hidden but in edit mode, we still display, can happen with animation */ - return ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)); + return ((ob->restrictflag & OB_RESTRICT_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)); } bool ED_operator_object_active(bContext *C) @@ -632,24 +631,6 @@ static bool screen_active_editable(bContext *C) return 0; } -static ARegion *screen_find_region_type(bContext *C, int type) -{ - ARegion *ar = CTX_wm_region(C); - - /* find the header region - * - try context first, but upon failing, search all regions in area... - */ - if ((ar == NULL) || (ar->regiontype != type)) { - ScrArea *sa = CTX_wm_area(C); - ar = BKE_area_find_region_type(sa, type); - } - else { - ar = NULL; - } - - return ar; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -2771,7 +2752,7 @@ static int frame_offset_exec(bContext *C, wmOperator *op) areas_do_frame_follow(C, false); - BKE_sound_update_and_seek(bmain, CTX_data_depsgraph(C)); + BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); @@ -2833,7 +2814,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op) areas_do_frame_follow(C, true); - BKE_sound_update_and_seek(bmain, CTX_data_depsgraph(C)); + BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } @@ -2949,7 +2930,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) else { areas_do_frame_follow(C, true); - BKE_sound_update_and_seek(bmain, CTX_data_depsgraph(C)); + BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); @@ -3016,7 +2997,7 @@ static int marker_jump_exec(bContext *C, wmOperator *op) areas_do_frame_follow(C, true); - BKE_sound_update_and_seek(bmain, CTX_data_depsgraph(C)); + BKE_sound_seek_scene(bmain, scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); @@ -3956,10 +3937,10 @@ static void SCREEN_OT_header_toggle_menus(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Header Tools Operator +/** \name Region Context Menu Operator (Header/Footer/Navbar) * \{ */ -static bool header_context_menu_poll(bContext *C) +static bool screen_region_context_menu_poll(bContext *C) { ScrArea *sa = CTX_wm_area(C); return (sa && sa->spacetype != SPACE_STATUSBAR); @@ -4009,89 +3990,17 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN } } -static int header_context_menu_invoke(bContext *C, - wmOperator *UNUSED(op), - const wmEvent *UNUSED(event)) -{ - uiPopupMenu *pup; - uiLayout *layout; - - pup = UI_popup_menu_begin(C, IFACE_("Header"), ICON_NONE); - layout = UI_popup_menu_layout(pup); - - ED_screens_header_tools_menu_create(C, layout, NULL); - - UI_popup_menu_end(C, pup); - - return OPERATOR_INTERFACE; -} - -static void SCREEN_OT_header_context_menu(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Header Context Menu"; - ot->description = "Display header region context menu"; - ot->idname = "SCREEN_OT_header_context_menu"; - - /* api callbacks */ - ot->poll = header_context_menu_poll; - ot->invoke = header_context_menu_invoke; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Footer Toggle Operator - * \{ */ - -static int footer_exec(bContext *C, wmOperator *UNUSED(op)) -{ - ARegion *ar = screen_find_region_type(C, RGN_TYPE_FOOTER); - - if (ar == NULL) { - return OPERATOR_CANCELLED; - } - - ar->flag ^= RGN_FLAG_HIDDEN; - - ED_area_tag_redraw(CTX_wm_area(C)); - - WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); - - return OPERATOR_FINISHED; -} - -static void SCREEN_OT_footer(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Footer"; - ot->description = "Toggle footer display"; - ot->idname = "SCREEN_OT_footer"; - - /* api callbacks */ - ot->exec = footer_exec; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Footer Tools Operator - * \{ */ - -static bool footer_context_menu_poll(bContext *C) -{ - ScrArea *sa = CTX_wm_area(C); - return sa; -} - void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg)) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); const char *but_flip_str = (ar->alignment == RGN_ALIGN_TOP) ? IFACE_("Flip to Bottom") : IFACE_("Flip to Top"); - - uiItemO(layout, IFACE_("Toggle Footer"), ICON_NONE, "SCREEN_OT_footer"); + { + PointerRNA ptr; + RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, sa->spacedata.first, &ptr); + uiItemR(layout, &ptr, "show_region_footer", 0, IFACE_("Show Footer"), ICON_NONE); + } /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); @@ -4108,51 +4017,58 @@ void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UN } } -static int footer_context_menu_invoke(bContext *C, +void ED_screens_navigation_bar_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg)) +{ + const ARegion *ar = CTX_wm_region(C); + const char *but_flip_str = (ar->alignment == RGN_ALIGN_LEFT) ? IFACE_("Flip to Right") : + IFACE_("Flip to Left"); + + /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */ + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); + + uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip"); +} + +static int screen_context_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { uiPopupMenu *pup; uiLayout *layout; + const ARegion *ar = CTX_wm_region(C); - pup = UI_popup_menu_begin(C, IFACE_("Footer"), ICON_NONE); - layout = UI_popup_menu_layout(pup); - - ED_screens_footer_tools_menu_create(C, layout, NULL); - - UI_popup_menu_end(C, pup); + if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { + pup = UI_popup_menu_begin(C, IFACE_("Header"), ICON_NONE); + layout = UI_popup_menu_layout(pup); + ED_screens_header_tools_menu_create(C, layout, NULL); + UI_popup_menu_end(C, pup); + } + else if (ar->regiontype == RGN_TYPE_FOOTER) { + pup = UI_popup_menu_begin(C, IFACE_("Footer"), ICON_NONE); + layout = UI_popup_menu_layout(pup); + ED_screens_footer_tools_menu_create(C, layout, NULL); + UI_popup_menu_end(C, pup); + } + else if (ar->regiontype == RGN_TYPE_NAV_BAR) { + pup = UI_popup_menu_begin(C, IFACE_("Navigation Bar"), ICON_NONE); + layout = UI_popup_menu_layout(pup); + ED_screens_navigation_bar_tools_menu_create(C, layout, NULL); + UI_popup_menu_end(C, pup); + } return OPERATOR_INTERFACE; } -static void SCREEN_OT_footer_context_menu(wmOperatorType *ot) +static void SCREEN_OT_region_context_menu(wmOperatorType *ot) { /* identifiers */ - ot->name = "Footer Context Menu"; - ot->description = "Display footer region context menu"; - ot->idname = "SCREEN_OT_footer_context_menu"; + ot->name = "Region Context Menu"; + ot->description = "Display region context menu"; + ot->idname = "SCREEN_OT_region_context_menu"; /* api callbacks */ - ot->poll = footer_context_menu_poll; - ot->invoke = footer_context_menu_invoke; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Navigation Bar Tools Menu - * \{ */ - -void ED_screens_navigation_bar_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg)) -{ - const ARegion *ar = CTX_wm_region(C); - const char *but_flip_str = (ar->alignment == RGN_ALIGN_LEFT) ? IFACE_("Flip to Right") : - IFACE_("Flip to Left"); - - /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */ - uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); - - uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip"); + ot->poll = screen_region_context_menu_poll; + ot->invoke = screen_context_menu_invoke; } /** \} */ @@ -4288,8 +4204,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv if (screen->animtimer && screen->animtimer == event->customdata) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + struct Depsgraph *depsgraph = CTX_data_depsgraph(C); wmTimer *wt = screen->animtimer; ScreenAnimData *sad = wt->customdata; wmWindowManager *wm = CTX_wm_manager(C); @@ -4310,7 +4225,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } if ((scene->audio.flag & AUDIO_SYNC) && (sad->flag & ANIMPLAY_FLAG_REVERSE) == false && - isfinite(time = BKE_sound_sync_scene(scene_eval))) { + isfinite(time = BKE_sound_sync_scene(scene))) { double newfra = (double)time * FPS; /* give some space here to avoid jumps */ @@ -4403,7 +4318,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } if (sad->flag & ANIMPLAY_FLAG_JUMPED) { - BKE_sound_update_and_seek(bmain, depsgraph); + BKE_sound_seek_scene(bmain, scene); #ifdef PROFILE_AUDIO_SYNCH old_frame = CFRA; #endif @@ -4525,12 +4440,11 @@ int ED_screen_animation_play(bContext *C, int sync, int mode) { bScreen *screen = CTX_wm_screen(C); Scene *scene = CTX_data_scene(C); - Scene *scene_eval = DEG_get_evaluated_scene(CTX_data_depsgraph(C)); if (ED_screen_animation_playing(CTX_wm_manager(C))) { /* stop playback now */ ED_screen_animation_timer(C, 0, 0, 0, 0); - BKE_sound_stop_scene(scene_eval); + BKE_sound_stop_scene(scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } @@ -4539,7 +4453,7 @@ int ED_screen_animation_play(bContext *C, int sync, int mode) int refresh = SPACE_ACTION; if (mode == 1) { /* XXX only play audio forwards!? */ - BKE_sound_play_scene(scene_eval); + BKE_sound_play_scene(scene); } ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode); @@ -5302,9 +5216,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(SCREEN_OT_region_scale); WM_operatortype_append(SCREEN_OT_region_flip); WM_operatortype_append(SCREEN_OT_header_toggle_menus); - WM_operatortype_append(SCREEN_OT_header_context_menu); - WM_operatortype_append(SCREEN_OT_footer); - WM_operatortype_append(SCREEN_OT_footer_context_menu); + WM_operatortype_append(SCREEN_OT_region_context_menu); WM_operatortype_append(SCREEN_OT_screen_set); WM_operatortype_append(SCREEN_OT_screen_full_area); WM_operatortype_append(SCREEN_OT_back_to_previous); diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index 2dfa05cf6b0..863e3a15120 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -373,13 +373,15 @@ static int workspace_append_activate_exec(bContext *C, wmOperator *op) &bmain->workspaces, idname, offsetof(ID, name) + 2); BLI_assert(appended_workspace != NULL); - /* Reorder to last position. */ - BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true); + if (appended_workspace) { + /* Reorder to last position. */ + BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true); - /* Changing workspace changes context. Do delayed! */ - WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace); + /* Changing workspace changes context. Do delayed! */ + WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; + } } return OPERATOR_CANCELLED; diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 5a45f4946f2..f7a589350f9 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -47,6 +47,7 @@ #include "BKE_colorband.h" #include "BKE_context.h" #include "BKE_brush.h" +#include "BKE_image.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" @@ -154,7 +155,7 @@ void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int } } - ibuf->userflags |= IB_BITMAPDIRTY; + BKE_image_mark_dirty(ima, ibuf); if (tmpibuf) { IMB_freeImBuf(tmpibuf); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 0340a4989e1..d7553d18d3b 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -1837,7 +1837,7 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty) false); } - pjIma->ibuf->userflags |= IB_BITMAPDIRTY; + BKE_image_mark_dirty(pjIma->ima, pjIma->ibuf); /* tile ready, publish */ if (tinf->lock) { BLI_spin_lock(tinf->lock); @@ -6394,7 +6394,7 @@ static const EnumPropertyItem layer_type_items[] = { {0, NULL, 0, NULL, NULL}, }; -static Image *proj_paint_image_create(wmOperator *op, Main *bmain) +static Image *proj_paint_image_create(wmOperator *op, Main *bmain, bool is_data) { Image *ima; float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; @@ -6417,6 +6417,11 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain) ima = BKE_image_add_generated( bmain, width, height, imagename, alpha ? 32 : 24, use_float, gen_type, color, false); + if (is_data) { + STRNCPY(ima->colorspace_settings.name, + IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DATA)); + } + return ima; } @@ -6487,6 +6492,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op) if (ma) { Main *bmain = CTX_data_main(C); int type = RNA_enum_get(op->ptr, "type"); + bool is_data = (type > LAYER_BASE_COLOR); bNode *imanode; bNodeTree *ntree = ma->nodetree; @@ -6501,7 +6507,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op) /* try to add an image node */ imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE); - ima = proj_paint_image_create(op, bmain); + ima = proj_paint_image_create(op, bmain, is_data); imanode->id = &ima->id; nodeSetActive(ntree, imanode); @@ -6553,12 +6559,6 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op) } } - if (type > LAYER_BASE_COLOR) { - /* This is a "non color data" image */ - NodeTexImage *tex = imanode->storage; - tex->color_space = SHD_COLORSPACE_NONE; - } - /* Check if the socket in already connected to something */ bNodeLink *link = in_sock ? in_sock->link : NULL; if (in_sock != NULL && link == NULL) { diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 6d003820723..84b4a130183 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -389,6 +389,7 @@ static int imapaint_pick_face(ViewContext *vc, } /* sample only on the exact position */ + ED_view3d_select_id_validate(vc); *r_index = ED_view3d_select_id_sample(vc, mval[0], mval[1]); if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) { diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c index c1c2964156f..c904bf2005b 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -161,7 +161,7 @@ void PAINT_OT_weight_from_bones(wmOperatorType *ot) ot->poll = weight_from_bones_poll; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; /* properties */ ot->prop = RNA_def_enum( @@ -880,7 +880,7 @@ void PAINT_OT_weight_gradient(wmOperatorType *ot) ot->cancel = WM_gesture_straightline_cancel; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; prop = RNA_def_enum(ot->srna, "type", gradient_types, 0, "Type", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); diff --git a/source/blender/editors/sound/CMakeLists.txt b/source/blender/editors/sound/CMakeLists.txt index 7f4b5a45aa3..c2a88041a85 100644 --- a/source/blender/editors/sound/CMakeLists.txt +++ b/source/blender/editors/sound/CMakeLists.txt @@ -19,7 +19,6 @@ set(INC ../include ../../blenkernel ../../blenlib - ../../depsgraph ../../makesdna ../../makesrna ../../windowmanager diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 8ac49e447fe..25c05e2d1d0 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -62,8 +62,6 @@ # include <AUD_Special.h> #endif -#include "DEG_depsgraph_query.h" - #include "ED_sound.h" #include "ED_util.h" @@ -90,6 +88,7 @@ static int sound_open_exec(bContext *C, wmOperator *op) bSound *sound; PropertyPointerRNA *pprop; PointerRNA idptr; + AUD_SoundInfo info; Main *bmain = CTX_data_main(C); RNA_string_get(op->ptr, "filepath", path); @@ -99,8 +98,29 @@ static int sound_open_exec(bContext *C, wmOperator *op) sound_open_init(C, op); } + if (sound->playback_handle == NULL) { + if (op->customdata) { + MEM_freeN(op->customdata); + } + BKE_id_free(bmain, sound); + BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); + return OPERATOR_CANCELLED; + } + + info = AUD_getInfo(sound->playback_handle); + + if (info.specs.channels == AUD_CHANNELS_INVALID) { + BKE_id_free(bmain, sound); + if (op->customdata) { + MEM_freeN(op->customdata); + } + BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); + return OPERATOR_CANCELLED; + } + if (RNA_boolean_get(op->ptr, "mono")) { sound->flags |= SOUND_FLAGS_MONO; + BKE_sound_load(bmain, sound); } if (RNA_boolean_get(op->ptr, "cache")) { @@ -120,8 +140,6 @@ static int sound_open_exec(bContext *C, wmOperator *op) RNA_property_update(C, &pprop->ptr, pprop->prop); } - DEG_relations_tag_update(bmain); - MEM_freeN(op->customdata); return OPERATOR_FINISHED; } @@ -343,9 +361,8 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op) #ifdef WITH_AUDASPACE char path[FILE_MAX]; char filename[FILE_MAX]; - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - Main *bmain = CTX_data_main(C); + Scene *scene; + Main *bmain; int split; int bitrate, accuracy; @@ -363,20 +380,18 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op) container = RNA_enum_get(op->ptr, "container"); codec = RNA_enum_get(op->ptr, "codec"); split = RNA_boolean_get(op->ptr, "split_channels"); - specs.channels = scene_eval->r.ffcodecdata.audio_channels; - specs.rate = scene_eval->r.ffcodecdata.audio_mixrate; + scene = CTX_data_scene(C); + bmain = CTX_data_main(C); + specs.channels = scene->r.ffcodecdata.audio_channels; + specs.rate = scene->r.ffcodecdata.audio_mixrate; BLI_strncpy(filename, path, sizeof(filename)); BLI_path_abs(filename, BKE_main_blendfile_path(bmain)); - const double fps = (((double)scene_eval->r.frs_sec) / (double)scene_eval->r.frs_sec_base); - const int start_frame = scene_eval->r.sfra; - const int end_frame = scene_eval->r.efra; - if (split) { - result = AUD_mixdown_per_channel(scene_eval->sound_scene, - start_frame * specs.rate / fps, - (end_frame - start_frame + 1) * specs.rate / fps, + result = AUD_mixdown_per_channel(scene->sound_scene, + SFRA * specs.rate / FPS, + (EFRA - SFRA + 1) * specs.rate / FPS, accuracy, filename, specs, @@ -385,9 +400,9 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op) bitrate); } else { - result = AUD_mixdown(scene_eval->sound_scene, - start_frame * specs.rate / fps, - (end_frame - start_frame + 1) * specs.rate / fps, + result = AUD_mixdown(scene->sound_scene, + SFRA * specs.rate / FPS, + (EFRA - SFRA + 1) * specs.rate / FPS, accuracy, filename, specs, @@ -396,7 +411,7 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op) bitrate); } - BKE_sound_reset_scene_specs(scene_eval); + BKE_sound_reset_scene_specs(scene); if (result) { BKE_report(op->reports, RPT_ERROR, result); diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c index 2a6ae93fc99..f32207fe08b 100644 --- a/source/blender/editors/space_action/action_draw.c +++ b/source/blender/editors/space_action/action_draw.c @@ -411,7 +411,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene) } GPU_matrix_push(); - GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HEIGHT_TEXT + yoffs); + GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HEIGHT_HANDLES + yoffs); GPU_matrix_scale_2f(1.0, cache_draw_height); switch (pid->type) { diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 8ecd25bda76..1371305487e 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -47,6 +47,7 @@ #include "BKE_gpencil.h" #include "UI_view2d.h" +#include "UI_interface.h" #include "ED_anim_api.h" #include "ED_gpencil.h" diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 5ac6297e108..972f19bb643 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -45,6 +45,7 @@ #include "WM_types.h" #include "WM_message.h" +#include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -52,6 +53,7 @@ #include "ED_screen.h" #include "ED_anim_api.h" #include "ED_markers.h" +#include "ED_time_scrub_ui.h" #include "action_intern.h" /* own include */ #include "GPU_framebuffer.h" @@ -69,7 +71,7 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene) saction->autosnap = SACTSNAP_FRAME; saction->mode = SACTCONT_DOPESHEET; saction->mode_prev = SACTCONT_DOPESHEET; - saction->flag = SACTION_SHOW_INTERPOLATION; + saction->flag = SACTION_SHOW_INTERPOLATION | SACTION_SHOW_MARKER_LINES; saction->ads.filterflag |= ADS_FILTER_SUMMARY; @@ -125,7 +127,7 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene) ar->v2d.minzoom = 0.01f; ar->v2d.maxzoom = 50; - ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); + ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); ar->v2d.scroll |= (V2D_SCROLL_RIGHT); ar->v2d.keepzoom = V2D_LOCKZOOM_Y; ar->v2d.keepofs = V2D_KEEPOFS_Y; @@ -234,20 +236,13 @@ static void action_main_region_draw(const bContext *C, ARegion *ar) /* reset view matrix */ UI_view2d_view_restore(C); + /* scrubbing region */ + ED_scrubbing_draw(ar, scene, saction->flag & SACTION_DRAWTIME, true); + /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); UI_view2d_scrollers_draw(v2d, scrollers); UI_view2d_scrollers_free(scrollers); - - /* frame numbers */ - UI_view2d_draw_scale_x__discrete_frames_or_seconds( - ar, v2d, &v2d->hor, scene, saction->flag & SACTION_DRAWTIME, TH_TEXT); - - /* draw current frame number-indicator on top of scrollers */ - if ((saction->flag & SACTION_NODRAWCFRANUM) == 0) { - UI_view2d_view_orthoSpecial(ar, v2d, 1); - ANIM_draw_cfra_number(C, v2d, cfra_flag); - } } /* add handlers, stuff you only do once or on area/region changes */ @@ -285,6 +280,9 @@ static void action_channel_region_draw(const bContext *C, ARegion *ar) draw_channel_names((bContext *)C, &ac, ar); } + /* channel filter next to scrubbing area */ + ED_channel_search_draw(C, ar, ac.ads); + /* reset view matrix */ UI_view2d_view_restore(C); @@ -869,7 +867,7 @@ void ED_spacetype_action(void) art->draw = action_main_region_draw; art->listener = action_main_region_listener; art->message_subscribe = saction_main_region_message_subscribe; - art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES; + art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES; BLI_addhead(&st->regiontypes, art); @@ -901,7 +899,7 @@ void ED_spacetype_action(void) /* regions: UI buttons */ art = MEM_callocN(sizeof(ARegionType), "spacetype action region"); art->regionid = RGN_TYPE_UI; - art->prefsizex = 200; + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->keymapflag = ED_KEYMAP_UI; art->listener = action_region_listener; art->init = action_buttons_area_init; diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 577f7a7af8a..fde8b8f85f8 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -785,8 +785,11 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r SpaceProperties *sbuts = CTX_wm_space_properties(C); ButsContextPath *path = sbuts ? sbuts->path : NULL; - /* A zero sized path will be set for 'BCONTEXT_TOOL'. */ - if (!path || !path->len) { + if (sbuts->mainb == BCONTEXT_TOOL) { + return 0; + } + + if (!path) { return 0; } diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index fe4ed0209bf..500efe4bb4d 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -56,15 +56,10 @@ static int context_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { - const ARegion *ar = CTX_wm_region(C); uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Context Menu"), ICON_NONE); uiLayout *layout = UI_popup_menu_layout(pup); uiItemM(layout, "INFO_MT_area", NULL, ICON_NONE); - if (ar->regiontype == RGN_TYPE_NAV_BAR) { - ED_screens_navigation_bar_tools_menu_create(C, layout, NULL); - } - UI_popup_menu_end(C, pup); return OPERATOR_INTERFACE; diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index f9244049d54..9b0150d731d 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -34,6 +34,7 @@ #include "ED_space_api.h" #include "ED_screen.h" +#include "ED_view3d.h" /* To draw toolbar UI. */ #include "WM_api.h" #include "WM_types.h" @@ -198,105 +199,7 @@ static void buttons_main_region_layout_properties(const bContext *C, } const bool vertical = true; - ED_region_panels_layout_ex(C, ar, contexts, sbuts->mainb, vertical); -} - -static void buttons_main_region_layout_tool(const bContext *C, ARegion *ar) -{ - const enum eContextObjectMode mode = CTX_data_mode_enum(C); - - const char *contexts_base[5] = {NULL}; - contexts_base[0] = ".active_tool"; - const char **contexts = &contexts_base[1]; - - /* Hard coded to 3D view. */ - { - switch (mode) { - case CTX_MODE_EDIT_MESH: - ARRAY_SET_ITEMS(contexts, ".mesh_edit"); - break; - case CTX_MODE_EDIT_CURVE: - ARRAY_SET_ITEMS(contexts, ".curve_edit"); - break; - case CTX_MODE_EDIT_SURFACE: - ARRAY_SET_ITEMS(contexts, ".curve_edit"); - break; - case CTX_MODE_EDIT_TEXT: - ARRAY_SET_ITEMS(contexts, ".text_edit"); - break; - case CTX_MODE_EDIT_ARMATURE: - ARRAY_SET_ITEMS(contexts, ".armature_edit"); - break; - case CTX_MODE_EDIT_METABALL: - ARRAY_SET_ITEMS(contexts, ".mball_edit"); - break; - case CTX_MODE_EDIT_LATTICE: - ARRAY_SET_ITEMS(contexts, ".lattice_edit"); - break; - case CTX_MODE_POSE: - ARRAY_SET_ITEMS(contexts, ".posemode"); - break; - case CTX_MODE_SCULPT: - ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode"); - break; - case CTX_MODE_PAINT_WEIGHT: - ARRAY_SET_ITEMS(contexts, ".paint_common", ".weightpaint"); - break; - case CTX_MODE_PAINT_VERTEX: - ARRAY_SET_ITEMS(contexts, ".paint_common", ".vertexpaint"); - break; - case CTX_MODE_PAINT_TEXTURE: - ARRAY_SET_ITEMS(contexts, ".paint_common", ".imagepaint"); - break; - case CTX_MODE_PARTICLE: - ARRAY_SET_ITEMS(contexts, ".paint_common", ".particlemode"); - break; - case CTX_MODE_OBJECT: - ARRAY_SET_ITEMS(contexts, ".objectmode"); - break; - case CTX_MODE_PAINT_GPENCIL: - ARRAY_SET_ITEMS(contexts, ".greasepencil_paint"); - break; - case CTX_MODE_SCULPT_GPENCIL: - ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt"); - break; - case CTX_MODE_WEIGHT_GPENCIL: - ARRAY_SET_ITEMS(contexts, ".greasepencil_weight"); - break; - default: - break; - } - } - - /* for grease pencil we don't use tool system yet, so we need check outside - * workspace->tools_space_type because this value is not available - */ - switch (mode) { - case CTX_MODE_PAINT_GPENCIL: - ARRAY_SET_ITEMS(contexts, ".greasepencil_paint"); - break; - case CTX_MODE_SCULPT_GPENCIL: - ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt"); - break; - case CTX_MODE_WEIGHT_GPENCIL: - ARRAY_SET_ITEMS(contexts, ".greasepencil_weight"); - break; - case CTX_MODE_EDIT_GPENCIL: - ARRAY_SET_ITEMS(contexts, ".greasepencil_edit"); - break; - default: - break; - } - - int i = 0; - while (contexts_base[i]) { - i++; - } - BLI_assert(i < ARRAY_SIZE(contexts_base)); - contexts_base[i] = ".workspace"; - - const bool vertical = true; - ED_region_panels_layout_ex(C, ar, contexts_base, -1, vertical); + ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, contexts, sbuts->mainb, vertical, NULL); } static void buttons_main_region_layout(const bContext *C, ARegion *ar) @@ -305,7 +208,7 @@ static void buttons_main_region_layout(const bContext *C, ARegion *ar) SpaceProperties *sbuts = CTX_wm_space_properties(C); if (sbuts->mainb == BCONTEXT_TOOL) { - buttons_main_region_layout_tool(C, ar); + ED_view3d_buttons_region_layout_ex(C, ar, "Tool"); } else { buttons_main_region_layout_properties(C, sbuts, ar); @@ -400,9 +303,6 @@ static void buttons_header_region_message_subscribe(const bContext *UNUSED(C), static void buttons_navigation_bar_region_init(wmWindowManager *wm, ARegion *ar) { - wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Property Editor", SPACE_PROPERTIES, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); - ar->flag |= RGN_FLAG_PREFSIZE_OR_HIDDEN; ED_region_panels_init(wm, ar); @@ -749,7 +649,7 @@ void ED_spacetype_buttons(void) art->regionid = RGN_TYPE_NAV_BAR; art->prefsizex = AREAMINX - 3; /* XXX Works and looks best, * should we update AREAMINX accordingly? */ - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES | ED_KEYMAP_NAVBAR; art->init = buttons_navigation_bar_region_init; art->draw = buttons_navigation_bar_region_draw; art->message_subscribe = buttons_navigation_bar_region_message_subscribe; diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 70dc1caf36f..081515ca4bc 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -35,7 +35,7 @@ struct bContext; struct wmOperatorType; /* channel heights */ -#define CHANNEL_FIRST (-0.8f * U.widget_unit) +#define CHANNEL_FIRST (-UI_SCRUBBING_MARGIN_Y - CHANNEL_HEIGHT_HALF - CHANNEL_SKIP) #define CHANNEL_HEIGHT (0.8f * U.widget_unit) #define CHANNEL_HEIGHT_HALF (0.4f * U.widget_unit) #define CHANNEL_SKIP (0.1f * U.widget_unit) diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 8b3f221f3a5..a6b1db1aa83 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -955,10 +955,10 @@ static bool change_frame_poll(bContext *C) { /* prevent changes during render */ if (G.is_rendering) { - return 0; + return false; } - - return ED_space_clip_poll(C); + SpaceClip *space_clip = CTX_wm_space_clip(C); + return space_clip != NULL; } static void change_frame_apply(bContext *C, wmOperator *op) @@ -971,7 +971,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) SUBFRA = 0.0f; /* do updates */ - BKE_sound_update_and_seek(CTX_data_main(C), CTX_data_depsgraph(C)); + BKE_sound_seek_scene(CTX_data_main(C), scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 5364c4bc3ca..13d190e6861 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -47,6 +47,7 @@ #include "ED_mask.h" #include "ED_space_api.h" #include "ED_screen.h" +#include "ED_time_scrub_ui.h" #include "ED_select_utils.h" #include "ED_clip.h" #include "ED_transform.h" @@ -94,7 +95,7 @@ static void init_preview_region(const Scene *scene, ar->v2d.minzoom = 0.01f; ar->v2d.maxzoom = 50; - ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); + ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); ar->v2d.scroll |= (V2D_SCROLL_RIGHT); ar->v2d.keepzoom = V2D_LOCKZOOM_Y; ar->v2d.keepofs = V2D_KEEPOFS_Y; @@ -115,8 +116,8 @@ static void init_preview_region(const Scene *scene, ar->v2d.max[0] = MAXFRAMEF; ar->v2d.max[1] = FLT_MAX; - ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); - ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL); + ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); + ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES); ar->v2d.minzoom = 0.0f; ar->v2d.maxzoom = 0.0f; @@ -249,7 +250,7 @@ static SpaceLink *clip_new(const ScrArea *sa, const Scene *scene) sc->zoom = 1.0f; sc->path_length = 20; sc->scopes.track_preview_height = 120; - sc->around = V3D_AROUND_LOCAL_ORIGINS; + sc->around = V3D_AROUND_CENTER_MEDIAN; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for clip"); @@ -1001,9 +1002,13 @@ static void clip_preview_region_init(wmWindowManager *wm, ARegion *ar) UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); /* own keymap */ + keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0); WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Clip Scrubbing", SPACE_CLIP, RGN_TYPE_PREVIEW); + WM_event_add_keymap_handler_poll(&ar->handlers, keymap, ED_event_in_scrubbing_region); + keymap = WM_keymap_ensure(wm->defaultconf, "Clip Graph Editor", SPACE_CLIP, 0); WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap); @@ -1041,22 +1046,24 @@ static void graph_region_draw(const bContext *C, ARegion *ar) /* reset view matrix */ UI_view2d_view_restore(C); + /* time-scrubbing */ + ED_scrubbing_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true); + /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); UI_view2d_scrollers_draw(v2d, scrollers); UI_view2d_scrollers_free(scrollers); /* scale indicators */ - UI_view2d_draw_scale_x__discrete_frames_or_seconds( - ar, v2d, &v2d->hor, scene, sc->flag & SC_SHOW_SECONDS, TH_TEXT); - UI_view2d_draw_scale_y__values(ar, v2d, &v2d->vert, TH_TEXT); - - /* current frame indicator */ - if (sc->flag & SC_SHOW_SECONDS) { - cfra_flag |= DRAWCFRA_UNIT_SECONDS; + { + rcti rect; + BLI_rcti_init(&rect, + 0, + 15 * UI_DPI_FAC, + 15 * UI_DPI_FAC, + UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y); + UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_TEXT); } - UI_view2d_view_orthoSpecial(ar, v2d, 1); - ANIM_draw_cfra_number(C, v2d, cfra_flag); } static void dopesheet_region_draw(const bContext *C, ARegion *ar) @@ -1093,18 +1100,13 @@ static void dopesheet_region_draw(const bContext *C, ARegion *ar) /* reset view matrix */ UI_view2d_view_restore(C); + /* time-scrubbing */ + ED_scrubbing_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true); + /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); UI_view2d_scrollers_draw(v2d, scrollers); UI_view2d_scrollers_free(scrollers); - - /* frame numbers */ - UI_view2d_draw_scale_x__discrete_frames_or_seconds( - ar, v2d, &v2d->hor, scene, sc->flag & SC_SHOW_SECONDS, TH_TEXT); - - /* current frame number indicator */ - UI_view2d_view_orthoSpecial(ar, v2d, 1); - ANIM_draw_cfra_number(C, v2d, cfra_flag); } static void clip_preview_region_draw(const bContext *C, ARegion *ar) diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 441e65cefe4..b51baafbcf5 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1299,6 +1299,12 @@ void CLIP_OT_hide_tracks_clear(wmOperatorType *ot) /********************** frame jump operator *********************/ +static bool frame_jump_poll(bContext *C) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + return space_clip != NULL; +} + static int frame_jump_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); @@ -1350,7 +1356,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op) if (CFRA != sc->user.framenr) { CFRA = sc->user.framenr; - BKE_sound_update_and_seek(CTX_data_main(C), CTX_data_depsgraph(C)); + BKE_sound_seek_scene(CTX_data_main(C), scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } @@ -1377,7 +1383,7 @@ void CLIP_OT_frame_jump(wmOperatorType *ot) /* api callbacks */ ot->exec = frame_jump_exec; - ot->poll = ED_space_clip_poll; + ot->poll = frame_jump_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index bb8680682d2..6b3baa1e766 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -478,7 +478,7 @@ static void file_draw_preview(uiBlock *block, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); if (icon) { - UI_icon_draw_aspect((float)xco, (float)yco, icon, icon_aspect, 1.0f, NULL); + UI_icon_draw_ex((float)xco, (float)yco, icon, icon_aspect, 1.0f, 0.0f, NULL, false); } /* border */ diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 674735f3e1d..5ac7ff72aed 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -1011,7 +1011,7 @@ static int bookmark_cleanup_exec(bContext *C, wmOperator *UNUSED(op)) BLI_make_file_string( "/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE); fsmenu_write_file(fsmenu, name); - fsmenu_refresh_bookmarks_status(fsmenu); + fsmenu_refresh_bookmarks_status(CTX_wm_manager(C), fsmenu); ED_area_tag_refresh(sa); ED_area_tag_redraw(sa); } @@ -1567,6 +1567,9 @@ static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused)) /* refresh system directory menu */ fsmenu_refresh_system_category(fsmenu); + /* Update bookmarks 'valid' state. */ + fsmenu_refresh_bookmarks_status(wm, fsmenu); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 38423a87447..b50c37baae6 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -44,6 +44,9 @@ # include "BLI_winstuff.h" #endif +#include "WM_api.h" +#include "WM_types.h" + #ifdef __APPLE__ # include <Carbon/Carbon.h> #endif /* __APPLE__ */ @@ -721,31 +724,59 @@ void fsmenu_refresh_system_category(struct FSMenu *fsmenu) fsmenu_read_system(fsmenu, true); } -void fsmenu_refresh_bookmarks_status(struct FSMenu *fsmenu) +static void fsmenu_free_ex(FSMenu **fsmenu) { - int categories[] = { - FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT}; - int i; - - for (i = sizeof(categories) / sizeof(*categories); i--;) { - FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, categories[i]); - for (; fsm_iter; fsm_iter = fsm_iter->next) { - fsmenu_entry_refresh_valid(fsm_iter); - } + if (*fsmenu != NULL) { + fsmenu_free_category(*fsmenu, FS_CATEGORY_SYSTEM); + fsmenu_free_category(*fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS); + fsmenu_free_category(*fsmenu, FS_CATEGORY_BOOKMARKS); + fsmenu_free_category(*fsmenu, FS_CATEGORY_RECENT); + MEM_freeN(*fsmenu); } + + *fsmenu = NULL; } void fsmenu_free(void) { - if (g_fsmenu) { - fsmenu_free_category(g_fsmenu, FS_CATEGORY_SYSTEM); - fsmenu_free_category(g_fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS); - fsmenu_free_category(g_fsmenu, FS_CATEGORY_BOOKMARKS); - fsmenu_free_category(g_fsmenu, FS_CATEGORY_RECENT); - MEM_freeN(g_fsmenu); + fsmenu_free_ex(&g_fsmenu); +} + +static void fsmenu_copy_category(struct FSMenu *fsmenu_dst, + struct FSMenu *fsmenu_src, + const FSMenuCategory category) +{ + FSMenuEntry *fsm_dst_prev = NULL, *fsm_dst_head = NULL; + FSMenuEntry *fsm_src_iter = ED_fsmenu_get_category(fsmenu_src, category); + + for (; fsm_src_iter != NULL; fsm_src_iter = fsm_src_iter->next) { + FSMenuEntry *fsm_dst = MEM_dupallocN(fsm_src_iter); + if (fsm_dst->path != NULL) { + fsm_dst->path = MEM_dupallocN(fsm_dst->path); + } + + if (fsm_dst_prev != NULL) { + fsm_dst_prev->next = fsm_dst; + } + else { + fsm_dst_head = fsm_dst; + } + fsm_dst_prev = fsm_dst; } - g_fsmenu = NULL; + ED_fsmenu_set_category(fsmenu_dst, category, fsm_dst_head); +} + +static FSMenu *fsmenu_copy(FSMenu *fsmenu) +{ + FSMenu *fsmenu_copy = MEM_dupallocN(fsmenu); + + fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_SYSTEM); + fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_SYSTEM_BOOKMARKS); + fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_BOOKMARKS); + fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_RECENT); + + return fsmenu_copy; } int fsmenu_get_active_indices(struct FSMenu *fsmenu, enum FSMenuCategory category, const char *dir) @@ -761,3 +792,99 @@ int fsmenu_get_active_indices(struct FSMenu *fsmenu, enum FSMenuCategory categor return -1; } + +/* Thanks to some bookmarks sometimes being network drives that can have tens of seconds of delay + * before being defined as unreachable by the OS, we need to validate the bookmarks in an async + * job... + */ +static void fsmenu_bookmark_validate_job_startjob(void *fsmenuv, + short *stop, + short *do_update, + float *UNUSED(progress)) +{ + FSMenu *fsmenu = fsmenuv; + + int categories[] = { + FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT}; + + for (size_t i = ARRAY_SIZE(categories); i--;) { + FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, categories[i]); + for (; fsm_iter; fsm_iter = fsm_iter->next) { + if (*stop) { + return; + } + /* Note that we do not really need atomics primitives or thread locks here, since this only + * sets one short, which is assumed to be 'atomic'-enough for us here. */ + fsmenu_entry_refresh_valid(fsm_iter); + *do_update = true; + } + } +} + +static void fsmenu_bookmark_validate_job_update(void *fsmenuv) +{ + FSMenu *fsmenu_job = fsmenuv; + + int categories[] = { + FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT}; + + for (size_t i = ARRAY_SIZE(categories); i--;) { + FSMenuEntry *fsm_iter_src = ED_fsmenu_get_category(fsmenu_job, categories[i]); + FSMenuEntry *fsm_iter_dst = ED_fsmenu_get_category(ED_fsmenu_get(), categories[i]); + for (; fsm_iter_dst != NULL; fsm_iter_dst = fsm_iter_dst->next) { + while (fsm_iter_src != NULL && !STREQ(fsm_iter_dst->path, fsm_iter_src->path)) { + fsm_iter_src = fsm_iter_src->next; + } + if (fsm_iter_src == NULL) { + return; + } + fsm_iter_dst->valid = fsm_iter_src->valid; + } + } +} + +static void fsmenu_bookmark_validate_job_end(void *fsmenuv) +{ + /* In case there would be some dangling update... */ + fsmenu_bookmark_validate_job_update(fsmenuv); +} + +static void fsmenu_bookmark_validate_job_free(void *fsmenuv) +{ + FSMenu *fsmenu = fsmenuv; + fsmenu_free_ex(&fsmenu); +} + +static void fsmenu_bookmark_validate_job_start(wmWindowManager *wm) +{ + wmJob *wm_job; + FSMenu *fsmenu_job = fsmenu_copy(g_fsmenu); + + /* setup job */ + wm_job = WM_jobs_get( + wm, wm->winactive, wm, "Validating Bookmarks...", 0, WM_JOB_TYPE_FSMENU_BOOKMARK_VALIDATE); + WM_jobs_customdata_set(wm_job, fsmenu_job, fsmenu_bookmark_validate_job_free); + WM_jobs_timer(wm_job, 0.01, NC_SPACE | ND_SPACE_FILE_LIST, NC_SPACE | ND_SPACE_FILE_LIST); + WM_jobs_callbacks(wm_job, + fsmenu_bookmark_validate_job_startjob, + NULL, + fsmenu_bookmark_validate_job_update, + fsmenu_bookmark_validate_job_end); + + /* start the job */ + WM_jobs_start(wm, wm_job); +} + +static void fsmenu_bookmark_validate_job_stop(wmWindowManager *wm) +{ + WM_jobs_kill_type(wm, wm, WM_JOB_TYPE_FSMENU_BOOKMARK_VALIDATE); +} + +void fsmenu_refresh_bookmarks_status(wmWindowManager *wm, FSMenu *fsmenu) +{ + BLI_assert(fsmenu == ED_fsmenu_get()); + UNUSED_VARS_NDEBUG(fsmenu); + + fsmenu_bookmark_validate_job_stop(wm); + fsmenu_bookmark_validate_job_start(wm); +} diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h index cb0dccf0499..d9850cb855d 100644 --- a/source/blender/editors/space_file/fsmenu.h +++ b/source/blender/editors/space_file/fsmenu.h @@ -68,7 +68,7 @@ void fsmenu_free(void); void fsmenu_refresh_system_category(struct FSMenu *fsmenu); /** Refresh 'valid' status of all menu entries */ -void fsmenu_refresh_bookmarks_status(struct FSMenu *fsmenu); +void fsmenu_refresh_bookmarks_status(struct wmWindowManager *wm, struct FSMenu *fsmenu); /** Get active index based on given directory. */ int fsmenu_get_active_indices(struct FSMenu *fsmenu, diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 4629f33d210..1fd878e4662 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -83,7 +83,6 @@ static SpaceLink *file_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen BLI_addtail(&sfile->regionbase, ar); ar->regiontype = RGN_TYPE_TOOL_PROPS; ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV; - ar->flag |= RGN_FLAG_DYNAMIC_SIZE; /* ui list region */ ar = MEM_callocN(sizeof(ARegion), "ui region for file"); @@ -143,18 +142,16 @@ static void file_free(SpaceLink *sl) } /* spacetype; init callback, area size changes, screen set, etc */ -static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa) +static void file_init(wmWindowManager *wm, ScrArea *sa) { SpaceFile *sfile = (SpaceFile *)sa->spacedata.first; + struct FSMenu *fsmenu = ED_fsmenu_get(); /* refresh system directory list */ - fsmenu_refresh_system_category(ED_fsmenu_get()); + fsmenu_refresh_system_category(fsmenu); - /* Update bookmarks 'valid' state. - * Done here, because it seems BLI_is_dir() can have huge impact on performances - * in some cases, on win systems... See T43684. - */ - fsmenu_refresh_bookmarks_status(ED_fsmenu_get()); + /* Update bookmarks 'valid' state. */ + fsmenu_refresh_bookmarks_status(wm, fsmenu); if (sfile->layout) { sfile->layout->dirty = true; diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 0954538e430..c5f8c32ec7a 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -2820,6 +2820,7 @@ void GRAPH_OT_fmodifier_add(wmOperatorType *ot) /* id-props */ prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", ""); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ACTION); RNA_def_enum_funcs(prop, graph_fmodifier_itemf); ot->prop = prop; diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 054a1e3d8ee..5c7035a4c04 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -105,7 +105,7 @@ static void graphview_cursor_apply(bContext *C, wmOperator *op) } SUBFRA = 0.0f; - BKE_sound_update_and_seek(bmain, CTX_data_depsgraph(C)); + BKE_sound_seek_scene(bmain, scene); } /* set the cursor value */ diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 13a42f091f6..5ea07c56286 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -1141,7 +1141,7 @@ typedef enum eGraphVertIndex { /* Tolerance for absolute radius (in pixels) of the vert from the cursor to use */ // TODO: perhaps this should depend a bit on the size that the user set the vertices to be? -#define GVERTSEL_TOL 10 +#define GVERTSEL_TOL (10 * U.pixelsize) /* ....... */ diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 390ea0cf00b..4e131c653f8 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -42,6 +42,7 @@ #include "ED_screen.h" #include "ED_anim_api.h" #include "ED_markers.h" +#include "ED_time_scrub_ui.h" #include "GPU_immediate.h" #include "GPU_state.h" @@ -57,6 +58,7 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "UI_interface.h" #include "graph_intern.h" // own include @@ -79,7 +81,7 @@ static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene) /* settings for making it easier by default to just see what you're interested in tweaking */ sipo->ads->filterflag |= ADS_FILTER_ONLYSEL; - sipo->flag |= SIPO_SELVHANDLESONLY; + sipo->flag |= SIPO_SELVHANDLESONLY | SIPO_MARKER_LINES; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for graphedit"); @@ -124,8 +126,8 @@ static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene) ar->v2d.max[0] = MAXFRAMEF; ar->v2d.max[1] = FLT_MAX; - ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); - ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL); + ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); + ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES); ar->v2d.keeptot = 0; @@ -291,12 +293,14 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) } /* markers */ - UI_view2d_view_orthoSpecial(ar, v2d, 1); - int marker_draw_flag = DRAW_MARKERS_MARGIN; - if (sipo->flag & SIPO_MARKER_LINES) { - marker_draw_flag |= DRAW_MARKERS_LINES; + if (sipo->mode != SIPO_MODE_DRIVERS) { + UI_view2d_view_orthoSpecial(ar, v2d, 1); + int marker_draw_flag = DRAW_MARKERS_MARGIN; + if (sipo->flag & SIPO_MARKER_LINES) { + marker_draw_flag |= DRAW_MARKERS_LINES; + } + ED_markers_draw(C, marker_draw_flag); } - ED_markers_draw(C, marker_draw_flag); /* preview range */ UI_view2d_view_ortho(v2d); @@ -309,6 +313,9 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) /* reset view matrix */ UI_view2d_view_restore(C); + /* time-scrubbing */ + ED_scrubbing_draw(ar, scene, display_seconds, false); + /* scrollers */ // FIXME: args for scrollers depend on the type of data being shown... scrollers = UI_view2d_scrollers_calc(v2d, NULL); @@ -316,13 +323,14 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) UI_view2d_scrollers_free(scrollers); /* scale numbers */ - UI_view2d_draw_scale_x__frames_or_seconds(ar, v2d, &v2d->hor, scene, display_seconds, TH_TEXT); - UI_view2d_draw_scale_y__values(ar, v2d, &v2d->vert, TH_TEXT); - - /* draw current frame number-indicator on top of scrollers */ - if ((sipo->mode != SIPO_MODE_DRIVERS) && ((sipo->flag & SIPO_NODRAWCFRANUM) == 0)) { - UI_view2d_view_orthoSpecial(ar, v2d, 1); - ANIM_draw_cfra_number(C, v2d, cfra_flag); + { + rcti rect; + BLI_rcti_init(&rect, + 0, + 15 * UI_DPI_FAC, + 15 * UI_DPI_FAC, + UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y); + UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_SCROLL_TEXT); } } @@ -367,6 +375,9 @@ static void graph_channel_region_draw(const bContext *C, ARegion *ar) graph_draw_channel_names((bContext *)C, &ac, ar); } + /* channel filter next to scrubbing area */ + ED_channel_search_draw(C, ar, ac.ads); + /* reset view matrix */ UI_view2d_view_restore(C); @@ -849,7 +860,7 @@ void ED_spacetype_ipo(void) art->draw = graph_main_region_draw; art->listener = graph_region_listener; art->message_subscribe = graph_region_message_subscribe; - art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES; + art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES; BLI_addhead(&st->regiontypes, art); @@ -880,7 +891,7 @@ void ED_spacetype_ipo(void) /* regions: UI buttons */ art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region"); art->regionid = RGN_TYPE_UI; - art->prefsizex = 200; + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; art->listener = graph_region_listener; art->init = graph_buttons_region_init; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 0710ecf3bd6..c317cb26cb7 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2494,7 +2494,8 @@ static int image_invert_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID; + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + BKE_image_mark_dirty(ima, ibuf); if (ibuf->mipmap[0]) { ibuf->userflags |= IB_MIPMAP_INVALID; @@ -3542,7 +3543,7 @@ static void change_frame_apply(bContext *C, wmOperator *op) SUBFRA = 0.0f; /* do updates */ - BKE_sound_update_and_seek(CTX_data_main(C), CTX_data_depsgraph(C)); + BKE_sound_seek_scene(CTX_data_main(C), scene); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 3b2386d94e6..cbe655fc9ae 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -567,7 +567,8 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) Object *obedit = CTX_data_edit_object(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); Mask *mask = NULL; - bool curve = false; + bool show_uvedit = false; + bool show_curve = false; Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View2D *v2d = &ar->v2d; @@ -609,13 +610,13 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) /* check for mask (delay draw) */ if (ED_space_image_show_uvedit(sima, obedit)) { - /* pass */ + show_uvedit = true; } else if (sima->mode == SI_MODE_MASK) { mask = ED_space_image_get_mask(sima); } else if (ED_space_image_paint_curve(C)) { - curve = true; + show_curve = true; } ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); @@ -669,12 +670,9 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) false, NULL, C); - - UI_view2d_view_ortho(v2d); - ED_image_draw_cursor(ar, sima->cursor); - UI_view2d_view_restore(C); } - else if (curve) { + + if (show_uvedit || mask || show_curve) { UI_view2d_view_ortho(v2d); ED_image_draw_cursor(ar, sima->cursor); UI_view2d_view_restore(C); @@ -764,7 +762,7 @@ static void image_buttons_region_layout(const bContext *C, ARegion *ar) } const bool vertical = true; - ED_region_panels_layout_ex(C, ar, contexts_base, -1, vertical); + ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, contexts_base, -1, vertical, NULL); } static void image_buttons_region_draw(const bContext *C, ARegion *ar) @@ -1035,7 +1033,7 @@ void ED_spacetype_image(void) /* regions: listview/buttons/scopes */ art = MEM_callocN(sizeof(ARegionType), "spacetype image region"); art->regionid = RGN_TYPE_UI; - art->prefsizex = 220; // XXX + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; art->listener = image_buttons_region_listener; art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui; diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 171d8505222..bf43e493cc5 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -160,19 +160,11 @@ static int pack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(ev { Main *bmain = CTX_data_main(C); Image *ima; - ImBuf *ibuf; // first check for dirty images for (ima = bmain->images.first; ima; ima = ima->id.next) { - if (BKE_image_has_loaded_ibuf(ima)) { /* XXX FIX */ - ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - - if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { - BKE_image_release_ibuf(ima, ibuf, NULL); - break; - } - - BKE_image_release_ibuf(ima, ibuf, NULL); + if (BKE_image_is_dirty(ima)) { + break; } } diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 3e4eb6af098..e5c116e85de 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -52,6 +52,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "UI_interface.h" + #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -389,7 +391,7 @@ static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEv UI_view2d_listview_view_to_cell(NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, - NLACHANNEL_FIRST_TOP(snla), + NLACHANNEL_FIRST_TOP(&ac), x, y, NULL, diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index b821a246dc5..68cbfd76331 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -689,11 +689,11 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for * start of list offset, and the second is as a correction for the scrollers. */ - int height = NLACHANNEL_TOT_HEIGHT(snla, items); + int height = NLACHANNEL_TOT_HEIGHT(ac, items); v2d->tot.ymin = -height; /* loop through channels, and set up drawing depending on their type */ - float ymax = NLACHANNEL_FIRST_TOP(snla); + float ymax = NLACHANNEL_FIRST_TOP(ac); for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla)) { float ymin = ymax - NLACHANNEL_HEIGHT(snla); @@ -822,7 +822,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar) * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for * start of list offset, and the second is as a correction for the scrollers. */ - int height = NLACHANNEL_TOT_HEIGHT(snla, items); + int height = NLACHANNEL_TOT_HEIGHT(ac, items); v2d->tot.ymin = -height; /* need to do a view-sync here, so that the keys area doesn't jump around @@ -832,7 +832,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar) /* draw channels */ { /* first pass: just the standard GL-drawing for backdrop + text */ size_t channel_index = 0; - float ymax = NLACHANNEL_FIRST_TOP(snla); + float ymax = NLACHANNEL_FIRST_TOP(ac); for (ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla), channel_index++) { @@ -849,7 +849,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar) { /* second pass: UI widgets */ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); size_t channel_index = 0; - float ymax = NLACHANNEL_FIRST_TOP(snla); + float ymax = NLACHANNEL_FIRST_TOP(ac); /* set blending again, as may not be set in previous step */ GPU_blend_set_func_separate( diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 07853e5850a..acb3d913114 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -429,7 +429,7 @@ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, floa ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* loop through all channels, finding the first one that's selected */ - float ymax = NLACHANNEL_FIRST_TOP(snla); + float ymax = NLACHANNEL_FIRST_TOP(ac); for (ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla)) { const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); @@ -2446,6 +2446,7 @@ void NLA_OT_fmodifier_add(wmOperatorType *ot) /* id-props */ ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", ""); + RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ACTION); RNA_def_enum_funcs(ot->prop, nla_fmodifier_itemf); RNA_def_boolean(ot->srna, diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index accd82525f5..0de9acfec25 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -47,6 +47,7 @@ #include "WM_types.h" #include "UI_view2d.h" +#include "UI_interface.h" #include "nla_intern.h" // own include @@ -542,7 +543,7 @@ static void mouse_nla_strips( * (i.e a row in the list) where keyframe was */ UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); UI_view2d_listview_view_to_cell( - 0, NLACHANNEL_STEP(snla), 0, NLACHANNEL_FIRST_TOP(snla), x, y, NULL, &channel_index); + 0, NLACHANNEL_STEP(snla), 0, NLACHANNEL_FIRST_TOP(ac), x, y, NULL, &channel_index); /* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click * (that is the size of keyframe icons, so user should be expecting similar tolerances) diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index ba660945d32..4b7dfe5d653 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -40,6 +40,7 @@ #include "ED_anim_api.h" #include "ED_markers.h" #include "ED_screen.h" +#include "ED_time_scrub_ui.h" #include "WM_api.h" #include "WM_types.h" @@ -47,6 +48,7 @@ #include "RNA_access.h" +#include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -69,6 +71,7 @@ static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene) /* set auto-snapping settings */ snla->autosnap = SACTSNAP_FRAME; + snla->flag = SNLA_SHOW_MARKER_LINES; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for nla"); @@ -116,7 +119,7 @@ static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene) ar->v2d.minzoom = 0.01f; ar->v2d.maxzoom = 50; - ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); + ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); ar->v2d.scroll |= (V2D_SCROLL_RIGHT); ar->v2d.keepzoom = V2D_LOCKZOOM_Y; ar->v2d.keepofs = V2D_KEEPOFS_Y; @@ -201,6 +204,9 @@ static void nla_channel_region_draw(const bContext *C, ARegion *ar) draw_nla_channel_list(C, &ac, ar); } + /* channel filter next to scrubbing area */ + ED_channel_search_draw(C, ar, ac.ads); + /* reset view matrix */ UI_view2d_view_restore(C); @@ -284,20 +290,12 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar) /* reset view matrix */ UI_view2d_view_restore(C); + ED_scrubbing_draw(ar, scene, snla->flag & SNLA_DRAWTIME, true); + /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); UI_view2d_scrollers_draw(v2d, scrollers); UI_view2d_scrollers_free(scrollers); - - /* frame numbers */ - UI_view2d_draw_scale_x__discrete_frames_or_seconds( - ar, v2d, &v2d->hor, scene, snla->flag & SNLA_DRAWTIME, TH_TEXT); - - /* draw current frame number-indicator on top of scrollers */ - if ((snla->flag & SNLA_NODRAWCFRANUM) == 0) { - UI_view2d_view_orthoSpecial(ar, v2d, 1); - ANIM_draw_cfra_number(C, v2d, cfra_flag); - } } /* add handlers, stuff you only do once or on area/region changes */ @@ -614,7 +612,7 @@ void ED_spacetype_nla(void) art->draw = nla_main_region_draw; art->listener = nla_main_region_listener; art->message_subscribe = nla_main_region_message_subscribe; - art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES; + art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES; BLI_addhead(&st->regiontypes, art); @@ -645,7 +643,7 @@ void ED_spacetype_nla(void) /* regions: UI buttons */ art = MEM_callocN(sizeof(ARegionType), "spacetype nla region"); art->regionid = RGN_TYPE_UI; - art->prefsizex = 200; + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->keymapflag = ED_KEYMAP_UI; art->listener = nla_region_listener; art->init = nla_buttons_region_init; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 447fea8098c..bf6ec961a5d 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -708,6 +708,11 @@ static void node_buts_image_user(uiLayout *layout, col = uiLayoutColumn(layout, false); uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE); } + + uiLayout *split = uiLayoutSplit(layout, 0.5f, true); + PointerRNA colorspace_settings_ptr = RNA_pointer_get(imaptr, "colorspace_settings"); + uiItemL(split, IFACE_("Color Space"), ICON_NONE); + uiItemR(split, &colorspace_settings_ptr, "name", 0, "", ICON_NONE); } static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -782,7 +787,6 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA NULL, UI_TEMPLATE_ID_FILTER_ALL, false); - uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE); uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE); uiItemR(layout, ptr, "projection", 0, "", ICON_NONE); @@ -820,11 +824,10 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin UI_TEMPLATE_ID_FILTER_ALL, false); - node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false); - - uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE); uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE); uiItemR(layout, ptr, "projection", 0, "", ICON_NONE); + + node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false); } static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -875,7 +878,6 @@ static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, P uiTemplateImageInfo(layout, C, ima, iuserptr.data); } - uiItemR(layout, ptr, "color_space", 0, IFACE_("Color Space"), ICON_NONE); uiItemR(layout, ptr, "interpolation", 0, IFACE_("Interpolation"), ICON_NONE); uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE); } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 3e73cc52c52..fb34d9dc459 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -453,13 +453,8 @@ void ED_node_shader_default(const bContext *C, ID *id) output_type = SH_NODE_OUTPUT_LIGHT; shader_type = SH_NODE_EMISSION; - copy_v3_v3(color, &la->r); - if (la->type == LA_LOCAL || la->type == LA_SPOT || la->type == LA_AREA) { - strength = 100.0f; - } - else { - strength = 1.0f; - } + copy_v3_fl3(color, 1.0f, 1.0f, 1.0f); + strength = 1.0f; break; } default: diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index b52d1d3b78f..aab328249fe 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -429,19 +429,24 @@ void node_select_single(bContext *C, bNode *node) WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); } -static int node_mouse_select(Main *bmain, - SpaceNode *snode, - ARegion *ar, +static int node_mouse_select(bContext *C, const int mval[2], const bool extend, const bool socket_select, - const bool deselect_all) + const bool deselect_all, + const bool wait_to_deselect_others) { + Main *bmain = CTX_data_main(C); + SpaceNode *snode = CTX_wm_space_node(C); + ARegion *ar = CTX_wm_region(C); bNode *node, *tnode; bNodeSocket *sock = NULL; bNodeSocket *tsock; float cursor[2]; - bool selected = false; + int ret_value = OPERATOR_CANCELLED; + + /* Waiting to deselect others is only allowed for basic selection. */ + BLI_assert(!(extend || socket_select) || !wait_to_deselect_others); /* get mouse coordinates in view2d space */ UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &cursor[0], &cursor[1]); @@ -449,89 +454,104 @@ static int node_mouse_select(Main *bmain, /* first do socket selection, these generally overlap with nodes. */ if (socket_select) { if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) { - node_socket_toggle(node, sock, 1); - selected = true; + /* NOTE: SOCK_IN does not take into account the extend case... + * This feature is not really used anyway currently? */ + node_socket_toggle(node, sock, true); + ret_value = OPERATOR_FINISHED; } else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) { if (sock->flag & SELECT) { if (extend) { - node_socket_deselect(node, sock, 1); + node_socket_deselect(node, sock, true); } else { - selected = true; + ret_value = OPERATOR_FINISHED; } } else { - /* only allow one selected output per node, for sensible linking. - * allows selecting outputs from different nodes though. */ + /* Only allow one selected output per node, for sensible linking. + * Allow selecting outputs from different nodes though, if extend is true. */ if (node) { for (tsock = node->outputs.first; tsock; tsock = tsock->next) { - node_socket_deselect(node, tsock, 1); + if (tsock == sock) { + continue; + } + node_socket_deselect(node, tsock, true); } } - if (extend) { - /* only allow one selected output per node, for sensible linking. - * allows selecting outputs from different nodes though. */ - for (tsock = node->outputs.first; tsock; tsock = tsock->next) { - if (tsock != sock) { - node_socket_deselect(node, tsock, 1); + if (!extend) { + for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) { + if (tnode == node) { + continue; + } + for (tsock = tnode->outputs.first; tsock; tsock = tsock->next) { + node_socket_deselect(tnode, tsock, true); } } } node_socket_select(node, sock); - selected = true; + ret_value = OPERATOR_FINISHED; } } } if (!sock) { - if (extend) { - /* find the closest visible node */ - node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]); + /* find the closest visible node */ + node = node_under_mouse_select(snode->edittree, (int)cursor[0], (int)cursor[1]); - if (node) { - if ((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0) { - /* if node is selected but not active make it active */ - ED_node_set_active(bmain, snode->edittree, node); - } - else { + if (extend) { + if (node != NULL) { + /* If node is selected but not active, we want to make it active, + * but not toggle (deselect) it. */ + if (!((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0)) { node_toggle(node); - ED_node_set_active(bmain, snode->edittree, node); } - selected = true; + ret_value = OPERATOR_FINISHED; } } - else { - /* find the closest visible node */ - node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]); + else if (deselect_all && node == NULL) { + /* Deselect in empty space. */ + for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) { + nodeSetSelected(tnode, false); + } + ret_value = OPERATOR_FINISHED; + } + else if (node != NULL) { + /* When clicking on an already selected node, we want to wait to deselect + * others and allow the user to start moving the node without that. */ + if (wait_to_deselect_others && (node->flag & SELECT)) { + ret_value = OPERATOR_RUNNING_MODAL; + } + else { + nodeSetSelected(node, true); - if (node != NULL || deselect_all) { for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) { - nodeSetSelected(tnode, false); - } - selected = true; - if (node != NULL) { - nodeSetSelected(node, true); - ED_node_set_active(bmain, snode->edittree, node); + if (tnode != node) { + nodeSetSelected(tnode, false); + } } + + ret_value = OPERATOR_FINISHED; } } } /* update node order */ - if (selected) { + if (ret_value != OPERATOR_CANCELLED) { + if (node != NULL && ret_value != OPERATOR_RUNNING_MODAL) { + ED_node_set_active(bmain, snode->edittree, node); + } ED_node_set_active_viewer_key(snode); ED_node_sort(snode->edittree); + + WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); } - return selected; + return ret_value; } static int node_select_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - SpaceNode *snode = CTX_wm_space_node(C); - ARegion *ar = CTX_wm_region(C); int mval[2]; /* get settings from RNA properties for operator */ @@ -544,17 +564,70 @@ static int node_select_exec(bContext *C, wmOperator *op) const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); /* perform the select */ - if (node_mouse_select(bmain, snode, ar, mval, extend, socket_select, deselect_all)) { - /* send notifiers */ - WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); + const int ret_value = node_mouse_select(C, mval, extend, socket_select, deselect_all, false); - /* allow tweak event to work too */ - return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; + /* allow tweak event to work too */ + return ret_value | OPERATOR_PASS_THROUGH; +} + +static int node_select_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + const short init_event_type = (short)POINTER_AS_INT(op->customdata); + + /* get settings from RNA properties for operator */ + int mval[2]; + mval[0] = RNA_int_get(op->ptr, "mouse_x"); + mval[1] = RNA_int_get(op->ptr, "mouse_y"); + + const bool extend = RNA_boolean_get(op->ptr, "extend"); + /* always do socket_select when extending selection. */ + const bool socket_select = extend || RNA_boolean_get(op->ptr, "socket_select"); + const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); + + /* These cases are never modal. */ + if (extend || socket_select) { + return node_select_exec(C, op); } - else { - /* allow tweak event to work too */ - return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; + + if (init_event_type == 0) { + if (event->val == KM_PRESS) { + const int ret_value = node_mouse_select(C, mval, extend, socket_select, deselect_all, true); + + op->customdata = POINTER_FROM_INT((int)event->type); + if (ret_value & OPERATOR_RUNNING_MODAL) { + WM_event_add_modal_handler(C, op); + } + return ret_value | OPERATOR_PASS_THROUGH; + } + else { + /* If we are in init phase, and cannot validate init of modal operations, + * just fall back to basic exec. + */ + return node_select_exec(C, op); + } } + else if (event->type == init_event_type && event->val == KM_RELEASE) { + const int ret_value = node_mouse_select(C, mval, extend, socket_select, deselect_all, false); + return ret_value | OPERATOR_PASS_THROUGH; + } + else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + const int dx = mval[0] - event->mval[0]; + const int dy = mval[1] - event->mval[1]; + const float tweak_threshold = U.tweak_threshold * U.dpi_fac; + /* If user moves mouse more than defined threshold, we consider select operator as + * finished. Otherwise, it is still running until we get an 'release' event. In any + * case, we pass through event, but select op is not finished yet. */ + if (abs(dx) + abs(dy) > tweak_threshold) { + return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; + } + else { + /* Important not to return anything other than PASS_THROUGH here, + * otherwise it prevents underlying tweak detection code to work properly. */ + return OPERATOR_PASS_THROUGH; + } + } + + return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; } static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) @@ -562,7 +635,9 @@ static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) RNA_int_set(op->ptr, "mouse_x", event->mval[0]); RNA_int_set(op->ptr, "mouse_y", event->mval[1]); - return node_select_exec(C, op); + op->customdata = POINTER_FROM_INT(0); + + return node_select_modal(C, op, event); } void NODE_OT_select(wmOperatorType *ot) @@ -575,6 +650,7 @@ void NODE_OT_select(wmOperatorType *ot) /* api callbacks */ ot->invoke = node_select_invoke; ot->exec = node_select_exec; + ot->modal = node_select_modal; ot->poll = ED_operator_node_active; /* flags */ @@ -1186,7 +1262,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op) static int node_find_node_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - UI_popup_block_invoke(C, node_find_menu, op); + UI_popup_block_invoke(C, node_find_menu, op, NULL); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 2152bb9847a..2351d437294 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -998,7 +998,7 @@ void ED_spacetype_node(void) /* regions: listview/buttons */ art = MEM_callocN(sizeof(ARegionType), "spacetype node region"); art->regionid = RGN_TYPE_UI; - art->prefsizex = 180; // XXX + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; art->listener = node_region_listener; art->init = node_buttons_region_init; diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index 6da42ecb3c0..21e54a29fb9 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -855,7 +855,7 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op) void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot) { /* identifiers */ - ot->name = "Set Exclude"; + ot->name = "Disable from View Layer"; ot->idname = "OUTLINER_OT_collection_exclude_set"; ot->description = "Exclude collection from the active view layer"; @@ -870,7 +870,7 @@ void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot) void OUTLINER_OT_collection_exclude_clear(wmOperatorType *ot) { /* identifiers */ - ot->name = "Clear Exclude"; + ot->name = "Enable in View Layer"; ot->idname = "OUTLINER_OT_collection_exclude_clear"; ot->description = "Include collection in the active view layer"; @@ -965,8 +965,8 @@ static int collection_isolate_exec(bContext *C, wmOperator *op) LayerCollection *lc_master = view_layer->layer_collections.first; for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter; lc_iter = lc_iter->next) { - lc_iter->flag |= LAYER_COLLECTION_RESTRICT_VIEW; - layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW); + lc_iter->flag |= LAYER_COLLECTION_HIDE; + layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_HIDE); } } @@ -1023,12 +1023,12 @@ void OUTLINER_OT_collection_isolate(wmOperatorType *ot) static bool collection_show_poll(bContext *C) { - return collections_view_layer_poll(C, true, LAYER_COLLECTION_RESTRICT_VIEW); + return collections_view_layer_poll(C, true, LAYER_COLLECTION_HIDE); } static bool collection_hide_poll(bContext *C) { - return collections_view_layer_poll(C, false, LAYER_COLLECTION_RESTRICT_VIEW); + return collections_view_layer_poll(C, false, LAYER_COLLECTION_HIDE); } static bool collection_inside_poll(bContext *C) @@ -1163,12 +1163,12 @@ static bool collection_flag_poll(bContext *C, bool clear, int flag) static bool collection_enable_poll(bContext *C) { - return collection_flag_poll(C, true, COLLECTION_RESTRICT_VIEW); + return collection_flag_poll(C, true, COLLECTION_RESTRICT_VIEWPORT); } static bool collection_disable_poll(bContext *C) { - return collection_flag_poll(C, false, COLLECTION_RESTRICT_VIEW); + return collection_flag_poll(C, false, COLLECTION_RESTRICT_VIEWPORT); } static bool collection_enable_render_poll(bContext *C) @@ -1188,7 +1188,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op) SpaceOutliner *soops = CTX_wm_space_outliner(C); const bool is_render = strstr(op->idname, "render"); const bool clear = strstr(op->idname, "show") || strstr(op->idname, "enable"); - int flag = is_render ? COLLECTION_RESTRICT_RENDER : COLLECTION_RESTRICT_VIEW; + int flag = is_render ? COLLECTION_RESTRICT_RENDER : COLLECTION_RESTRICT_VIEWPORT; struct CollectionEditData data = { .scene = scene, .soops = soops, @@ -1215,7 +1215,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op) /* Make sure (at least for this view layer) the collection is visible. */ if (clear && !is_render) { - layer_collection->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW; + layer_collection->flag &= ~LAYER_COLLECTION_HIDE; } } BLI_gset_free(data.collections_to_edit, NULL); @@ -1408,8 +1408,8 @@ static int outliner_unhide_all_exec(bContext *C, wmOperator *UNUSED(op)) LayerCollection *lc_master = view_layer->layer_collections.first; for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter; lc_iter = lc_iter->next) { - lc_iter->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW; - layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW); + lc_iter->flag &= ~LAYER_COLLECTION_HIDE; + layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_HIDE); } /* Unhide all objects. */ diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 9d6008ce3a8..6547b46a6e6 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -270,127 +270,413 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void } } -static int base_pushed_state_cb(bContext *UNUSED(C), void *poin) +static void outliner_object_set_flag_recursive_cb(bContext *C, + Base *base, + Object *ob, + const char *propname) +{ + Main *bmain = CTX_data_main(C); + wmWindow *win = CTX_wm_window(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + PointerRNA ptr; + + bool extend = (win->eventstate->shift != 0); + + if (!extend) { + return; + } + + /* Create PointerRNA and PropertyRNA for either Object or Base. */ + ID *id = ob ? &ob->id : &scene->id; + StructRNA *struct_rna = ob ? &RNA_Object : &RNA_ObjectBase; + void *data = ob ? (void *)ob : (void *)base; + + RNA_pointer_create(id, struct_rna, data, &ptr); + PropertyRNA *base_or_object_prop = RNA_struct_type_find_property(struct_rna, propname); + const bool value = RNA_property_boolean_get(&ptr, base_or_object_prop); + + Object *ob_parent = ob ? ob : base->object; + + for (Object *ob_iter = bmain->objects.first; ob_iter; ob_iter = ob_iter->id.next) { + if (BKE_object_is_child_recursive(ob_parent, ob_iter)) { + if (ob) { + RNA_id_pointer_create(&ob_iter->id, &ptr); + DEG_id_tag_update(&ob_iter->id, ID_RECALC_COPY_ON_WRITE); + } + else { + Base *base_iter = BKE_view_layer_base_find(view_layer, ob_iter); + RNA_pointer_create(&scene->id, &RNA_ObjectBase, base_iter, &ptr); + } + RNA_property_boolean_set(&ptr, base_or_object_prop, value); + } + } + + /* We don't call RNA_property_update() due to performance, so we batch update them. */ + if (ob) { + BKE_main_collection_sync_remap(bmain); + DEG_relations_tag_update(bmain); + } + else { + BKE_layer_collection_sync(scene, view_layer); + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); + } +} + +/** + * Object properties. + * */ +static void outliner__object_set_flag_recursive_cb(bContext *C, void *poin, void *poin2) +{ + Object *ob = poin; + char *propname = poin2; + outliner_object_set_flag_recursive_cb(C, NULL, ob, propname); +} + +/** + * Base properties. + * */ +static void outliner__base_set_flag_recursive_cb(bContext *C, void *poin, void *poin2) { Base *base = poin; - Object *ob = base->object; + char *propname = poin2; + outliner_object_set_flag_recursive_cb(C, base, NULL, propname); +} - const bool is_visible = ((base->flag & BASE_HIDDEN) == 0) && - ((ob->restrictflag & OB_RESTRICT_VIEW) == 0); - return !is_visible; +/** Create either a RNA_LayerCollection or a RNA_Collection pointer. */ +static void outliner_layer_or_collection_pointer_create(Scene *scene, + LayerCollection *layer_collection, + Collection *collection, + PointerRNA *ptr) +{ + if (collection) { + RNA_id_pointer_create(&collection->id, ptr); + } + else { + RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, ptr); + } } -static void hidebutton_base_flag_cb(bContext *C, void *poin, void *poin2) +/** Create either a RNA_ObjectBase or a RNA_Object pointer. */ +static void outliner_base_or_object_pointer_create(ViewLayer *view_layer, + Collection *collection, + Object *ob, + PointerRNA *ptr) { - wmWindow *win = CTX_wm_window(C); - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = poin; - Base *base = poin2; - Object *ob = base->object; - bool do_disable = (CTX_wm_window(C)->eventstate->alt != 0); - bool do_isolate = (win->eventstate->ctrl != 0) && !do_disable; - bool extend = (win->eventstate->shift != 0); - bool depsgraph_changed = false; - const bool is_linked = ID_IS_LINKED(ob); + if (collection) { + RNA_id_pointer_create(&ob->id, ptr); + } + else { + Base *base = BKE_view_layer_base_find(view_layer, ob); + RNA_pointer_create(&base->object->id, &RNA_ObjectBase, base, ptr); + } +} - if (do_disable) { - if (!is_linked) { - ob->restrictflag |= OB_RESTRICT_VIEW; - depsgraph_changed = true; - } +/* Note: Collection is only valid when we want to change the collection data, otherwise we get it + * from layer collection. Layer collection is valid whenever we are looking at a view layer. */ +static void outliner_collection_set_flag_recursive(Scene *scene, + ViewLayer *view_layer, + LayerCollection *layer_collection, + Collection *collection, + PropertyRNA *layer_or_collection_prop, + PropertyRNA *base_or_object_prop, + const bool value) +{ + if (layer_collection && layer_collection->flag & LAYER_COLLECTION_EXCLUDE) { + return; } - else if (do_isolate) { - depsgraph_changed = (!is_linked) && ((ob->restrictflag & OB_RESTRICT_VIEW) != 0); + PointerRNA ptr; + outliner_layer_or_collection_pointer_create(scene, layer_collection, collection, &ptr); + RNA_property_boolean_set(&ptr, layer_or_collection_prop, value); - if (!extend) { - /* Make only one base visible. */ - for (Base *other = view_layer->object_bases.first; other; other = other->next) { - other->flag |= BASE_HIDDEN; - } + /* Set the same flag for the nested objects as well. */ + if (base_or_object_prop) { + /* Note: We can't use BKE_collection_object_cache_get() + * otherwise we would not take collection exclusion into account. */ + for (CollectionObject *cob = layer_collection->collection->gobject.first; cob; + cob = cob->next) { - base->flag &= ~BASE_HIDDEN; - } - else { - /* Toggle visibility of one base. */ - base->flag ^= BASE_HIDDEN; - } + outliner_base_or_object_pointer_create(view_layer, collection, cob->ob, &ptr); + RNA_property_boolean_set(&ptr, base_or_object_prop, value); - if (!is_linked) { - ob->restrictflag &= ~OB_RESTRICT_VIEW; + if (collection) { + DEG_id_tag_update(&cob->ob->id, ID_RECALC_COPY_ON_WRITE); + } } } - else if (ob->restrictflag & OB_RESTRICT_VIEW) { - if (!is_linked) { - ob->restrictflag &= ~OB_RESTRICT_VIEW; - base->flag &= ~BASE_HIDDEN; + + /* Keep going recursively. */ + ListBase *lb = (layer_collection ? &layer_collection->layer_collections : &collection->children); + for (Link *link = lb->first; link; link = link->next) { + LayerCollection *layer_collection_iter = layer_collection ? (LayerCollection *)link : NULL; + Collection *collection_iter = layer_collection ? + (collection ? layer_collection_iter->collection : NULL) : + ((CollectionChild *)link)->collection; + outliner_collection_set_flag_recursive(scene, + view_layer, + layer_collection_iter, + collection_iter, + layer_or_collection_prop, + base_or_object_prop, + value); + } + + if (collection) { + DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE); + } +} + +/** Check if collection is already isolated. + * + * A collection is isolated if all its parents and children are "visible". + * All the other collections must be "invisible". + * + * Note: We could/should boost performance by iterating over the tree twice. + * First tagging all the children/parent collections, then getting their values and comparing. + * To run BKE_collection_has_collection() so many times is silly and slow. + */ +static bool outliner_collection_is_isolated(Scene *scene, + const LayerCollection *layer_collection_cmp, + const Collection *collection_cmp, + const bool value_cmp, + const PropertyRNA *layer_or_collection_prop, + LayerCollection *layer_collection, + Collection *collection) +{ + PointerRNA ptr; + outliner_layer_or_collection_pointer_create(scene, layer_collection, collection, &ptr); + const bool value = RNA_property_boolean_get(&ptr, (PropertyRNA *)layer_or_collection_prop); + Collection *collection_ensure = collection ? collection : layer_collection->collection; + const Collection *collection_ensure_cmp = collection_cmp ? collection_cmp : + layer_collection_cmp->collection; + + if (collection_ensure->flag & COLLECTION_IS_MASTER) { + } + else if (collection_ensure == collection_ensure_cmp) { + } + else if (BKE_collection_has_collection(collection_ensure, (Collection *)collection_ensure_cmp) || + BKE_collection_has_collection((Collection *)collection_ensure_cmp, collection_ensure)) { + /* This collection is either a parent or a child of the collection. + * We expect it to be set "visble" already. */ + if (value != value_cmp) { + return false; } - depsgraph_changed = true; } else { - base->flag ^= BASE_HIDDEN; + /* This collection is neither a parent nor a child of the collection. + * We expect it to be "invisble". */ + if (value == value_cmp) { + return false; + } } - if (depsgraph_changed) { - BKE_main_collection_sync_remap(bmain); - DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); - DEG_relations_tag_update(bmain); - WM_main_add_notifier(NC_OBJECT | ND_DRAW, &ob->id); + /* Keep going recursively. */ + ListBase *lb = (layer_collection ? &layer_collection->layer_collections : &collection->children); + for (Link *link = lb->first; link; link = link->next) { + LayerCollection *layer_collection_iter = layer_collection ? (LayerCollection *)link : NULL; + Collection *collection_iter = layer_collection ? + (collection ? layer_collection_iter->collection : NULL) : + ((CollectionChild *)link)->collection; + if (layer_collection_iter && layer_collection_iter->flag & LAYER_COLLECTION_EXCLUDE) { + continue; + } + if (!outliner_collection_is_isolated(scene, + layer_collection_cmp, + collection_cmp, + value_cmp, + layer_or_collection_prop, + layer_collection_iter, + collection_iter)) { + return false; + } } - if (!do_disable) { - BKE_layer_collection_sync(scene, view_layer); - DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - } + return true; } -static int layer_collection_pushed_state_cb(bContext *UNUSED(C), void *poin) +static void outliner_collection_isolate_flag(Scene *scene, + ViewLayer *view_layer, + LayerCollection *layer_collection, + Collection *collection, + PropertyRNA *layer_or_collection_prop, + const char *propname, + const bool value) { - LayerCollection *lc = poin; - Collection *collection = lc->collection; + PointerRNA ptr; + const bool is_hide = strstr(propname, "hide_") != NULL; + + LayerCollection *top_layer_collection = layer_collection ? view_layer->layer_collections.first : + NULL; + Collection *top_collection = collection ? scene->master_collection : NULL; + + bool was_isolated = (value == is_hide); + was_isolated &= outliner_collection_is_isolated(scene, + layer_collection, + collection, + !is_hide, + layer_or_collection_prop, + top_layer_collection, + top_collection); + + if (was_isolated) { + const bool default_value = RNA_property_boolean_get_default(NULL, layer_or_collection_prop); + /* Make every collection go back to its default "visibility" state. */ + outliner_collection_set_flag_recursive(scene, + view_layer, + top_layer_collection, + top_collection, + layer_or_collection_prop, + NULL, + default_value); + return; + } - const bool is_visible = ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) == 0) && - ((collection->flag & COLLECTION_RESTRICT_VIEW) == 0); - return !is_visible; + /* Make every collection "invisible". */ + outliner_collection_set_flag_recursive(scene, + view_layer, + top_layer_collection, + top_collection, + layer_or_collection_prop, + NULL, + is_hide); + + /* Make this collection and its children collections the only "visible". */ + outliner_collection_set_flag_recursive( + scene, view_layer, layer_collection, collection, layer_or_collection_prop, NULL, !is_hide); + + /* Make this collection direct parents also "visible". */ + if (layer_collection) { + LayerCollection *lc_parent = layer_collection; + for (LayerCollection *lc_iter = top_layer_collection->layer_collections.first; lc_iter; + lc_iter = lc_iter->next) { + if (BKE_layer_collection_has_layer_collection(lc_iter, layer_collection)) { + lc_parent = lc_iter; + break; + } + } + + while (lc_parent != layer_collection) { + outliner_layer_or_collection_pointer_create( + scene, lc_parent, collection ? lc_parent->collection : NULL, &ptr); + RNA_property_boolean_set(&ptr, layer_or_collection_prop, !is_hide); + + for (LayerCollection *lc_iter = lc_parent->layer_collections.first; lc_iter; + lc_iter = lc_iter->next) { + if (BKE_layer_collection_has_layer_collection(lc_iter, layer_collection)) { + lc_parent = lc_iter; + break; + } + } + } + } + else { + CollectionParent *parent; + Collection *child = collection; + while ((parent = child->parents.first)) { + if (parent->collection->flag & COLLECTION_IS_MASTER) { + break; + } + RNA_id_pointer_create(&parent->collection->id, &ptr); + RNA_property_boolean_set(&ptr, layer_or_collection_prop, !is_hide); + child = parent->collection; + } + } } -static void hidebutton_layer_collection_flag_cb(bContext *C, void *poin, void *poin2) +static void outliner_collection_set_flag_recursive_cb(bContext *C, + LayerCollection *layer_collection, + Collection *collection, + const char *propname) { Main *bmain = CTX_data_main(C); wmWindow *win = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = poin; - LayerCollection *lc = poin2; - Collection *collection = lc->collection; - bool do_disable = (win->eventstate->alt != 0); - bool do_isolate = (win->eventstate->ctrl != 0) && !do_disable; + ViewLayer *view_layer = CTX_data_view_layer(C); + PointerRNA ptr; + + bool do_isolate = (win->eventstate->ctrl != 0); bool extend = (win->eventstate->shift != 0); - bool depsgraph_changed = false; - if (do_disable) { - if (!ID_IS_LINKED(collection)) { - collection->flag |= COLLECTION_RESTRICT_VIEW; - depsgraph_changed = true; - } + if (!ELEM(true, do_isolate, extend)) { + return; + } + + /* Create PointerRNA and PropertyRNA for either Collection or LayerCollection. */ + ID *id = collection ? &collection->id : &scene->id; + StructRNA *struct_rna = collection ? &RNA_Collection : &RNA_LayerCollection; + void *data = collection ? (void *)collection : (void *)layer_collection; + + RNA_pointer_create(id, struct_rna, data, &ptr); + outliner_layer_or_collection_pointer_create(scene, layer_collection, collection, &ptr); + PropertyRNA *layer_or_collection_prop = RNA_struct_type_find_property(struct_rna, propname); + const bool value = RNA_property_boolean_get(&ptr, layer_or_collection_prop); + + PropertyRNA *base_or_object_prop = NULL; + if (layer_collection != NULL) { + /* If we are toggling Layer collections we still want to change the properties of the base + * or the objects. If we have a matching property, toggle it as well, it can be NULL. */ + struct_rna = collection ? &RNA_Object : &RNA_ObjectBase; + base_or_object_prop = RNA_struct_type_find_property(struct_rna, propname); } - else if (do_isolate) { - depsgraph_changed |= BKE_layer_collection_isolate(scene, view_layer, lc, extend); + + if (extend) { + outliner_collection_set_flag_recursive(scene, + view_layer, + layer_collection, + collection, + layer_or_collection_prop, + base_or_object_prop, + value); } else { - bool make_visible = ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0) || - ((collection->flag & COLLECTION_RESTRICT_VIEW) != 0); - depsgraph_changed |= BKE_layer_collection_set_visible(view_layer, lc, make_visible, extend); - } + outliner_collection_isolate_flag(scene, + view_layer, + layer_collection, + collection, + layer_or_collection_prop, + propname, + value); + } + + /* We don't call RNA_property_update() due to performance, so we batch update them. */ + BKE_main_collection_sync_remap(bmain); + DEG_relations_tag_update(bmain); +} - BKE_layer_collection_sync(scene, view_layer); - DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); +/** + * Layer collection properties called from the ViewLayer mode. + * Change the (non-excluded) collection children, and the objects nested to them all. + */ +static void view_layer__layer_collection_set_flag_recursive_cb(bContext *C, + void *poin, + void *poin2) +{ + LayerCollection *layer_collection = poin; + char *propname = poin2; + outliner_collection_set_flag_recursive_cb(C, layer_collection, NULL, propname); +} - if (depsgraph_changed) { - BKE_main_collection_sync_remap(bmain); - DEG_relations_tag_update(bmain); - } - WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL); +/** + * Collection properties called from the ViewLayer mode. + * Change the (non-excluded) collection children, and the objects nested to them all. + */ +static void view_layer__collection_set_flag_recursive_cb(bContext *C, void *poin, void *poin2) +{ + LayerCollection *layer_collection = poin; + char *propname = poin2; + outliner_collection_set_flag_recursive_cb( + C, layer_collection, layer_collection->collection, propname); +} + +/** + * Collection properties called from the Scenes mode. + * Change the collection children but no objects. + */ +static void scenes__collection_set_flag_recursive_cb(bContext *C, void *poin, void *poin2) +{ + Collection *collection = poin; + char *propname = poin2; + outliner_collection_set_flag_recursive_cb(C, NULL, collection, propname); } static void namebutton_cb(bContext *C, void *tsep, char *oldname) @@ -580,7 +866,10 @@ static void outliner_draw_restrictbuts(uiBlock *block, bool initialized; PropertyRNA *object_hide_viewport, *object_hide_select, *object_hide_render; + PropertyRNA *base_hide_viewport; PropertyRNA *collection_hide_viewport, *collection_hide_select, *collection_hide_render; + PropertyRNA *layer_collection_holdout, *layer_collection_indirect_only, + *layer_collection_hide_viewport; PropertyRNA *modifier_show_viewport, *modifier_show_render; } props = {false}; @@ -588,16 +877,57 @@ static void outliner_draw_restrictbuts(uiBlock *block, props.object_hide_viewport = RNA_struct_type_find_property(&RNA_Object, "hide_viewport"); props.object_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select"); props.object_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render"); - props.collection_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select"); + props.base_hide_viewport = RNA_struct_type_find_property(&RNA_ObjectBase, "hide_viewport"); props.collection_hide_viewport = RNA_struct_type_find_property(&RNA_Collection, "hide_viewport"); + props.collection_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select"); props.collection_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render"); + props.layer_collection_holdout = RNA_struct_type_find_property(&RNA_LayerCollection, + "holdout"); + props.layer_collection_indirect_only = RNA_struct_type_find_property(&RNA_LayerCollection, + "indirect_only"); + props.layer_collection_hide_viewport = RNA_struct_type_find_property(&RNA_LayerCollection, + "hide_viewport"); props.modifier_show_viewport = RNA_struct_type_find_property(&RNA_Modifier, "show_viewport"); props.modifier_show_render = RNA_struct_type_find_property(&RNA_Modifier, "show_render"); props.initialized = true; } + struct { + int select; + int hide; + int viewport; + int render; + int indirect_only; + int holdout; + } restrict_offsets = {0}; + int restrict_column_offset = 0; + + /* This will determine the order of drawing from RIGHT to LEFT. */ + if (soops->outlinevis == SO_VIEW_LAYER) { + if (soops->show_restrict_flags & SO_RESTRICT_INDIRECT_ONLY) { + restrict_offsets.indirect_only = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; + } + if (soops->show_restrict_flags & SO_RESTRICT_HOLDOUT) { + restrict_offsets.holdout = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; + } + } + if (soops->show_restrict_flags & SO_RESTRICT_RENDER) { + restrict_offsets.render = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; + } + if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) { + restrict_offsets.viewport = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; + } + if (soops->show_restrict_flags & SO_RESTRICT_HIDE) { + restrict_offsets.hide = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; + } + if (soops->show_restrict_flags & SO_RESTRICT_SELECT) { + restrict_offsets.select = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH; + } + BLI_assert((restrict_column_offset * UI_UNIT_X + V2D_SCROLL_WIDTH) == + outliner_restrict_columns_width(soops)); + /* Create buttons. */ uiBut *bt; @@ -605,27 +935,29 @@ static void outliner_draw_restrictbuts(uiBlock *block, TreeStoreElem *tselem = TREESTORE(te); if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { if (tselem->type == TSE_R_LAYER && (soops->outlinevis == SO_SCENES)) { - /* View layer render toggle. */ - ViewLayer *layer = te->directdata; + if (soops->show_restrict_flags & SO_RESTRICT_RENDER) { + /* View layer render toggle. */ + ViewLayer *layer = te->directdata; - bt = uiDefIconButBitS(block, - UI_BTYPE_ICON_TOGGLE_N, - VIEW_LAYER_RENDER, - 0, - ICON_RESTRICT_RENDER_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - &layer->flag, - 0, - 0, - 0, - 0, - TIP_("Use view layer for rendering")); - UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); + bt = uiDefIconButBitS(block, + UI_BTYPE_ICON_TOGGLE_N, + VIEW_LAYER_RENDER, + 0, + ICON_RESTRICT_RENDER_OFF, + (int)(ar->v2d.cur.xmax - restrict_offsets.render), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &layer->flag, + 0, + 0, + 0, + 0, + TIP_("Use view layer for rendering")); + UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); + } } else if ((tselem->type == 0 && te->idcode == ID_OB) && (te->flag & TE_CHILD_NOT_IN_COLLECTION)) { @@ -634,40 +966,65 @@ static void outliner_draw_restrictbuts(uiBlock *block, else if (tselem->type == 0 && te->idcode == ID_OB) { PointerRNA ptr; Object *ob = (Object *)tselem->id; - RNA_pointer_create(&ob->id, &RNA_Object, ob, &ptr); - Base *base = BKE_view_layer_base_find(view_layer, ob); - - if (base) { - int icon = ICON_RESTRICT_VIEW_ON; - if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0) { - icon = (base->flag & BASE_HIDDEN) != 0 ? ICON_HIDE_ON : ICON_HIDE_OFF; + RNA_id_pointer_create(&ob->id, &ptr); + + if (soops->show_restrict_flags & SO_RESTRICT_HIDE) { + Base *base = (te->directdata) ? (Base *)te->directdata : + BKE_view_layer_base_find(view_layer, ob); + if (base) { + PointerRNA base_ptr; + RNA_pointer_create(&ob->id, &RNA_ObjectBase, base, &base_ptr); + bt = uiDefIconButR_prop(block, + UI_BTYPE_ICON_TOGGLE, + 0, + 0, + (int)(ar->v2d.cur.xmax - restrict_offsets.hide), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &base_ptr, + props.base_hide_viewport, + -1, + 0, + 0, + 0, + 0, + TIP_("Temporarly hide in viewport\n" + "* Shift to set children")); + UI_but_func_set( + bt, outliner__base_set_flag_recursive_cb, base, (void *)"hide_viewport"); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); } - bt = uiDefIconBut(block, - UI_BTYPE_ICON_TOGGLE, - 0, - icon, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - TIP_("Hide object in viewport\n" - "* Alt to disable for all viewports\n" - "* Ctrl to isolate visibility")); - UI_but_func_set(bt, hidebutton_base_flag_cb, view_layer, base); - UI_but_func_pushed_state_set(bt, base_pushed_state_cb, base); + } + + if (soops->show_restrict_flags & SO_RESTRICT_SELECT) { + bt = uiDefIconButR_prop(block, + UI_BTYPE_ICON_TOGGLE, + 0, + 0, + (int)(ar->v2d.cur.xmax - restrict_offsets.select), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &ptr, + props.object_hide_select, + -1, + 0, + 0, + -1, + -1, + TIP_("Disable selection in viewport\n" + "* Shift to set children")); + UI_but_func_set(bt, outliner__object_set_flag_recursive_cb, ob, (char *)"hide_select"); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); } - else { + + if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) { bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, 0, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), + (int)(ar->v2d.cur.xmax - restrict_offsets.viewport), te->ys, UI_UNIT_X, UI_UNIT_Y, @@ -678,256 +1035,320 @@ static void outliner_draw_restrictbuts(uiBlock *block, 0, -1, -1, + TIP_("Globally disable in viewports\n" + "* Shift to set children")); + UI_but_func_set(bt, outliner__object_set_flag_recursive_cb, ob, (void *)"hide_viewport"); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } + + if (soops->show_restrict_flags & SO_RESTRICT_RENDER) { + bt = uiDefIconButR_prop(block, + UI_BTYPE_ICON_TOGGLE, + 0, + 0, + (int)(ar->v2d.cur.xmax - restrict_offsets.render), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &ptr, + props.object_hide_render, + -1, + 0, + 0, + -1, + -1, + TIP_("Globally disable in renders\n" + "* Shift to set children")); + UI_but_func_set(bt, outliner__object_set_flag_recursive_cb, ob, (char *)"hide_render"); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } + } + else if (tselem->type == TSE_MODIFIER) { + ModifierData *md = (ModifierData *)te->directdata; + + PointerRNA ptr; + RNA_pointer_create(tselem->id, &RNA_Modifier, md, &ptr); + + if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) { + bt = uiDefIconButR_prop(block, + UI_BTYPE_ICON_TOGGLE, + 0, + 0, + (int)(ar->v2d.cur.xmax - restrict_offsets.viewport), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &ptr, + props.modifier_show_viewport, + -1, + 0, + 0, + -1, + -1, + NULL); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } + + if (soops->show_restrict_flags & SO_RESTRICT_RENDER) { + bt = uiDefIconButR_prop(block, + UI_BTYPE_ICON_TOGGLE, + 0, + 0, + (int)(ar->v2d.cur.xmax - restrict_offsets.render), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &ptr, + props.modifier_show_render, + -1, + 0, + 0, + -1, + -1, NULL); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); } + } + else if (tselem->type == TSE_POSE_CHANNEL) { + bPoseChannel *pchan = (bPoseChannel *)te->directdata; + Bone *bone = pchan->bone; + Object *ob = (Object *)tselem->id; - bt = uiDefIconButR_prop(block, + if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) { + bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, + BONE_HIDDEN_P, 0, - 0, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), + ICON_HIDE_OFF, + (int)(ar->v2d.cur.xmax - restrict_offsets.viewport), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, - props.object_hide_select, - -1, + &(bone->flag), + 0, 0, 0, - -1, - -1, - NULL); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + 0, + TIP_("Restrict visibility in the 3D View")); + UI_but_func_set(bt, restrictbutton_bone_visibility_cb, ob->data, bone); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); + } - bt = uiDefIconButR_prop(block, + if (soops->show_restrict_flags & SO_RESTRICT_SELECT) { + bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, + BONE_UNSELECTABLE, 0, - 0, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), + ICON_RESTRICT_SELECT_OFF, + (int)(ar->v2d.cur.xmax - restrict_offsets.select), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, - props.object_hide_render, - -1, + &(bone->flag), + 0, 0, 0, - -1, - -1, - NULL); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + 0, + TIP_("Restrict selection in the 3D View")); + UI_but_func_set(bt, restrictbutton_bone_select_cb, ob->data, bone); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); + } } - else if (tselem->type == TSE_MODIFIER) { - ModifierData *md = (ModifierData *)te->directdata; - - PointerRNA ptr; - RNA_pointer_create(tselem->id, &RNA_Modifier, md, &ptr); + else if (tselem->type == TSE_EBONE) { + EditBone *ebone = (EditBone *)te->directdata; - bt = uiDefIconButR_prop(block, + if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) { + bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, + BONE_HIDDEN_A, 0, - 0, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), + ICON_RESTRICT_VIEW_OFF, + (int)(ar->v2d.cur.xmax - restrict_offsets.viewport), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, - props.modifier_show_viewport, - -1, + &(ebone->flag), + 0, 0, 0, - -1, - -1, - NULL); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + 0, + TIP_("Restrict visibility in the 3D View")); + UI_but_func_set(bt, restrictbutton_ebone_visibility_cb, NULL, ebone); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); + } - bt = uiDefIconButR_prop(block, + if (soops->show_restrict_flags & SO_RESTRICT_SELECT) { + bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, + BONE_UNSELECTABLE, 0, - 0, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), + ICON_RESTRICT_SELECT_OFF, + (int)(ar->v2d.cur.xmax - restrict_offsets.select), te->ys, UI_UNIT_X, UI_UNIT_Y, - &ptr, - props.modifier_show_render, - -1, + &(ebone->flag), 0, 0, - -1, - -1, - NULL); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - } - else if (tselem->type == TSE_POSE_CHANNEL) { - bPoseChannel *pchan = (bPoseChannel *)te->directdata; - Bone *bone = pchan->bone; - Object *ob = (Object *)tselem->id; - - bt = uiDefIconButBitI(block, - UI_BTYPE_ICON_TOGGLE, - BONE_HIDDEN_P, - 0, - ICON_HIDE_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - &(bone->flag), - 0, - 0, - 0, - 0, - TIP_("Restrict/Allow visibility in the 3D View")); - UI_but_func_set(bt, restrictbutton_bone_visibility_cb, ob->data, bone); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); - - bt = uiDefIconButBitI(block, - UI_BTYPE_ICON_TOGGLE, - BONE_UNSELECTABLE, - 0, - ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - &(bone->flag), - 0, - 0, - 0, - 0, - TIP_("Restrict/Allow selection in the 3D View")); - UI_but_func_set(bt, restrictbutton_bone_select_cb, ob->data, bone); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); - } - else if (tselem->type == TSE_EBONE) { - EditBone *ebone = (EditBone *)te->directdata; - - bt = uiDefIconButBitI(block, - UI_BTYPE_ICON_TOGGLE, - BONE_HIDDEN_A, - 0, - ICON_RESTRICT_VIEW_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - &(ebone->flag), - 0, - 0, - 0, - 0, - TIP_("Restrict/Allow visibility in the 3D View")); - UI_but_func_set(bt, restrictbutton_ebone_visibility_cb, NULL, ebone); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); - - bt = uiDefIconButBitI(block, - UI_BTYPE_ICON_TOGGLE, - BONE_UNSELECTABLE, - 0, - ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - &(ebone->flag), - 0, - 0, - 0, - 0, - TIP_("Restrict/Allow selection in the 3D View")); - UI_but_func_set(bt, restrictbutton_ebone_select_cb, NULL, ebone); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); + 0, + 0, + TIP_("Restrict selection in the 3D View")); + UI_but_func_set(bt, restrictbutton_ebone_select_cb, NULL, ebone); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); + } } else if (tselem->type == TSE_GP_LAYER) { ID *id = tselem->id; bGPDlayer *gpl = (bGPDlayer *)te->directdata; - bt = uiDefIconButBitS(block, - UI_BTYPE_ICON_TOGGLE, - GP_LAYER_HIDE, - 0, - ICON_HIDE_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - &gpl->flag, - 0, - 0, - 0, - 0, - TIP_("Restrict/Allow visibility in the 3D View")); - UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); - UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); - - bt = uiDefIconButBitS( - block, - UI_BTYPE_ICON_TOGGLE, - GP_LAYER_LOCKED, - 0, - ICON_UNLOCKED, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - &gpl->flag, - 0, - 0, - 0, - 0, - TIP_("Restrict/Allow editing of strokes and keyframes in this layer")); - UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) { + bt = uiDefIconButBitS(block, + UI_BTYPE_ICON_TOGGLE, + GP_LAYER_HIDE, + 0, + ICON_HIDE_OFF, + (int)(ar->v2d.cur.xmax - restrict_offsets.viewport), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &gpl->flag, + 0, + 0, + 0, + 0, + TIP_("Restrict visibility in the 3D View")); + UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE); + } + + if (soops->show_restrict_flags & SO_RESTRICT_SELECT) { + bt = uiDefIconButBitS(block, + UI_BTYPE_ICON_TOGGLE, + GP_LAYER_LOCKED, + 0, + ICON_UNLOCKED, + (int)(ar->v2d.cur.xmax - restrict_offsets.select), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &gpl->flag, + 0, + 0, + 0, + 0, + TIP_("Restrict editing of strokes and keyframes in this layer")); + UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } } else if (outliner_is_collection_tree_element(te)) { - LayerCollection *lc = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata : NULL; + LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ? + te->directdata : + NULL; Collection *collection = outliner_collection_from_tree_element(te); - if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) && + if ((!layer_collection || !(layer_collection->flag & LAYER_COLLECTION_EXCLUDE)) && !(collection->flag & COLLECTION_IS_MASTER)) { PointerRNA collection_ptr; RNA_id_pointer_create(&collection->id, &collection_ptr); - if (lc != NULL) { - int icon = ICON_RESTRICT_VIEW_ON; - if ((collection->flag & COLLECTION_RESTRICT_VIEW) == 0) { - icon = (lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0 ? ICON_HIDE_ON : - ICON_HIDE_OFF; + if (layer_collection != NULL) { + PointerRNA layer_collection_ptr; + RNA_pointer_create( + &scene->id, &RNA_LayerCollection, layer_collection, &layer_collection_ptr); + + if (soops->show_restrict_flags & SO_RESTRICT_HIDE) { + bt = uiDefIconButR_prop(block, + UI_BTYPE_ICON_TOGGLE, + 0, + 0, + (int)(ar->v2d.cur.xmax - restrict_offsets.hide), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &layer_collection_ptr, + props.layer_collection_hide_viewport, + -1, + 0, + 0, + 0, + 0, + TIP_("Temporarily hide in viewport\n" + "* Ctrl to isolate collection\n" + "* Shift to set inside collections and objects")); + UI_but_func_set(bt, + view_layer__layer_collection_set_flag_recursive_cb, + layer_collection, + (char *)"hide_viewport"); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } + + if (soops->show_restrict_flags & SO_RESTRICT_HOLDOUT) { + bt = uiDefIconButR_prop(block, + UI_BTYPE_ICON_TOGGLE, + 0, + 0, + (int)(ar->v2d.cur.xmax - restrict_offsets.holdout), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &layer_collection_ptr, + props.layer_collection_holdout, + -1, + 0, + 0, + 0, + 0, + TIP_("Mask out objects in collection from view layer\n" + "* Ctrl to isolate collection\n" + "* Shift to set inside collections")); + UI_but_func_set(bt, + view_layer__layer_collection_set_flag_recursive_cb, + layer_collection, + (char *)"holdout"); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } + + if (soops->show_restrict_flags & SO_RESTRICT_INDIRECT_ONLY) { + bt = uiDefIconButR_prop( + block, + UI_BTYPE_ICON_TOGGLE, + 0, + (layer_collection->flag & LAYER_COLLECTION_INDIRECT_ONLY) != 0 ? 0 : ICON_REMOVE, + (int)(ar->v2d.cur.xmax - restrict_offsets.indirect_only), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &layer_collection_ptr, + props.layer_collection_indirect_only, + -1, + 0, + 0, + 0, + 0, + TIP_("Objects in collection only contribute indirectly (through shadows and " + "reflections) in the view layer\n" + "* Ctrl to isolate collection\n" + "* Shift to set inside collections")); + UI_but_func_set(bt, + view_layer__layer_collection_set_flag_recursive_cb, + layer_collection, + (char *)"indirect_only"); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); } - bt = uiDefIconBut(block, - UI_BTYPE_ICON_TOGGLE, - 0, - icon, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0, - 0, - 0, - 0, - TIP_("Hide collection in viewport\n" - "* Alt to disable for all viewports\n" - "* Ctrl to isolate visibility\n" - "* Shift to hide inside objects and collections")); - UI_but_func_set(bt, hidebutton_layer_collection_flag_cb, view_layer, lc); - UI_but_func_pushed_state_set(bt, layer_collection_pushed_state_cb, lc); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); } - else { + + if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) { bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, 0, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), + (int)(ar->v2d.cur.xmax - restrict_offsets.viewport), te->ys, UI_UNIT_X, UI_UNIT_Y, @@ -938,45 +1359,87 @@ static void outliner_draw_restrictbuts(uiBlock *block, 0, 0, 0, - NULL); + TIP_("Globally disable in viewports\n" + "* Ctrl to isolate collection\n" + "* Shift to set inside collections and objects")); + if (layer_collection != NULL) { + UI_but_func_set(bt, + view_layer__collection_set_flag_recursive_cb, + layer_collection, + (char *)"hide_viewport"); + } + else { + UI_but_func_set(bt, + scenes__collection_set_flag_recursive_cb, + collection, + (char *)"hide_viewport"); + } UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); } - bt = uiDefIconButR_prop(block, - UI_BTYPE_ICON_TOGGLE, - 0, - 0, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - &collection_ptr, - props.collection_hide_render, - -1, - 0, - 0, - 0, - 0, - NULL); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + if (soops->show_restrict_flags & SO_RESTRICT_RENDER) { + bt = uiDefIconButR_prop(block, + UI_BTYPE_ICON_TOGGLE, + 0, + 0, + (int)(ar->v2d.cur.xmax - restrict_offsets.render), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &collection_ptr, + props.collection_hide_render, + -1, + 0, + 0, + 0, + 0, + TIP_("Globally disable in renders\n" + "* Ctrl to isolate collection\n" + "* Shift to set inside collections and objects")); + if (layer_collection != NULL) { + UI_but_func_set(bt, + view_layer__collection_set_flag_recursive_cb, + layer_collection, + (char *)"hide_render"); + } + else { + UI_but_func_set( + bt, scenes__collection_set_flag_recursive_cb, collection, (char *)"hide_render"); + } + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } - bt = uiDefIconButR_prop(block, - UI_BTYPE_ICON_TOGGLE, - 0, - 0, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - &collection_ptr, - props.collection_hide_select, - -1, - 0, - 0, - 0, - 0, - NULL); - UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + if (soops->show_restrict_flags & SO_RESTRICT_SELECT) { + bt = uiDefIconButR_prop(block, + UI_BTYPE_ICON_TOGGLE, + 0, + 0, + (int)(ar->v2d.cur.xmax - restrict_offsets.select), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + &collection_ptr, + props.collection_hide_select, + -1, + 0, + 0, + 0, + 0, + TIP_("Disable selection in viewport\n" + "* Ctrl to isolate collection\n" + "* Shift to set inside collections and objects")); + if (layer_collection != NULL) { + UI_but_func_set(bt, + view_layer__collection_set_flag_recursive_cb, + layer_collection, + (char *)"hide_select"); + } + else { + UI_but_func_set( + bt, scenes__collection_set_flag_recursive_cb, collection, (char *)"hide_select"); + } + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + } } } } @@ -1005,6 +1468,23 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s but_flag |= UI_BUT_DISABLED; } + BLI_str_format_int_grouped(buf, id->us); + bt = uiDefBut(block, + UI_BTYPE_BUT, + 1, + buf, + (int)(ar->v2d.cur.xmax - OL_TOG_USER_BUTS_USERS), + te->ys, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0, + 0, + TIP_("Number of users of this data-block")); + UI_but_flag_enable(bt, but_flag); + if (id->flag & LIB_FAKEUSER) { icon = ICON_FILE_TICK; tip = TIP_("Data-block will be retained using a fake user"); @@ -1018,7 +1498,7 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s LIB_FAKEUSER, 1, icon, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), + (int)(ar->v2d.cur.xmax - OL_TOG_USER_BUTS_STATUS), te->ys, UI_UNIT_X, UI_UNIT_Y, @@ -1031,29 +1511,12 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL); UI_but_flag_enable(bt, but_flag); - BLI_str_format_int_grouped(buf, id->us); - bt = uiDefBut(block, - UI_BTYPE_BUT, - 1, - buf, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), - te->ys, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0, - 0, - TIP_("Number of users of this data-block")); - UI_but_flag_enable(bt, but_flag); - bt = uiDefButBitS(block, UI_BTYPE_ICON_TOGGLE, LIB_FAKEUSER, 1, (id->flag & LIB_FAKEUSER) ? "F" : " ", - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), + (int)(ar->v2d.cur.xmax - OL_TOG_USER_BUTS_FAKEUSER), te->ys, UI_UNIT_X, UI_UNIT_Y, @@ -1179,8 +1642,13 @@ static void outliner_draw_rnabuts( } } -static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, TreeElement *te) +static void outliner_buttons(const bContext *C, + uiBlock *block, + ARegion *ar, + const float restrict_column_width, + TreeElement *te) { + SpaceOutliner *soops = CTX_wm_space_outliner(C); uiBut *bt; TreeStoreElem *tselem; int spx, dx, len; @@ -1206,7 +1674,11 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Tre } spx = te->xs + 1.8f * UI_UNIT_X; - dx = ar->v2d.cur.xmax - (spx + 3.2f * UI_UNIT_X); + if ((tselem->type == TSE_LAYER_COLLECTION) && + (soops->show_restrict_flags & SO_RESTRICT_ENABLE)) { + spx += UI_UNIT_X; + } + dx = ar->v2d.cur.xmax - (spx + restrict_column_width + 0.2f * UI_UNIT_X); bt = uiDefBut(block, UI_BTYPE_TEXT, @@ -1778,6 +2250,60 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) return data; } +static void tselem_draw_layer_collection_enable_icon( + Scene *scene, uiBlock *block, int xmax, float x, float y, TreeElement *te, float alpha) +{ + /* Get RNA property (once for speed). */ + static PropertyRNA *exclude_prop = NULL; + if (exclude_prop == NULL) { + exclude_prop = RNA_struct_type_find_property(&RNA_LayerCollection, "exclude"); + } + + if (x >= xmax) { + /* Placement of icons, copied from interface_widgets.c. */ + float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT; + x += 2.0f * aspect; + y += 2.0f * aspect; + + /* restrict column clip... it has been coded by simply overdrawing, + * doesn't work for buttons */ + char color[4]; + int icon = RNA_property_ui_icon(exclude_prop); + if (UI_icon_get_theme_color(icon, (uchar *)color)) { + UI_icon_draw_ex(x, y, icon, U.inv_dpi_fac, alpha, 0.0f, color, true); + } + else { + UI_icon_draw_ex(x, y, icon, U.inv_dpi_fac, alpha, 0.0f, NULL, false); + } + } + else { + LayerCollection *layer_collection = te->directdata; + PointerRNA layer_collection_ptr; + RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, &layer_collection_ptr); + + char emboss = UI_block_emboss_get(block); + UI_block_emboss_set(block, UI_EMBOSS_NONE); + uiBut *bt = uiDefIconButR_prop(block, + UI_BTYPE_ICON_TOGGLE, + 0, + 0, + x, + y, + UI_UNIT_X, + UI_UNIT_Y, + &layer_collection_ptr, + exclude_prop, + -1, + 0, + 0, + 0, + 0, + NULL); + UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); + UI_block_emboss_set(block, emboss); + } +} + static void tselem_draw_icon(uiBlock *block, int xmax, float x, @@ -1801,7 +2327,13 @@ static void tselem_draw_icon(uiBlock *block, /* restrict column clip... it has been coded by simply overdrawing, * doesn't work for buttons */ - UI_icon_draw_alpha(x, y, data.icon, alpha); + char color[4]; + if (UI_icon_get_theme_color(data.icon, (uchar *)color)) { + UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true); + } + else { + UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, NULL, false); + } } else { uiDefIconBut(block, @@ -2068,6 +2600,7 @@ static void outliner_draw_tree_element(bContext *C, bool draw_grayed_out, int startx, int *starty, + const float restrict_column_width, TreeElement **te_edit) { TreeStoreElem *tselem; @@ -2090,8 +2623,8 @@ static void outliner_draw_tree_element(bContext *C, } /* icons can be ui buts, we don't want it to overlap with restrict */ - if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0) { - xmax -= OL_TOGW + UI_UNIT_X; + if (restrict_column_width > 0) { + xmax -= restrict_column_width + UI_UNIT_X; } GPU_blend(true); @@ -2150,13 +2683,21 @@ static void outliner_draw_tree_element(bContext *C, rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha); } + /* Checkbox to enable collections. */ + if ((tselem->type == TSE_LAYER_COLLECTION) && + (soops->show_restrict_flags & SO_RESTRICT_ENABLE)) { + tselem_draw_layer_collection_enable_icon( + scene, block, xmax, (float)startx + offsx + UI_UNIT_X, (float)*starty, te, 0.8f); + offsx += UI_UNIT_X; + } + /* active circle */ if (active != OL_DRAWSEL_NONE) { UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_aa(true, - (float)startx + UI_UNIT_X + 1.0f * ufac, + (float)startx + offsx + UI_UNIT_X + 1.0f * ufac, (float)*starty + 1.0f * ufac, - (float)startx + 2.0f * UI_UNIT_X - 1.0f * ufac, + (float)startx + offsx + 2.0f * UI_UNIT_X - 1.0f * ufac, (float)*starty + UI_UNIT_Y - 1.0f * ufac, UI_UNIT_Y / 2.0f - 1.0f * ufac, color); @@ -2190,7 +2731,6 @@ static void outliner_draw_tree_element(bContext *C, offsx += UI_UNIT_X; /* datatype icon */ - if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE))) { tselem_draw_icon( block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac, true); @@ -2306,6 +2846,7 @@ static void outliner_draw_tree_element(bContext *C, draw_childs_grayed_out, startx + UI_UNIT_X, starty, + restrict_column_width, te_edit); } } @@ -2585,7 +3126,7 @@ static void outliner_draw_tree(bContext *C, ViewLayer *view_layer, ARegion *ar, SpaceOutliner *soops, - const bool has_restrict_icons, + const float restrict_column_width, TreeElement **te_edit) { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; @@ -2607,8 +3148,8 @@ static void outliner_draw_tree(bContext *C, /* set scissor so tree elements or lines can't overlap restriction icons */ float scissor[4] = {0}; - if (has_restrict_icons) { - int mask_x = BLI_rcti_size_x(&ar->v2d.mask) - (int)OL_TOGW + 1; + if (restrict_column_width > 0.0f) { + int mask_x = BLI_rcti_size_x(&ar->v2d.mask) - (int)restrict_column_width + 1; CLAMP_MIN(mask_x, 0); GPU_scissor_get_f(scissor); @@ -2636,10 +3177,11 @@ static void outliner_draw_tree(bContext *C, (te->flag & TE_DRAGGING) != 0, startx, &starty, + restrict_column_width, te_edit); } - if (has_restrict_icons) { + if (restrict_column_width > 0.0f) { /* reset scissor */ GPU_scissor(UNPACK4(scissor)); } @@ -2694,7 +3236,6 @@ void draw_outliner(const bContext *C) uiBlock *block; int sizey = 0, sizex = 0, sizex_rna = 0; TreeElement *te_edit = NULL; - bool has_restrict_icons; outliner_build_tree(mainvar, scene, view_layer, soops, ar); // always @@ -2704,6 +3245,7 @@ void draw_outliner(const bContext *C) /* extend size to allow for horizontal scrollbar */ sizey += V2D_SCROLL_HEIGHT; + const float restrict_column_width = outliner_restrict_columns_width(soops); if (soops->outlinevis == SO_DATA_API) { /* RNA has two columns: * - column 1 is (max_width + OL_RNA_COL_SPACEX) or @@ -2719,7 +3261,6 @@ void draw_outliner(const bContext *C) /* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */ sizex = sizex_rna + OL_RNA_COL_SIZEX + 50; - has_restrict_icons = false; } else { /* width must take into account restriction columns (if visible) @@ -2728,13 +3269,8 @@ void draw_outliner(const bContext *C) // XXX should use outliner_width instead when te->xend will be set correctly... outliner_rna_width(soops, &soops->tree, &sizex, 0); - /* constant offset for restriction columns */ - // XXX this isn't that great yet... - if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0) { - sizex += OL_TOGW * 3; - } - - has_restrict_icons = !(soops->flag & SO_HIDE_RESTRICTCOLS); + /* Constant offset for restriction columns */ + sizex += restrict_column_width; } /* adds vertical offset */ @@ -2752,7 +3288,7 @@ void draw_outliner(const bContext *C) outliner_back(ar); block = UI_block_begin(C, ar, __func__, UI_EMBOSS); outliner_draw_tree( - (bContext *)C, block, scene, view_layer, ar, soops, has_restrict_icons, &te_edit); + (bContext *)C, block, scene, view_layer, ar, soops, restrict_column_width, &te_edit); /* Default to no emboss for outliner UI. */ UI_block_emboss_set(block, UI_EMBOSS_NONE); @@ -2765,20 +3301,20 @@ void draw_outliner(const bContext *C) outliner_draw_rnabuts(block, ar, soops, sizex_rna, &soops->tree); UI_block_emboss_set(block, UI_EMBOSS_NONE); } - else if ((soops->outlinevis == SO_ID_ORPHANS) && has_restrict_icons) { + else if (soops->outlinevis == SO_ID_ORPHANS) { /* draw user toggle columns */ outliner_draw_userbuts(block, ar, soops, &soops->tree); } - else if (has_restrict_icons) { + else if (restrict_column_width > 0.0f) { /* draw restriction columns */ outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &soops->tree); } UI_block_emboss_set(block, UI_EMBOSS); - /* draw edit buttons if nessecery */ + /* Draw edit buttons if necessary. */ if (te_edit) { - outliner_buttons(C, block, ar, te_edit); + outliner_buttons(C, block, ar, restrict_column_width, te_edit); } UI_block_end(C, block); diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index a943e972cf5..90180c4ea47 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -1025,8 +1025,8 @@ int common_restrict_check(bContext *C, Object *ob) Object *obedit = CTX_data_edit_object(C); if (obedit && obedit == ob) { /* found object is hidden, reset */ - if (ob->restrictflag & OB_RESTRICT_VIEW) { - ob->restrictflag &= ~OB_RESTRICT_VIEW; + if (ob->restrictflag & OB_RESTRICT_VIEWPORT) { + ob->restrictflag &= ~OB_RESTRICT_VIEWPORT; } /* found object is unselectable, reset */ if (ob->restrictflag & OB_RESTRICT_SELECT) { diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 8211e3005c7..15489c61230 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -156,11 +156,9 @@ typedef enum { /* size constants */ #define OL_Y_OFFSET 2 -#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 3.0f + V2D_SCROLL_WIDTH) -#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f + V2D_SCROLL_WIDTH) -#define OL_TOG_RESTRICT_RENDERX (UI_UNIT_X + V2D_SCROLL_WIDTH) - -#define OL_TOGW OL_TOG_RESTRICT_SELECTX +#define OL_TOG_USER_BUTS_USERS (UI_UNIT_X * 2.0f + V2D_SCROLL_WIDTH) +#define OL_TOG_USER_BUTS_STATUS (UI_UNIT_X * 3.0f + V2D_SCROLL_WIDTH) +#define OL_TOG_USER_BUTS_FAKEUSER (UI_UNIT_X + V2D_SCROLL_WIDTH) #define OL_RNA_COLX (UI_UNIT_X * 15) #define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f) @@ -449,5 +447,6 @@ bool outliner_tree_traverse(const SpaceOutliner *soops, int filter_tselem_flag, TreeTraversalFunc func, void *customdata); +float outliner_restrict_columns_width(const struct SpaceOutliner *soops); #endif /* __OUTLINER_INTERN_H__ */ diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 995f41382cd..c6fcf1d8cf7 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -1271,8 +1271,7 @@ static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops, const ARegion *ar, float view_co_x) { - return ((soops->outlinevis != SO_DATA_API) && !(soops->flag & SO_HIDE_RESTRICTCOLS) && - (view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX)); + return (view_co_x > ar->v2d.cur.xmax - outliner_restrict_columns_width(soops)); } /** diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 4e3fd6037bb..80424f021e2 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -302,6 +302,9 @@ static void outliner_add_scene_contents(SpaceOutliner *soops, tenlay->directdata = view_layer; } + /* World */ + outliner_add_element(soops, lb, sce->world, te, 0, 0); + /* Collections */ ten = outliner_add_element(soops, lb, &sce->id, te, TSE_SCENE_COLLECTION_BASE, 0); ten->name = IFACE_("Scene Collection"); @@ -1370,6 +1373,12 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops, const bool show_objects) { for (LayerCollection *lc = layer_collections->first; lc; lc = lc->next) { + const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0; + + if (exclude && ((soops->show_restrict_flags & SO_RESTRICT_ENABLE) == 0)) { + continue; + } + ID *id = &lc->collection->id; TreeElement *ten = outliner_add_element(soops, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0); @@ -1382,8 +1391,7 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops, tselem->flag &= ~TSE_CLOSED; } - const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0; - if (exclude || ((lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0)) { + if (exclude || (lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0) { ten->flag |= TE_DISABLED; } diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c index 03d15088380..f57dce97b38 100644 --- a/source/blender/editors/space_outliner/outliner_utils.c +++ b/source/blender/editors/space_outliner/outliner_utils.c @@ -31,6 +31,7 @@ #include "ED_armature.h" #include "UI_interface.h" +#include "UI_view2d.h" #include "outliner_intern.h" @@ -261,3 +262,41 @@ bool outliner_tree_traverse(const SpaceOutliner *soops, return true; } + +float outliner_restrict_columns_width(const SpaceOutliner *soops) +{ + int num_columns = 0; + + switch (soops->outlinevis) { + case SO_DATA_API: + case SO_SEQUENCE: + case SO_LIBRARIES: + return 0.0f; + case SO_ID_ORPHANS: + num_columns = 3; + break; + case SO_VIEW_LAYER: + if (soops->show_restrict_flags & SO_RESTRICT_HOLDOUT) { + num_columns++; + } + if (soops->show_restrict_flags & SO_RESTRICT_INDIRECT_ONLY) { + num_columns++; + } + ATTR_FALLTHROUGH; + case SO_SCENES: + if (soops->show_restrict_flags & SO_RESTRICT_SELECT) { + num_columns++; + } + if (soops->show_restrict_flags & SO_RESTRICT_HIDE) { + num_columns++; + } + if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) { + num_columns++; + } + if (soops->show_restrict_flags & SO_RESTRICT_RENDER) { + num_columns++; + } + break; + } + return (num_columns * UI_UNIT_X + V2D_SCROLL_WIDTH); +} diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index a8e3129b5b4..6634edfebee 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -302,6 +302,7 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED( soutliner = MEM_callocN(sizeof(SpaceOutliner), "initoutliner"); soutliner->spacetype = SPACE_OUTLINER; soutliner->filter_id_type = ID_GR; + soutliner->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_SELECT | SO_RESTRICT_HIDE; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for outliner"); diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt index d57be0c85c3..4668a9cef90 100644 --- a/source/blender/editors/space_sequencer/CMakeLists.txt +++ b/source/blender/editors/space_sequencer/CMakeLists.txt @@ -21,7 +21,6 @@ set(INC ../../blenlib ../../blentranslation ../../gpu - ../../depsgraph ../../imbuf ../../makesdna ../../makesrna diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 1cad9e4f734..b5bb79fb430 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -64,8 +64,6 @@ # include <AUD_Sequence.h> #endif -#include "DEG_depsgraph.h" - /* own include */ #include "sequencer_intern.h" @@ -357,7 +355,6 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op) sequencer_add_apply_replace_sel(C, op, seq); sequencer_add_apply_overlap(C, op, seq); - DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -444,7 +441,6 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op) sequencer_add_apply_replace_sel(C, op, seq); sequencer_add_apply_overlap(C, op, seq); - DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -531,7 +527,6 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op) sequencer_add_apply_replace_sel(C, op, seq); sequencer_add_apply_overlap(C, op, seq); - DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -646,7 +641,6 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad BKE_sequencer_sort(scene); BKE_sequencer_update_muting(ed); - DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -974,7 +968,6 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) MEM_freeN(op->customdata); } - DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -1130,7 +1123,6 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) * it was NOT called in blender 2.4x, but wont hurt */ BKE_sequencer_sort(scene); - DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 72f186d4c1a..805ec26950a 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -60,6 +60,7 @@ #include "ED_mask.h" #include "ED_sequencer.h" #include "ED_screen.h" +#include "ED_time_scrub_ui.h" #include "ED_space_api.h" #include "BIF_glutil.h" @@ -259,6 +260,11 @@ static void drawseqwave(View2D *v2d, return; } + if (!sound->spinlock) { + sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock"); + BLI_spin_init(sound->spinlock); + } + BLI_spin_lock(sound->spinlock); if (!sound->waveform) { if (!(sound->tags & SOUND_TAGS_WAVEFORM_LOADING)) { @@ -955,7 +961,7 @@ static void draw_seq_strip(const bContext *C, x1 = seq->startdisp + handsize_clamped; x2 = seq->enddisp - handsize_clamped; - float scroller_vert_xoffs = (V2D_SCROLL_WIDTH_TEXT + SEQ_SCROLLER_TEXT_OFFSET) * pixelx; + float scroller_vert_xoffs = (V2D_SCROLL_WIDTH_HANDLES + SEQ_SCROLLER_TEXT_OFFSET) * pixelx; /* info text on the strip */ if (x1 < v2d->cur.xmin + scroller_vert_xoffs) { @@ -1842,7 +1848,7 @@ static bool draw_cache_view_cb( color[2] = 0.2f; stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_DPI_FAC * U.pixelsize) - v2d->cur.ymin; - stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HEIGHT_TEXT); + stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HEIGHT_HANDLES); stripe_top = stripe_bot + stripe_ht; break; } @@ -1916,12 +1922,16 @@ static void draw_cache_view(const bContext *C) uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - float stripe_bot, stripe_top, stripe_offs; + float stripe_bot, stripe_top; + float stripe_offs = UI_view2d_region_to_view_y(v2d, 1.0f) - v2d->cur.ymin; float stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_DPI_FAC * U.pixelsize) - v2d->cur.ymin; + CLAMP_MAX(stripe_ht, 0.2f); + CLAMP_MIN(stripe_offs, stripe_ht / 2); + if (scene->ed->cache_flag & SEQ_CACHE_VIEW_FINAL_OUT) { - stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HEIGHT_TEXT); + stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HEIGHT_HANDLES); stripe_top = stripe_bot + stripe_ht; float bg_color[4] = {1.0f, 0.4f, 0.2f, 0.1f}; @@ -1938,10 +1948,6 @@ static void draw_cache_view(const bContext *C) continue; } - CLAMP_MAX(stripe_ht, 0.2f); - stripe_offs = UI_view2d_region_to_view_y(v2d, 1.0f) - v2d->cur.ymin; - CLAMP_MIN(stripe_offs, stripe_ht / 2); - stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + stripe_offs; stripe_top = stripe_bot + stripe_ht; @@ -2080,19 +2086,22 @@ void draw_timeline_seq(const bContext *C, ARegion *ar) /* reset view matrix */ UI_view2d_view_restore(C); + /* scrubbing region */ + ED_scrubbing_draw(ar, scene, !(sseq->flag & SEQ_DRAWFRAMES), true); + /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); UI_view2d_scrollers_draw(v2d, scrollers); UI_view2d_scrollers_free(scrollers); - /* scale numbers */ - UI_view2d_draw_scale_x__discrete_frames_or_seconds( - ar, v2d, &v2d->hor, scene, !(sseq->flag & SEQ_DRAWFRAMES), TH_TEXT); - UI_view2d_draw_scale_y__block(ar, v2d, &v2d->vert, TH_TEXT); - - /* draw current frame number-indicator on top of scrollers */ - if ((sseq->flag & SEQ_NO_DRAW_CFRANUM) == 0) { - UI_view2d_view_orthoSpecial(ar, v2d, 1); - ANIM_draw_cfra_number(C, v2d, cfra_flag); + /* channel numbers */ + { + rcti rect; + BLI_rcti_init(&rect, + 0, + 15 * UI_DPI_FAC, + 15 * UI_DPI_FAC, + UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y); + UI_view2d_draw_scale_y__block(ar, v2d, &rect, TH_SCROLL_TEXT); } } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 0f5c02327cc..94437d4871a 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -64,8 +64,6 @@ #include "UI_view2d.h" #include "UI_interface.h" -#include "DEG_depsgraph.h" - /* own include */ #include "sequencer_intern.h" @@ -2381,7 +2379,6 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op)) ms = ms->prev; } - DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_sequencer/sequencer_preview.c b/source/blender/editors/space_sequencer/sequencer_preview.c index 8a4e8c007f7..546c2a8a9f0 100644 --- a/source/blender/editors/space_sequencer/sequencer_preview.c +++ b/source/blender/editors/space_sequencer/sequencer_preview.c @@ -50,7 +50,6 @@ typedef struct PreviewJob { typedef struct PreviewJobAudio { struct PreviewJobAudio *next, *prev; - struct Main *bmain; bSound *sound; int lr; /* sample left or right */ int startframe; @@ -80,9 +79,7 @@ static void preview_startjob(void *data, short *stop, short *do_update, float *p PreviewJobAudio *preview_next; bSound *sound = previewjb->sound; - BKE_sound_load_audio(previewjb->bmain, sound); BKE_sound_read_waveform(sound, stop); - BKE_sound_free_audio(sound); if (*stop || G.is_break) { BLI_mutex_lock(pj->mutex); @@ -156,7 +153,6 @@ void sequencer_preview_add_sound(const bContext *C, Sequence *seq) /* attempt to lock mutex of job here */ - audiojob->bmain = CTX_data_main(C); audiojob->sound = seq->sound; BLI_mutex_lock(pj->mutex); diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 2b0c29a02ad..7a02b1850ae 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -157,8 +157,8 @@ static SpaceLink *sequencer_new(const ScrArea *UNUSED(sa), const Scene *scene) ar->v2d.minzoom = 0.01f; ar->v2d.maxzoom = 100.0f; - ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL); - ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL); + ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES); + ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES); ar->v2d.keepzoom = 0; ar->v2d.keeptot = 0; ar->v2d.align = V2D_ALIGN_NO_NEG_Y; @@ -816,7 +816,7 @@ void ED_spacetype_sequencer(void) art->draw = sequencer_main_region_draw; art->listener = sequencer_main_region_listener; art->message_subscribe = sequencer_main_region_message_subscribe; - art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION; + art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION; BLI_addhead(&st->regiontypes, art); @@ -832,7 +832,7 @@ void ED_spacetype_sequencer(void) /* regions: listview/buttons */ art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region"); art->regionid = RGN_TYPE_UI; - art->prefsizex = 220; // XXX + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; art->listener = sequencer_buttons_region_listener; art->init = sequencer_buttons_region_init; diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 678879018a7..ac1fb4af1c2 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -1665,12 +1665,14 @@ void draw_text_main(SpaceText *st, ARegion *ar) immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + GPU_line_width(2.0f); + float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); - immUniform1i("colors_len", 0); /* "simple" mode */ - immUniformThemeColor(TH_GRID); /* same color as line number background */ + immUniform1i("colors_len", 0); /* "simple" mode */ + immUniformThemeColor3(TH_GRID); /* same color as line number background */ immUniform1f("dash_width", 2.0f); immUniform1f("dash_factor", 0.5f); diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index d0809ec33fc..a3a438c3220 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -101,7 +101,7 @@ static char *buf_tabs_to_spaces(const char *in_buf, const int tab_size) } /* Allocate output before with extra space for expanded tabs. */ - const int out_size = strlen(in_buf) + num_tabs * (tab_size - 1); + const int out_size = strlen(in_buf) + num_tabs * (tab_size - 1) + 1; char *out_buf = MEM_mallocN(out_size * sizeof(char), __func__); /* Fill output buffer. */ diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c index 8b290009a97..725a49e417e 100644 --- a/source/blender/editors/space_topbar/space_topbar.c +++ b/source/blender/editors/space_topbar/space_topbar.c @@ -213,12 +213,15 @@ static void recent_files_menu_draw(const bContext *UNUSED(C), Menu *menu) { struct RecentFile *recent; uiLayout *layout = menu->layout; - uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN); + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); if (!BLI_listbase_is_empty(&G.recent_files)) { for (recent = G.recent_files.first; (recent); recent = recent->next) { const char *file = BLI_path_basename(recent->filepath); const int icon = BLO_has_bfile_extension(file) ? ICON_FILE_BLEND : ICON_FILE_BACKUP; - uiItemStringO(layout, file, icon, "WM_OT_open_mainfile", "filepath", recent->filepath); + PointerRNA ptr; + uiItemFullO(layout, "WM_OT_open_mainfile", file, icon, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr); + RNA_string_set(&ptr, "filepath", recent->filepath); + RNA_boolean_set(&ptr, "display_file_selector", false); } } else { diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index 2237e8b02bc..4c6f2231cc1 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -249,7 +249,7 @@ void ED_spacetype_userpref(void) art->init = userpref_navigation_region_init; art->draw = userpref_navigation_region_draw; art->listener = userpref_navigation_region_listener; - art->keymapflag = ED_KEYMAP_UI; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_NAVBAR; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 638c77fc3cb..cc76c151a29 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -41,7 +41,6 @@ #include "GPU_batch.h" #include "GPU_matrix.h" #include "GPU_state.h" -#include "GPU_framebuffer.h" #include "ED_mesh.h" @@ -51,8 +50,6 @@ #include "view3d_intern.h" /* bad level include */ -#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */ - int view3d_effective_drawtype(const struct View3D *v3d) { if (v3d->shading.type == OB_RENDER) { @@ -61,24 +58,6 @@ int view3d_effective_drawtype(const struct View3D *v3d) return v3d->shading.type; } -static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt) -{ - if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0) { - return false; - } - - if (G.f & G_FLAG_BACKBUFSEL) { - return false; - } - - /* if its drawing textures with zbuf sel, then don't draw dots */ - if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) { - return false; - } - - return true; -} - /* OpenGL Circle Drawing - Tables for Optimized Drawing Speed */ /* 32 values of sin function (still same result!) */ #define CIRCLE_RESOL 32 @@ -138,216 +117,6 @@ bool view3d_camera_border_hack_test = false; /* ***************** BACKBUF SEL (BBS) ********* */ -/** See #DRW_shgroup_world_clip_planes_from_rv3d, same function for draw manager. */ -static void bbs_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4]) -{ - GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]); -} - -static void bbs_mesh_verts(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) -{ - GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE)); - - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); -} - -static void bbs_mesh_wire(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) -{ - GPU_line_width(1.0f); - glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - - glProvokingVertex(GL_LAST_VERTEX_CONVENTION); -} - -/* two options, facecolors or black */ -static void bbs_mesh_face(GPUBatch *batch, - const bool use_select, - const float world_clip_planes[6][4]) -{ - if (use_select) { - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", 1); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - } - else { - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "id", 0); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - } -} - -static void bbs_mesh_face_dot(GPUBatch *batch, const float world_clip_planes[6][4]) -{ - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", 1); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); -} - -static void bbs_mesh_solid_verts(Depsgraph *UNUSED(depsgraph), - Scene *UNUSED(scene), - Object *ob, - const float world_clip_planes[6][4]) -{ - Mesh *me = ob->data; - - GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); - - /* Only draw faces to mask out verts, we don't want their selection ID's. */ - bbs_mesh_face(geom_faces, false, world_clip_planes); - bbs_mesh_verts(geom_verts, 1, world_clip_planes); - - bm_vertoffs = me->totvert + 1; -} - -static void bbs_mesh_solid_faces(Scene *UNUSED(scene), - Object *ob, - const float world_clip_planes[6][4]) -{ - Mesh *me = ob->data; - Mesh *me_orig = DEG_get_original_object(ob)->data; - - const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL); - GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, use_hide); - - bbs_mesh_face(geom_faces, true, world_clip_planes); -} - -void draw_object_select_id(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; - } - - GPU_matrix_mul(ob->obmat); - GPU_depth_test(true); - - const float(*world_clip_planes)[4] = NULL; - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_local(rv3d, ob->obmat); - world_clip_planes = rv3d->clip_local; - } - - switch (ob->type) { - case OB_MESH: - if (ob->mode & OB_MODE_EDIT) { - Mesh *me = ob->data; - BMEditMesh *em = me->edit_mesh; - const bool draw_facedot = check_ob_drawface_dot(scene, v3d, ob->dt); - const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0; - - BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); - - GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots; - geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - if (select_mode & SCE_SELECT_EDGE) { - geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); - } - if (select_mode & SCE_SELECT_VERTEX) { - geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); - } - if (draw_facedot) { - geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); - } - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); - - bbs_mesh_face(geom_faces, use_faceselect, world_clip_planes); - - if (use_faceselect && draw_facedot) { - bbs_mesh_face_dot(geom_facedots, world_clip_planes); - } - - if (select_mode & SCE_SELECT_FACE) { - bm_solidoffs = 1 + em->bm->totface; - } - else { - bm_solidoffs = 1; - } - - ED_view3d_polygon_offset(rv3d, 1.0); - - /* we draw edges if edge select mode */ - if (select_mode & SCE_SELECT_EDGE) { - bbs_mesh_wire(geom_edges, bm_solidoffs, world_clip_planes); - bm_wireoffs = bm_solidoffs + em->bm->totedge; - } - else { - /* `bm_vertoffs` is calculated from `bm_wireoffs`. (otherwise see T53512) */ - bm_wireoffs = bm_solidoffs; - } - - ED_view3d_polygon_offset(rv3d, 1.1); - - /* we draw verts if vert select mode. */ - if (select_mode & SCE_SELECT_VERTEX) { - bbs_mesh_verts(geom_verts, bm_wireoffs, world_clip_planes); - bm_vertoffs = bm_wireoffs + em->bm->totvert; - } - else { - bm_vertoffs = bm_wireoffs; - } - - ED_view3d_polygon_offset(rv3d, 0.0); - } - else { - Mesh *me = DEG_get_original_object(ob)->data; - if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) && - /* currently vertex select supports weight paint and vertex paint*/ - ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) { - bbs_mesh_solid_verts(depsgraph, scene, ob, world_clip_planes); - } - else { - bbs_mesh_solid_faces(scene, ob, world_clip_planes); - } - } - break; - case OB_CURVE: - case OB_SURF: - break; - } - - GPU_matrix_set(rv3d->viewmat); -} - void ED_draw_object_facemap(Depsgraph *depsgraph, Object *ob, const float col[4], diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index dbf2160d39b..770172d702b 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1132,6 +1132,9 @@ static void view3d_header_region_listener(wmWindow *UNUSED(win), ED_region_tag_redraw(ar); } break; + case NC_BRUSH: + ED_region_tag_redraw(ar); + break; } /* From topbar, which ones are needed? split per header? */ @@ -1201,9 +1204,106 @@ static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar) WM_event_add_keymap_handler(&ar->handlers, keymap); } -static void view3d_buttons_region_draw(const bContext *C, ARegion *ar) +void ED_view3d_buttons_region_layout_ex(const bContext *C, + ARegion *ar, + const char *category_override) { - ED_region_panels_ex(C, ar, (const char *[]){CTX_data_mode_string(C), NULL}, -1, true); + const enum eContextObjectMode mode = CTX_data_mode_enum(C); + + const char *contexts_base[4] = {NULL}; + contexts_base[0] = CTX_data_mode_string(C); + + const char **contexts = &contexts_base[1]; + + switch (mode) { + case CTX_MODE_EDIT_MESH: + ARRAY_SET_ITEMS(contexts, ".mesh_edit"); + break; + case CTX_MODE_EDIT_CURVE: + ARRAY_SET_ITEMS(contexts, ".curve_edit"); + break; + case CTX_MODE_EDIT_SURFACE: + ARRAY_SET_ITEMS(contexts, ".curve_edit"); + break; + case CTX_MODE_EDIT_TEXT: + ARRAY_SET_ITEMS(contexts, ".text_edit"); + break; + case CTX_MODE_EDIT_ARMATURE: + ARRAY_SET_ITEMS(contexts, ".armature_edit"); + break; + case CTX_MODE_EDIT_METABALL: + ARRAY_SET_ITEMS(contexts, ".mball_edit"); + break; + case CTX_MODE_EDIT_LATTICE: + ARRAY_SET_ITEMS(contexts, ".lattice_edit"); + break; + case CTX_MODE_POSE: + ARRAY_SET_ITEMS(contexts, ".posemode"); + break; + case CTX_MODE_SCULPT: + ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode"); + break; + case CTX_MODE_PAINT_WEIGHT: + ARRAY_SET_ITEMS(contexts, ".paint_common", ".weightpaint"); + break; + case CTX_MODE_PAINT_VERTEX: + ARRAY_SET_ITEMS(contexts, ".paint_common", ".vertexpaint"); + break; + case CTX_MODE_PAINT_TEXTURE: + ARRAY_SET_ITEMS(contexts, ".paint_common", ".imagepaint"); + break; + case CTX_MODE_PARTICLE: + ARRAY_SET_ITEMS(contexts, ".paint_common", ".particlemode"); + break; + case CTX_MODE_OBJECT: + ARRAY_SET_ITEMS(contexts, ".objectmode"); + break; + case CTX_MODE_PAINT_GPENCIL: + ARRAY_SET_ITEMS(contexts, ".greasepencil_paint"); + break; + case CTX_MODE_SCULPT_GPENCIL: + ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt"); + break; + case CTX_MODE_WEIGHT_GPENCIL: + ARRAY_SET_ITEMS(contexts, ".greasepencil_weight"); + break; + default: + break; + } + + switch (mode) { + case CTX_MODE_PAINT_GPENCIL: + ARRAY_SET_ITEMS(contexts, ".greasepencil_paint"); + break; + case CTX_MODE_SCULPT_GPENCIL: + ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt"); + break; + case CTX_MODE_WEIGHT_GPENCIL: + ARRAY_SET_ITEMS(contexts, ".greasepencil_weight"); + break; + case CTX_MODE_EDIT_GPENCIL: + ARRAY_SET_ITEMS(contexts, ".greasepencil_edit"); + break; + default: + break; + } + + ListBase *paneltypes = &ar->type->paneltypes; + + /* Allow drawing 3D view toolbar from non 3D view space type. */ + if (category_override != NULL) { + SpaceType *st = BKE_spacetype_from_id(SPACE_VIEW3D); + ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_UI); + paneltypes = &art->paneltypes; + } + + const bool vertical = true; + ED_region_panels_layout_ex(C, ar, paneltypes, contexts_base, -1, vertical, category_override); +} + +static void view3d_buttons_region_layout(const bContext *C, ARegion *ar) +{ + ED_view3d_buttons_region_layout_ex(C, ar, NULL); } static void view3d_buttons_region_listener(wmWindow *UNUSED(win), @@ -1508,12 +1608,13 @@ void ED_spacetype_view3d(void) /* regions: listview/buttons */ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region"); art->regionid = RGN_TYPE_UI; - art->prefsizex = 180; /* XXX */ + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; art->listener = view3d_buttons_region_listener; art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui; art->init = view3d_buttons_region_init; - art->draw = view3d_buttons_region_draw; + art->layout = view3d_buttons_region_layout; + art->draw = ED_region_panels_draw; BLI_addhead(&st->regiontypes, art); view3d_buttons_register(art); diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index b0cee18f8e3..e0dbe1f6543 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -77,6 +77,7 @@ #include "ED_armature.h" #include "ED_keyframing.h" #include "ED_gpencil.h" +#include "ED_mesh.h" #include "ED_screen.h" #include "ED_space_api.h" #include "ED_screen_types.h" @@ -208,7 +209,16 @@ static void validate_object_select_id(struct Depsgraph *depsgraph, if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { DRW_framebuffer_select_id_setup(ar, true); - draw_object_select_id(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode); + DRW_draw_select_id_object(scene_eval, + rv3d, + obact_eval, + select_mode, + false, + 0, + &bm_vertoffs, + &bm_wireoffs, + &bm_solidoffs); + DRW_framebuffer_select_id_release(ar); } @@ -271,10 +281,8 @@ void ED_view3d_backbuf_depth_validate(ViewContext *vc) } } -uint *ED_view3d_select_id_read_rect(ViewContext *vc, const rcti *clip, uint *r_buf_len) +uint *ED_view3d_select_id_read_rect(ViewContext *UNUSED(vc), const rcti *clip, uint *r_buf_len) { - ED_view3d_select_id_validate(vc); - uint width = BLI_rcti_size_x(clip); uint height = BLI_rcti_size_y(clip); uint buf_len = width * height; diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c index 6f35c0aa748..9cbf179ab49 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c @@ -304,15 +304,14 @@ static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const em_setup_viewcontext(C, &vc); copy_v2_v2_int(vc.mval, mval); - for (uint base_index = 0; base_index < gz_ring->bases_len; base_index++) { - Object *ob_iter = gz_ring->bases[base_index]->object; - ED_view3d_viewcontext_init_object(&vc, ob_iter); - BMEdge *eed_test = EDBM_edge_find_nearest_ex(&vc, &best.dist, NULL, false, false, NULL); - if (eed_test) { - best.ob = ob_iter; - best.eed = eed_test; - best.base_index = base_index; - } + uint base_index; + BMEdge *eed_test = EDBM_edge_find_nearest_ex( + &vc, &best.dist, NULL, false, false, NULL, gz_ring->bases, gz_ring->bases_len, &base_index); + + if (eed_test) { + best.ob = gz_ring->bases[base_index]->object; + best.eed = eed_test; + best.base_index = base_index; } BMesh *bm = NULL; diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 9075909a6fe..e499672acc1 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -127,13 +127,6 @@ void VIEW3D_OT_fly(struct wmOperatorType *ot); void VIEW3D_OT_walk(struct wmOperatorType *ot); /* drawobject.c */ -void draw_object_select_id(struct Depsgraph *depsgraph, - Scene *scene, - View3D *v3d, - RegionView3D *rv3d, - struct Object *ob, - short select_mode); - int view3d_effective_drawtype(const struct View3D *v3d); /* view3d_draw.c */ diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 2ce23486476..419ec87eec8 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -57,6 +57,7 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "BKE_global.h" +#include "BKE_main.h" #include "BKE_armature.h" #include "BKE_context.h" @@ -134,9 +135,6 @@ void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact) if (vc->obedit) { BLI_assert(BKE_object_is_in_editmode(obact)); vc->obedit = obact; - /* previous selections are now invalid. */ - vc->v3d->flag |= V3D_INVALID_BACKBUF; - if (vc->em) { vc->em = BKE_editmesh_from_object(vc->obedit); } @@ -1170,6 +1168,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op) if (mcords) { view3d_operator_needs_opengl(C); + BKE_object_update_select_id(CTX_data_main(C)); /* setup view context for argument to callbacks */ ED_view3d_viewcontext_init(C, &vc); @@ -1337,7 +1336,7 @@ static Base *object_mouse_select_menu( if (buffer) { for (int a = 0; a < hits; a++) { /* index was converted */ - if (base->object->select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) { + if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) { ok = true; break; } @@ -1609,7 +1608,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, else { /* only exclude active object when it is selected... */ if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) { - notcol = BASACT(view_layer)->object->select_id; + notcol = BASACT(view_layer)->object->runtime.select_id; } for (a = 0; a < hits; a++) { @@ -1623,7 +1622,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, base = FIRSTBASE(view_layer); while (base) { if (BASE_SELECTABLE(v3d, base)) { - if (base->object->select_id == selcol) { + if (base->object->runtime.select_id == selcol) { break; } } @@ -1654,13 +1653,13 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, if (has_bones) { /* skip non-bone objects */ if ((buffer[4 * a + 3] & 0xFFFF0000)) { - if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) { + if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) { basact = base; } } } else { - if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) { + if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) { basact = base; } } @@ -1693,6 +1692,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) /* setup view context for argument to callbacks */ view3d_operator_needs_opengl(C); + BKE_object_update_select_id(CTX_data_main(C)); ED_view3d_viewcontext_init(C, &vc); @@ -1878,7 +1878,7 @@ static bool ed_object_select_pick(bContext *C, /* if there's bundles in buffer select bundles first, * so non-camera elements should be ignored in buffer */ - if (basact->object->select_id != (hitresult & 0xFFFF)) { + if (basact->object->runtime.select_id != (hitresult & 0xFFFF)) { continue; } @@ -2129,6 +2129,7 @@ static int view3d_select_exec(bContext *C, wmOperator *op) RNA_int_get_array(op->ptr, "location", location); view3d_operator_needs_opengl(C); + BKE_object_update_select_id(CTX_data_main(C)); if (object) { obedit = NULL; @@ -2355,14 +2356,14 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSe } else if (use_zbuf) { MVert *mvert; - unsigned int *rt; + uint *rt, *buf, buf_len; int a, index; char *selar; selar = MEM_callocN(me->totvert + 1, "selar"); - uint buf_len; - uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); + ED_view3d_select_id_validate(vc); + buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); rt = buf; @@ -2652,7 +2653,7 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO } const uint hit_object = hitresult & 0xFFFF; - if (vc->obedit->select_id != hit_object) { + if (vc->obedit->runtime.select_id != hit_object) { continue; } @@ -2803,7 +2804,7 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) { if (BASE_SELECTABLE(v3d, base)) { - if ((base->object->select_id & 0x0000FFFF) != 0) { + if ((base->object->runtime.select_id & 0x0000FFFF) != 0) { BLI_array_append(bases, base); } } @@ -2893,7 +2894,7 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e /* Select the next bone if we're not switching bases. */ if (col + 4 != col_end) { - if ((base->object->select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) { + if ((base->object->runtime.select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) { break; } if (base->object->pose != NULL) { @@ -2930,6 +2931,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) bool changed_multi = false; view3d_operator_needs_opengl(C); + BKE_object_update_select_id(CTX_data_main(C)); /* setup view context for argument to callbacks */ ED_view3d_viewcontext_init(C, &vc); @@ -3670,6 +3672,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) if (obedit || BKE_paint_select_elem_test(obact) || (obact && (obact->mode & OB_MODE_POSE))) { view3d_operator_needs_opengl(C); + BKE_object_update_select_id(CTX_data_main(C)); FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, obact->type, obact->mode, ob_iter) { ED_view3d_viewcontext_init_object(&vc, ob_iter); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 81405b55ac2..09f198ff14c 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4917,8 +4917,7 @@ static void initSnapSpatial(TransInfo *t, float r_snap[3]) } else if (t->spacetype == SPACE_NODE) { r_snap[0] = 0.0f; - r_snap[1] = ED_node_grid_size(); - r_snap[2] = ED_node_grid_size(); + r_snap[1] = r_snap[2] = ED_node_grid_size(); } else if (t->spacetype == SPACE_GRAPH) { r_snap[0] = 0.0f; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 50fc1a276b9..b0f720bfdf7 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -383,6 +383,30 @@ typedef struct BoneInitData { float zwidth; } BoneInitData; +typedef struct PoseInitData_Mirror { + /** Points to the bone which this info is initialized & restored to. + * A NULL value is used to terminate the array. */ + struct bPoseChannel *pchan; + struct { + float loc[3]; + float size[3]; + union { + float eul[3]; + float quat[4]; + float axis_angle[4]; + }; + float curve_in_x; + float curve_out_x; + float roll1; + float roll2; + } orig; + /** + * An extra offset to apply after mirroring. + * Use with #POSE_MIRROR_RELATIVE. + */ + float offset_mtx[4][4]; +} PoseInitData_Mirror; + typedef struct TransData { /** Distance needed to affect element (for Proportionnal Editing). */ float dist; @@ -501,7 +525,7 @@ typedef struct TransDataContainer { struct Object *obedit; /** - * Use when #T_LOCAL_MATRIX is set. + * Store matrix, this avoids having to have duplicate check all over * Typically: 'obedit->obmat' or 'poseobj->obmat', but may be used elsewhere too. */ bool use_local_mat; @@ -715,10 +739,8 @@ enum { T_CURSOR = 1 << 5, /** Transform points, having no rotation/scale. */ T_POINTS = 1 << 6, - /** - * Apply matrix #TransDataContainer.matrix, this avoids having to have duplicate check all over - * that happen to apply to specific modes (edit & pose for eg). */ - T_LOCAL_MATRIX = 1 << 7, + + /* empty slot - (1 << 7) */ /** restrictions flags */ T_NO_CONSTRAINT = 1 << 8, @@ -892,6 +914,7 @@ void flushTransSeq(TransInfo *t); void flushTransTracking(TransInfo *t); void flushTransMasking(TransInfo *t); void flushTransPaintCurve(TransInfo *t); +void restoreMirrorPoseBones(TransDataContainer *tc); void restoreBones(TransDataContainer *tc); /*********************** transform_gizmo.c ********** */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 6c1da5ae825..4037fab2b68 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -198,7 +198,10 @@ void sort_trans_data_dist(TransInfo *t) } } -static void sort_trans_data_container(TransDataContainer *tc) +/** + * Make #TD_SELECTED first in the array. + */ +static void sort_trans_data_selected_first_container(TransDataContainer *tc) { TransData *sel, *unsel; TransData temp; @@ -225,10 +228,10 @@ static void sort_trans_data_container(TransDataContainer *tc) unsel++; } } -static void sort_trans_data(TransInfo *t) +static void sort_trans_data_selected_first(TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { - sort_trans_data_container(tc); + sort_trans_data_selected_first_container(tc); } } @@ -1201,6 +1204,74 @@ static short pose_grab_with_ik(Main *bmain, Object *ob) return (tot_ik) ? 1 : 0; } +static void pose_mirror_info_init(PoseInitData_Mirror *pid, + bPoseChannel *pchan, + bPoseChannel *pchan_orig, + bool is_mirror_relative) +{ + pid->pchan = pchan; + copy_v3_v3(pid->orig.loc, pchan->loc); + copy_v3_v3(pid->orig.size, pchan->size); + pid->orig.curve_in_x = pchan->curve_in_x; + pid->orig.curve_out_x = pchan->curve_out_x; + pid->orig.roll1 = pchan->roll1; + pid->orig.roll2 = pchan->roll2; + + if (pchan->rotmode > 0) { + copy_v3_v3(pid->orig.eul, pchan->eul); + } + else if (pchan->rotmode == ROT_MODE_AXISANGLE) { + copy_v3_v3(pid->orig.axis_angle, pchan->rotAxis); + pid->orig.axis_angle[3] = pchan->rotAngle; + } + else { + copy_qt_qt(pid->orig.quat, pchan->quat); + } + + if (is_mirror_relative) { + float pchan_mtx[4][4]; + float pchan_mtx_mirror[4][4]; + + float flip_mtx[4][4]; + unit_m4(flip_mtx); + flip_mtx[0][0] = -1; + + BKE_pchan_to_mat4(pchan_orig, pchan_mtx_mirror); + BKE_pchan_to_mat4(pchan, pchan_mtx); + + mul_m4_m4m4(pchan_mtx_mirror, pchan_mtx_mirror, flip_mtx); + mul_m4_m4m4(pchan_mtx_mirror, flip_mtx, pchan_mtx_mirror); + + invert_m4(pchan_mtx_mirror); + mul_m4_m4m4(pid->offset_mtx, pchan_mtx, pchan_mtx_mirror); + } + else { + unit_m4(pid->offset_mtx); + } +} + +static void pose_mirror_info_restore(const PoseInitData_Mirror *pid) +{ + bPoseChannel *pchan = pid->pchan; + copy_v3_v3(pchan->loc, pid->orig.loc); + copy_v3_v3(pchan->size, pid->orig.size); + pchan->curve_in_x = pid->orig.curve_in_x; + pchan->curve_out_x = pid->orig.curve_out_x; + pchan->roll1 = pid->orig.roll1; + pchan->roll2 = pid->orig.roll2; + + if (pchan->rotmode > 0) { + copy_v3_v3(pchan->eul, pid->orig.eul); + } + else if (pchan->rotmode == ROT_MODE_AXISANGLE) { + copy_v3_v3(pchan->rotAxis, pid->orig.axis_angle); + pchan->rotAngle = pid->orig.axis_angle[3]; + } + else { + copy_qt_qt(pchan->quat, pid->orig.quat); + } +} + /** * When objects array is NULL, use 't->data_container' as is. */ @@ -1215,16 +1286,19 @@ static void createTransPose(TransInfo *t) FOREACH_TRANS_DATA_CONTAINER (t, tc) { Object *ob = tc->poseobj; + bPose *pose = ob->pose; bArmature *arm; short ik_on = 0; /* check validity of state */ arm = BKE_armature_from_object(tc->poseobj); - if ((arm == NULL) || (ob->pose == NULL)) { + if ((arm == NULL) || (pose == NULL)) { continue; } + const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0); + /* set flags and count total */ tc->data_len = count_set_pose_transflags(ob, t->mode, t->around, has_translate_rotate); if (tc->data_len == 0) { @@ -1240,13 +1314,32 @@ static void createTransPose(TransInfo *t) } /* do we need to add temporal IK chains? */ - if ((arm->flag & ARM_AUTO_IK) && t->mode == TFM_TRANSLATION) { + if ((pose->flag & POSE_AUTO_IK) && t->mode == TFM_TRANSLATION) { ik_on = pose_grab_with_ik(bmain, ob); if (ik_on) { t->flag |= T_AUTOIK; has_translate_rotate[0] = true; } } + + if (mirror) { + int total_mirrored = 0; + for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + if ((pchan->bone->flag & BONE_TRANSFORM) && + BKE_pose_channel_get_mirrored(ob->pose, pchan->name)) { + total_mirrored++; + } + } + + PoseInitData_Mirror *pid = MEM_mallocN((total_mirrored + 1) * sizeof(PoseInitData_Mirror), + "PoseInitData_Mirror"); + + /* Trick to terminate iteration. */ + pid[total_mirrored].pchan = NULL; + + tc->custom.type.data = pid; + tc->custom.type.use_free = true; + } } /* if there are no translatable bones, do rotation */ @@ -1269,6 +1362,17 @@ static void createTransPose(TransInfo *t) short ik_on = 0; int i; + PoseInitData_Mirror *pid = tc->custom.type.data; + int pid_index = 0; + bPose *pose = ob->pose; + + if (pose == NULL) { + continue; + } + + const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0); + const bool is_mirror_relative = ((pose->flag & POSE_MIRROR_RELATIVE) != 0); + tc->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */ /* init trans data */ @@ -1285,6 +1389,15 @@ static void createTransPose(TransInfo *t) for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone->flag & BONE_TRANSFORM) { add_pose_transdata(t, pchan, ob, tc, td); + + if (mirror) { + bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name); + if (pchan_mirror) { + pose_mirror_info_init(&pid[pid_index], pchan_mirror, pchan, is_mirror_relative); + pid_index++; + } + } + td++; } } @@ -1304,6 +1417,19 @@ static void createTransPose(TransInfo *t) t->flag &= ~T_PROP_EDIT_ALL; } +void restoreMirrorPoseBones(TransDataContainer *tc) +{ + bPose *pose = tc->poseobj->pose; + + if (!(pose->flag & POSE_MIRROR_EDIT)) { + return; + } + + for (PoseInitData_Mirror *pid = tc->custom.type.data; pid->pchan; pid++) { + pose_mirror_info_restore(pid); + } +} + void restoreBones(TransDataContainer *tc) { bArmature *arm; @@ -9253,7 +9379,7 @@ void createTransData(bContext *C, TransInfo *t) countAndCleanTransDataContainer(t); if (t->data_len_all && t->flag & T_PROP_EDIT) { - sort_trans_data(t); // makes selected become first in array + sort_trans_data_selected_first(t); set_prop_dist(t, 1); sort_trans_data_dist(t); } @@ -9267,7 +9393,7 @@ void createTransData(bContext *C, TransInfo *t) countAndCleanTransDataContainer(t); if (t->data_len_all && (t->flag & T_PROP_EDIT)) { - sort_trans_data(t); // makes selected become first in array + sort_trans_data_selected_first(t); set_prop_dist(t, 1); sort_trans_data_dist(t); } @@ -9281,7 +9407,7 @@ void createTransData(bContext *C, TransInfo *t) countAndCleanTransDataContainer(t); if (t->data_len_all && (t->flag & T_PROP_EDIT)) { - sort_trans_data(t); // makes selected become first in array + sort_trans_data_selected_first(t); set_prop_dist(t, true); sort_trans_data_dist(t); } @@ -9304,7 +9430,7 @@ void createTransData(bContext *C, TransInfo *t) t->flag |= T_EDIT; if (t->data_len_all && (t->flag & T_PROP_EDIT)) { - sort_trans_data(t); // makes selected become first in array + sort_trans_data_selected_first(t); set_prop_dist(t, 1); sort_trans_data_dist(t); } @@ -9321,7 +9447,7 @@ void createTransData(bContext *C, TransInfo *t) countAndCleanTransDataContainer(t); if (t->data_len_all && (t->flag & T_PROP_EDIT)) { - sort_trans_data(t); // makes selected become first in array + sort_trans_data_selected_first(t); /* don't do that, distance has been set in createTransActionData already */ // set_prop_dist(t, false); sort_trans_data_dist(t); @@ -9351,7 +9477,7 @@ void createTransData(bContext *C, TransInfo *t) if (t->data_len_all && (t->flag & T_PROP_EDIT)) { /* makes selected become first in array */ - sort_trans_data(t); + sort_trans_data_selected_first(t); /* don't do that, distance has been set in createTransGraphEditData already */ set_prop_dist(t, false); @@ -9367,7 +9493,7 @@ void createTransData(bContext *C, TransInfo *t) countAndCleanTransDataContainer(t); if (t->data_len_all && (t->flag & T_PROP_EDIT)) { - sort_trans_data(t); // makes selected become first in array + sort_trans_data_selected_first(t); set_prop_dist(t, 1); sort_trans_data_dist(t); } @@ -9386,7 +9512,7 @@ void createTransData(bContext *C, TransInfo *t) countAndCleanTransDataContainer(t); if (t->data_len_all && (t->flag & T_PROP_EDIT)) { - sort_trans_data(t); // makes selected become first in array + sort_trans_data_selected_first(t); set_prop_dist(t, true); sort_trans_data_dist(t); } @@ -9426,21 +9552,30 @@ void createTransData(bContext *C, TransInfo *t) t->flag |= T_EDIT | T_POINTS; - if (t->data_len_all && t->flag & T_PROP_EDIT) { - if (ELEM(t->obedit_type, OB_CURVE, OB_MESH)) { - sort_trans_data(t); // makes selected become first in array - if ((t->obedit_type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) { - /* already calculated by editmesh_set_connectivity_distance */ + if (t->data_len_all) { + if (t->flag & T_PROP_EDIT) { + if (ELEM(t->obedit_type, OB_CURVE, OB_MESH)) { + sort_trans_data_selected_first(t); + if ((t->obedit_type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) { + /* already calculated by editmesh_set_connectivity_distance */ + } + else { + set_prop_dist(t, 0); + } + sort_trans_data_dist(t); } else { - set_prop_dist(t, 0); + sort_trans_data_selected_first(t); + set_prop_dist(t, 1); + sort_trans_data_dist(t); } - sort_trans_data_dist(t); } else { - sort_trans_data(t); // makes selected become first in array - set_prop_dist(t, 1); - sort_trans_data_dist(t); + if (ELEM(t->obedit_type, OB_CURVE)) { + /* Needed because bezier handles can be partially selected + * and are still added into transform data. */ + sort_trans_data_selected_first(t); + } } } @@ -9494,7 +9629,7 @@ void createTransData(bContext *C, TransInfo *t) t->flag |= T_POINTS; if (t->data_len_all && t->flag & T_PROP_EDIT) { - sort_trans_data(t); // makes selected become first in array + sort_trans_data_selected_first(t); set_prop_dist(t, 1); sort_trans_data_dist(t); } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index a840c04ab5a..758551be0b5 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -781,6 +781,49 @@ static void recalcData_spaceclip(TransInfo *t) } } +/** + * if pose bone (partial) selected, copy data. + * context; posemode armature, with mirror editing enabled. + * + * \param pid: Optional, apply relative transform when set. + */ +static void pose_transform_mirror_update(Object *ob, PoseInitData_Mirror *pid) +{ + float flip_mtx[4][4]; + unit_m4(flip_mtx); + flip_mtx[0][0] = -1; + + for (bPoseChannel *pchan_orig = ob->pose->chanbase.first; pchan_orig; + pchan_orig = pchan_orig->next) { + /* no layer check, correct mirror is more important */ + if (pchan_orig->bone->flag & BONE_TRANSFORM) { + bPoseChannel *pchan = BKE_pose_channel_get_mirrored(ob->pose, pchan_orig->name); + + if (pchan) { + /* also do bbone scaling */ + pchan->bone->xwidth = pchan_orig->bone->xwidth; + pchan->bone->zwidth = pchan_orig->bone->zwidth; + + /* we assume X-axis flipping for now */ + pchan->curve_in_x = pchan_orig->curve_in_x * -1; + pchan->curve_out_x = pchan_orig->curve_out_x * -1; + pchan->roll1 = pchan_orig->roll1 * -1; // XXX? + pchan->roll2 = pchan_orig->roll2 * -1; // XXX? + + float pchan_mtx_final[4][4]; + BKE_pchan_to_mat4(pchan_orig, pchan_mtx_final); + mul_m4_m4m4(pchan_mtx_final, pchan_mtx_final, flip_mtx); + mul_m4_m4m4(pchan_mtx_final, flip_mtx, pchan_mtx_final); + if (pid) { + mul_m4_m4m4(pchan_mtx_final, pid->offset_mtx, pchan_mtx_final); + pid++; + } + BKE_pchan_apply_mat4(pchan, pchan_mtx_final, false); + } + } + } +} + /* helper for recalcData() - for object transforms, typically in the 3D view */ static void recalcData_objects(TransInfo *t) { @@ -975,12 +1018,22 @@ static void recalcData_objects(TransInfo *t) FOREACH_TRANS_DATA_CONTAINER (t, tc) { Object *ob = tc->poseobj; bArmature *arm = ob->data; - if (arm->flag & ARM_MIRROR_EDIT) { - if (t->state != TRANS_CANCEL) { - ED_armature_edit_transform_mirror_update(ob); + if (ob->mode == OB_MODE_EDIT) { + if (arm->flag & ARM_MIRROR_EDIT) { + if (t->state != TRANS_CANCEL) { + ED_armature_edit_transform_mirror_update(ob); + } + else { + restoreBones(tc); + } } - else { - restoreBones(tc); + } + else if (ob->mode == OB_MODE_POSE) { + /* actually support TFM_BONESIZE in posemode as well */ + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + bPose *pose = ob->pose; + if (arm->flag & ARM_MIRROR_EDIT || pose->flag & POSE_MIRROR_EDIT) { + pose_transform_mirror_update(ob, NULL); } } } @@ -991,6 +1044,20 @@ static void recalcData_objects(TransInfo *t) FOREACH_TRANS_DATA_CONTAINER (t, tc) { Object *ob = tc->poseobj; bArmature *arm = ob->data; + bPose *pose = ob->pose; + + if (pose->flag & POSE_MIRROR_EDIT) { + if (t->state != TRANS_CANCEL) { + PoseInitData_Mirror *pid = NULL; + if (pose->flag & POSE_MIRROR_RELATIVE) { + pid = tc->custom.type.data; + } + pose_transform_mirror_update(ob, pid); + } + else { + restoreMirrorPoseBones(tc); + } + } /* if animtimer is running, and the object already has animation data, * check if the auto-record feature means that we should record 'samples' @@ -1121,8 +1188,6 @@ static void recalcData_sequencer(TransInfo *t) seq_prev = seq; } - DEG_id_tag_update(&t->scene->id, ID_RECALC_SEQUENCER); - flushTransSeq(t); } @@ -1311,7 +1376,9 @@ void initTransDataContainers_FromObjectData(TransInfo *t, BLI_assert((t->flag & T_2D_EDIT) == 0); copy_m4_m4(tc->mat, objects[i]->obmat); copy_m3_m4(tc->mat3, tc->mat); - invert_m4_m4(tc->imat, tc->mat); + /* for non-invertible scale matrices, invert_m4_m4_fallback() + * can still provide a valid pivot */ + invert_m4_m4_fallback(tc->imat, tc->mat); invert_m3_m3(tc->imat3, tc->mat3); normalize_m3_m3(tc->mat3_unit, tc->mat3); } diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 50610f1b3da..35fda39e8dc 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -1762,6 +1762,15 @@ static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *gzgroup) } } MAN_ITER_AXES_END; + + /* Ensure rotate disks don't overlap scale arrows, especially in ortho view. */ + float rotate_select_bias = 0.0f; + if ((ggd->twtype & V3D_GIZMO_SHOW_OBJECT_SCALE) && ggd->twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) { + rotate_select_bias = -2.0f; + } + for (int i = MAN_AXIS_RANGE_ROT_START; i < MAN_AXIS_RANGE_ROT_END; i++) { + ggd->gizmos[i]->select_bias = rotate_select_bias; + } } static void WIDGETGROUP_gizmo_message_subscribe(const bContext *C, diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index 3b49784d5eb..0564cb07897 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -84,6 +84,7 @@ set(SRC ../include/ED_sound.h ../include/ED_space_api.h ../include/ED_text.h + ../include/ED_time_scrub_ui.h ../include/ED_transform.h ../include/ED_transform_snap_object_context.h ../include/ED_transverts.h diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 804b9c22104..3a5aead3d44 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -170,6 +170,7 @@ static void uvedit_get_batches(Object *ob, const bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0; const bool draw_faces = (sima->flag & SI_NO_DRAWFACES) == 0; + DRW_mesh_batch_cache_validate(ob->data); *edges = DRW_mesh_batch_cache_get_edituv_edges(ob->data); *verts = DRW_mesh_batch_cache_get_edituv_verts(ob->data); @@ -206,6 +207,7 @@ static void draw_uvs_shadow(SpaceImage *UNUSED(sima), float col[4]; UI_GetThemeColor4fv(TH_UV_SHADOW, col); + DRW_mesh_batch_cache_validate(me); GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me); DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false); @@ -228,6 +230,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) return; } + DRW_mesh_batch_cache_validate(me); GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me); DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 85393925802..717bc347cf7 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -386,6 +386,10 @@ static ParamHandle *construct_param_handle_multi(Scene *scene, const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + if (cd_loop_uv_offset == -1) { + continue; + } + BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || diff --git a/source/blender/freestyle/intern/geometry/Noise.cpp b/source/blender/freestyle/intern/geometry/Noise.cpp index 09c29025d15..8b81660fd58 100644 --- a/source/blender/freestyle/intern/geometry/Noise.cpp +++ b/source/blender/freestyle/intern/geometry/Noise.cpp @@ -24,6 +24,9 @@ #include <stdlib.h> #include <time.h> +#include "BLI_compiler_attrs.h" +#include "BLI_rand.h" + #include "Noise.h" namespace Freestyle { @@ -40,9 +43,7 @@ namespace Freestyle { ((s) * (RTable[m] * 0.5 + RTable[m + 1] * (x) + RTable[m + 2] * (y) + RTable[m + 3] * (z))) # define MAXSIZE 500 -# define NRAND() ((float)rand() / (float)RAND_MAX) #endif -#define SEEDNRAND(x) (srand(x * RAND_MAX)) #define BM 0xff #define N 0x1000 @@ -236,25 +237,26 @@ float Noise::smoothNoise3(Vec3f &vec) Noise::Noise(long seed) { + /* Use Blender RNG for repeatable results across platforms. */ + RNG *rng = BLI_rng_new(seed); int i, j, k; - SEEDNRAND((seed < 0) ? time(NULL) : seed); for (i = 0; i < _NOISE_B; i++) { p[i] = i; - g1[i] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B; + g1[i] = (float)((BLI_rng_get_int(rng) % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B; for (j = 0; j < 2; j++) - g2[i][j] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B; + g2[i][j] = (float)((BLI_rng_get_int(rng) % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B; normalize2(g2[i]); for (j = 0; j < 3; j++) - g3[i][j] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B; + g3[i][j] = (float)((BLI_rng_get_int(rng) % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B; normalize3(g3[i]); } while (--i) { k = p[i]; - p[i] = p[j = rand() % _NOISE_B]; + p[i] = p[j = BLI_rng_get_int(rng) % _NOISE_B]; p[j] = k; } @@ -268,6 +270,8 @@ Noise::Noise(long seed) for (j = 0; j < 3; j++) g3[_NOISE_B + i][j] = g3[i][j]; } + + BLI_rng_free(rng); } } /* namespace Freestyle */ diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 5a42c4d3d1b..f30eff1484b 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -178,7 +178,6 @@ data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_normal_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_flat_color_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_smooth_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_normal_smooth_color_vert.glsl SRC) @@ -225,14 +224,6 @@ data_to_c_simple(shaders/gpu_shader_2D_edituvs_stretch_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_selection_id_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_selection_id_frag.glsl SRC) -data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_geom.glsl SRC) -data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_edges_front_back_ortho_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_edges_overlay_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_edges_overlay_geom.glsl SRC) -data_to_c_simple(shaders/gpu_shader_edges_overlay_simple_geom.glsl SRC) -data_to_c_simple(shaders/gpu_shader_edges_overlay_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_text_simple_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_text_simple_geom.glsl SRC) data_to_c_simple(shaders/gpu_shader_text_vert.glsl SRC) diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index 856148563f2..783bfb0b1f0 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -33,6 +33,7 @@ #include "GPU_shader.h" typedef enum { + GPU_BATCH_UNUSED, GPU_BATCH_READY_TO_FORMAT, GPU_BATCH_READY_TO_BUILD, GPU_BATCH_BUILDING, diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index 718553e2b1c..9009c134837 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -32,10 +32,10 @@ struct CCGKey; struct DMFlagMat; struct GSet; struct MLoop; +struct MLoopCol; struct MLoopTri; struct MPoly; struct MVert; -struct MLoopCol; struct PBVH; /* Buffers for drawing from PBVH grids. */ diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 300fc7c65a2..eb54ff127d8 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -84,7 +84,7 @@ void GPU_create_gl_tex(unsigned int *bind, int recth, int textarget, bool mipmap, - bool use_hight_bit_depth, + bool use_srgb, struct Image *ima); void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix, diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index da61dc76422..dd5292d9c58 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -107,7 +107,7 @@ typedef enum eGPUBuiltin { GPU_VOLUME_TEMPERATURE = (1 << 18), GPU_BARYCENTRIC_TEXCO = (1 << 19), GPU_BARYCENTRIC_DIST = (1 << 20), - GPU_INVERSE_NORMAL_MATRIX = (1 << 21), + GPU_WORLD_NORMAL = (1 << 21), } eGPUBuiltin; typedef enum eGPUMatFlag { @@ -145,7 +145,7 @@ typedef enum eGPUMaterialStatus { GPUNodeLink *GPU_attribute(CustomDataType type, const char *name); GPUNodeLink *GPU_constant(float *num); GPUNodeLink *GPU_uniform(float *num); -GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data); +GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser); GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer); GPUNodeLink *GPU_builtin(eGPUBuiltin builtin); @@ -177,6 +177,7 @@ GPUMaterial *GPU_material_from_nodetree_find(struct ListBase *gpumaterials, const void *engine_type, int options); GPUMaterial *GPU_material_from_nodetree(struct Scene *scene, + struct Material *ma, struct bNodeTree *ntree, struct ListBase *gpumaterials, const void *engine_type, @@ -194,6 +195,7 @@ void GPU_materials_free(struct Main *bmain); struct Scene *GPU_material_scene(GPUMaterial *material); struct GPUPass *GPU_material_get_pass(GPUMaterial *material); struct ListBase *GPU_material_get_inputs(GPUMaterial *material); +struct Material *GPU_material_get_material(GPUMaterial *material); eGPUMaterialStatus GPU_material_status(GPUMaterial *mat); struct GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material); @@ -202,7 +204,6 @@ struct GPUUniformBuffer *GPU_material_create_sss_profile_ubo(void); void GPU_material_vertex_attrs(GPUMaterial *material, struct GPUVertAttrLayers *attrs); -bool GPU_material_do_color_management(GPUMaterial *mat); bool GPU_material_use_domain_surface(GPUMaterial *mat); bool GPU_material_use_domain_volume(GPUMaterial *mat); diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h index 67fb2bb2bd4..6f7d25dafa7 100644 --- a/source/blender/gpu/GPU_matrix.h +++ b/source/blender/gpu/GPU_matrix.h @@ -106,6 +106,11 @@ bool GPU_matrix_unproject(const float win[3], const float proj[4][4], const int view[4], float world[3]); +void GPU_matrix_unproject_model_inverted(const float win[3], + const float model_inverted[4][4], + const float proj[4][4], + const int view[4], + float world[3]); /* 2D Projection Matrix */ diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index d174aafacce..00570bd7ebc 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -100,10 +100,6 @@ typedef enum eGPUBuiltinShader { /* specialized drawing */ GPU_SHADER_TEXT, GPU_SHADER_TEXT_SIMPLE, - GPU_SHADER_EDGES_FRONT_BACK_PERSP, - GPU_SHADER_EDGES_FRONT_BACK_ORTHO, - GPU_SHADER_EDGES_OVERLAY_SIMPLE, - GPU_SHADER_EDGES_OVERLAY, GPU_SHADER_KEYFRAME_DIAMOND, GPU_SHADER_SIMPLE_LIGHTING, GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR, @@ -402,10 +398,7 @@ void GPU_shader_free_builtin_shaders(void); typedef struct GPUVertAttrLayers { struct { - int type; - int glindex; - int glinfoindoex; - int gltexco; + int type; /* CustomDataType */ int attr_id; char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ } layer[GPU_MAX_ATTR]; diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h index ace8832303b..fc7d9e22ea3 100644 --- a/source/blender/gpu/GPU_shader_interface.h +++ b/source/blender/gpu/GPU_shader_interface.h @@ -45,13 +45,10 @@ typedef enum { GPU_UNIFORM_VIEWPROJECTION_INV, /* mat4 ViewProjectionMatrixInverse */ GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */ - GPU_UNIFORM_NORMAL_INV, /* mat3 NormalMatrixInverse */ - GPU_UNIFORM_WORLDNORMAL, /* mat3 WorldNormalMatrix */ GPU_UNIFORM_CAMERATEXCO, /* vec4 CameraTexCoFactors */ GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */ GPU_UNIFORM_COLOR, /* vec4 color */ - GPU_UNIFORM_EYE, /* vec3 eye */ GPU_UNIFORM_CALLID, /* int callId */ GPU_UNIFORM_OBJECT_INFO, /* vec3 objectInfo */ diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 3527398a396..3fb7dfc6331 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -186,10 +186,7 @@ GPUTexture *GPU_texture_create_from_vertbuf(struct GPUVertBuf *vert); GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat data_type, const uint buffer); GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode); -GPUTexture *GPU_texture_from_blender(struct Image *ima, - struct ImageUser *iuser, - int textarget, - bool is_data); +GPUTexture *GPU_texture_from_blender(struct Image *ima, struct ImageUser *iuser, int textarget); GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap); void GPU_texture_add_mipmap(GPUTexture *tex, diff --git a/source/blender/gpu/GPU_vertex_buffer.h b/source/blender/gpu/GPU_vertex_buffer.h index 6d88460964d..3e178e193dc 100644 --- a/source/blender/gpu/GPU_vertex_buffer.h +++ b/source/blender/gpu/GPU_vertex_buffer.h @@ -48,12 +48,17 @@ typedef enum { typedef struct GPUVertBuf { GPUVertFormat format; - uint vertex_len; /* number of verts we want to draw */ - uint vertex_alloc; /* number of verts data */ - bool dirty; + /** Number of verts we want to draw. */ + uint vertex_len; + /** Number of verts data. */ + uint vertex_alloc; + /** 0 indicates not yet allocated. */ + uint32_t vbo_id; + /** Usage hint for GL optimisation. */ + uint usage : 2; + /** Data has been touched and need to be reuploaded to GPU. */ + uint dirty : 1; unsigned char *data; /* NULL indicates data in VRAM (unmapped) */ - uint32_t vbo_id; /* 0 indicates not yet allocated */ - GPUUsageType usage; /* usage hint for GL optimisation */ } GPUVertBuf; GPUVertBuf *GPU_vertbuf_create(GPUUsageType); @@ -62,6 +67,7 @@ GPUVertBuf *GPU_vertbuf_create_with_format_ex(const GPUVertFormat *, GPUUsageTyp #define GPU_vertbuf_create_with_format(format) \ GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_STATIC) +void GPU_vertbuf_clear(GPUVertBuf *verts); void GPU_vertbuf_discard(GPUVertBuf *); void GPU_vertbuf_init(GPUVertBuf *, GPUUsageType); diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h index 7f1934431cf..43eec55bca2 100644 --- a/source/blender/gpu/GPU_vertex_format.h +++ b/source/blender/gpu/GPU_vertex_format.h @@ -27,6 +27,8 @@ #define __GPU_VERTEX_FORMAT_H__ #include "GPU_common.h" +#include "BLI_compiler_compat.h" +#include "BLI_assert.h" #define GPU_VERT_ATTR_MAX_LEN 16 #define GPU_VERT_ATTR_MAX_NAMES 4 @@ -54,28 +56,41 @@ typedef enum { } GPUVertFetchMode; typedef struct GPUVertAttr { - GPUVertFetchMode fetch_mode; - GPUVertCompType comp_type; + uint fetch_mode : 2; + uint comp_type : 3; + /* 1 to 4 or 8 or 12 or 16 */ + uint comp_len : 5; + /* size in bytes, 1 to 64 */ + uint sz : 7; + /* from beginning of vertex, in bytes */ + uint offset : 11; + /* up to GPU_VERT_ATTR_MAX_NAMES */ + uint name_len : 3; uint gl_comp_type; - uint comp_len; /* 1 to 4 or 8 or 12 or 16 */ - uint sz; /* size in bytes, 1 to 64 */ - uint offset; /* from beginning of vertex, in bytes */ - uint name_len; /* up to GPU_VERT_ATTR_MAX_NAMES */ - const char *name[GPU_VERT_ATTR_MAX_NAMES]; + /* -- 8 Bytes -- */ + uchar names[GPU_VERT_ATTR_MAX_NAMES]; } GPUVertAttr; +BLI_STATIC_ASSERT(GPU_VERT_ATTR_NAMES_BUF_LEN <= 256, + "We use uchar as index inside the name buffer " + "so GPU_VERT_ATTR_NAMES_BUF_LEN needs to be be " + "smaller than GPUVertFormat->name_offset and " + "GPUVertAttr->names maximum value"); + typedef struct GPUVertFormat { /** 0 to 16 (GPU_VERT_ATTR_MAX_LEN). */ - uint attr_len; + uint attr_len : 5; /** Total count of active vertex attribute. */ - uint name_len; - /** Stride in bytes, 1 to 256. */ - uint stride; - uint name_offset; - bool packed; - char names[GPU_VERT_ATTR_NAMES_BUF_LEN]; - /** TODO: variable-size array */ + uint name_len : 5; + /** Stride in bytes, 1 to 1024. */ + uint stride : 11; + /** Has the format been packed. */ + uint packed : 1; + /** Current offset in names[]. */ + uint name_offset : 8; + GPUVertAttr attrs[GPU_VERT_ATTR_MAX_LEN]; + char names[GPU_VERT_ATTR_NAMES_BUF_LEN]; } GPUVertFormat; struct GPUShaderInterface; @@ -88,18 +103,15 @@ void GPU_vertformat_from_interface(GPUVertFormat *format, uint GPU_vertformat_attr_add( GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode); void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias); + int GPU_vertformat_attr_id_get(const GPUVertFormat *, const char *name); -/** - * This makes the "virtual" attributes with suffixes "0", "1", "2" - * to access triangle data in the vertex shader. - * - * IMPORTANT: - * - Call this before creating the vertex buffer and after creating all attributes - * - Only first vertex out of 3 has the correct information. - * Use flat output with #GL_FIRST_VERTEX_CONVENTION. - */ -void GPU_vertformat_triple_load(GPUVertFormat *format); +BLI_INLINE const char *GPU_vertformat_attr_name_get(const GPUVertFormat *format, + const GPUVertAttr *attr, + uint n_idx) +{ + return format->names + attr->names[n_idx]; +} /* format conversion */ diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index 198a9ec98e2..e61cfe363df 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -37,12 +37,12 @@ typedef struct GPUViewport GPUViewport; /* Contains memory pools information */ typedef struct ViewportMemoryPool { - struct BLI_mempool *calls; - struct BLI_mempool *states; - struct BLI_mempool *shgroups; - struct BLI_mempool *uniforms; - struct BLI_mempool *passes; - struct BLI_mempool *images; + struct BLI_memblock *calls; + struct BLI_memblock *states; + struct BLI_memblock *shgroups; + struct BLI_memblock *uniforms; + struct BLI_memblock *passes; + struct BLI_memblock *images; } ViewportMemoryPool; /* All FramebufferLists are just the same pointers with different names */ @@ -118,7 +118,7 @@ GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport); GPUTexture *GPU_viewport_texture_pool_query( GPUViewport *viewport, void *engine, int width, int height, int format); -bool GPU_viewport_engines_data_validate(GPUViewport *viewport, unsigned int hash); +bool GPU_viewport_engines_data_validate(GPUViewport *viewport, void **engine_handle_array); void GPU_viewport_cache_release(GPUViewport *viewport); #endif // __GPU_VIEWPORT_H__ diff --git a/source/blender/gpu/intern/gpu_attr_binding.c b/source/blender/gpu/intern/gpu_attr_binding.c index e280b77f661..802b15a0c4e 100644 --- a/source/blender/gpu/intern/gpu_attr_binding.c +++ b/source/blender/gpu/intern/gpu_attr_binding.c @@ -70,7 +70,8 @@ void get_attr_locations(const GPUVertFormat *format, for (uint a_idx = 0; a_idx < format->attr_len; ++a_idx) { const GPUVertAttr *a = &format->attrs[a_idx]; for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) { - const GPUShaderInput *input = GPU_shaderinterface_attr(shaderface, a->name[n_idx]); + const char *name = GPU_vertformat_attr_name_get(format, a, n_idx); + const GPUShaderInput *input = GPU_shaderinterface_attr(shaderface, name); #if TRUST_NO_ONE assert(input != NULL); /* TODO: make this a recoverable runtime error? diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c index f179f9ef22c..45697befe50 100644 --- a/source/blender/gpu/intern/gpu_batch.c +++ b/source/blender/gpu/intern/gpu_batch.c @@ -139,6 +139,7 @@ void GPU_batch_clear(GPUBatch *batch) } } GPU_batch_vao_cache_clear(batch); + batch->phase = GPU_BATCH_UNUSED; } void GPU_batch_discard(GPUBatch *batch) @@ -369,7 +370,8 @@ static void create_bindings(GPUVertBuf *verts, const GLvoid *pointer = (const GLubyte *)0 + a->offset + v_first * stride; for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) { - const GPUShaderInput *input = GPU_shaderinterface_attr(interface, a->name[n_idx]); + const char *name = GPU_vertformat_attr_name_get(format, a, n_idx); + const GPUShaderInput *input = GPU_shaderinterface_attr(interface, name); if (input == NULL) { continue; diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index a77bba5ab86..8dda98ab990 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -520,9 +520,6 @@ const char *GPU_builtin_name(eGPUBuiltin builtin) else if (builtin == GPU_INVERSE_OBJECT_MATRIX) { return "unfinvobmat"; } - else if (builtin == GPU_INVERSE_NORMAL_MATRIX) { - return "unfinvnormat"; - } else if (builtin == GPU_LOC_TO_VIEW_MATRIX) { return "unflocaltoviewmat"; } @@ -532,6 +529,9 @@ const char *GPU_builtin_name(eGPUBuiltin builtin) else if (builtin == GPU_VIEW_POSITION) { return "varposition"; } + else if (builtin == GPU_WORLD_NORMAL) { + return "varwnormal"; + } else if (builtin == GPU_VIEW_NORMAL) { return "varnormal"; } @@ -786,15 +786,15 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final else if (input->builtin == GPU_INVERSE_OBJECT_MATRIX) { BLI_dynstr_append(ds, "objinv"); } - else if (input->builtin == GPU_INVERSE_NORMAL_MATRIX) { - BLI_dynstr_append(ds, "norinv"); - } else if (input->builtin == GPU_VIEW_POSITION) { BLI_dynstr_append(ds, "viewposition"); } else if (input->builtin == GPU_VIEW_NORMAL) { BLI_dynstr_append(ds, "facingnormal"); } + else if (input->builtin == GPU_WORLD_NORMAL) { + BLI_dynstr_append(ds, "facingwnormal"); + } else { BLI_dynstr_append(ds, GPU_builtin_name(input->builtin)); } @@ -879,17 +879,15 @@ static char *code_generate_fragment(GPUMaterial *material, if (builtins & GPU_INVERSE_OBJECT_MATRIX) { BLI_dynstr_append(ds, "\t#define objinv ModelMatrixInverse\n"); } - if (builtins & GPU_INVERSE_NORMAL_MATRIX) { - BLI_dynstr_append(ds, "\t#define norinv NormalMatrixInverse\n"); - } if (builtins & GPU_INVERSE_VIEW_MATRIX) { BLI_dynstr_append(ds, "\t#define viewinv ViewMatrixInverse\n"); } if (builtins & GPU_LOC_TO_VIEW_MATRIX) { - BLI_dynstr_append(ds, "\t#define localtoviewmat ModelViewMatrix\n"); + BLI_dynstr_append(ds, "\t#define localtoviewmat (ViewMatrix * ModelMatrix)\n"); } if (builtins & GPU_INVERSE_LOC_TO_VIEW_MATRIX) { - BLI_dynstr_append(ds, "\t#define invlocaltoviewmat ModelViewMatrixInverse\n"); + BLI_dynstr_append(ds, + "\t#define invlocaltoviewmat (ModelMatrixInverse * ViewMatrixInverse)\n"); } if (builtins & GPU_VIEW_NORMAL) { BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); @@ -897,9 +895,22 @@ static char *code_generate_fragment(GPUMaterial *material, BLI_dynstr_append(ds, "\tworld_normals_get(n);\n"); BLI_dynstr_append(ds, "\tvec3 facingnormal = transform_direction(ViewMatrix, n);\n"); BLI_dynstr_append(ds, "#else\n"); - BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? viewNormal: -viewNormal;\n"); + BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing ? viewNormal: -viewNormal;\n"); BLI_dynstr_append(ds, "#endif\n"); } + if (builtins & GPU_WORLD_NORMAL) { + BLI_dynstr_append(ds, "\tvec3 facingwnormal;\n"); + if (builtins & GPU_VIEW_NORMAL) { + BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); + BLI_dynstr_append(ds, "\tfacingwnormal = n;\n"); + BLI_dynstr_append(ds, "#else\n"); + BLI_dynstr_append(ds, "\tworld_normals_get(facingwnormal);\n"); + BLI_dynstr_append(ds, "#endif\n"); + } + else { + BLI_dynstr_append(ds, "\tworld_normals_get(facingwnormal);\n"); + } + } if (builtins & GPU_VIEW_POSITION) { BLI_dynstr_append(ds, "\t#define viewposition viewPosition\n"); } @@ -1024,13 +1035,39 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u BLI_dynstr_append(ds, "out vec3 barycentricPosg;\n"); } + BLI_dynstr_append(ds, "\n#define USE_ATTR\n"); + + /* Prototype, defined later (this is because of matrices definition). */ + BLI_dynstr_append(ds, "void pass_attr(in vec3 position);\n"); + + BLI_dynstr_append(ds, "\n"); + + if (use_geom) { + /* XXX HACK: Eevee specific. */ + char *vert_new, *vert_new2; + vert_new = BLI_str_replaceN(vert_code, "worldPosition", "worldPositiong"); + vert_new2 = vert_new; + vert_new = BLI_str_replaceN(vert_new2, "viewPosition", "viewPositiong"); + MEM_freeN(vert_new2); + vert_new2 = vert_new; + vert_new = BLI_str_replaceN(vert_new2, "worldNormal", "worldNormalg"); + MEM_freeN(vert_new2); + vert_new2 = vert_new; + vert_new = BLI_str_replaceN(vert_new2, "viewNormal", "viewNormalg"); + MEM_freeN(vert_new2); + + BLI_dynstr_append(ds, vert_new); + + MEM_freeN(vert_new); + } + else { + BLI_dynstr_append(ds, vert_code); + } + BLI_dynstr_append(ds, "\n"); BLI_dynstr_append(ds, "#define USE_ATTR\n" - "uniform mat3 NormalMatrix;\n" - "uniform mat4 ModelMatrixInverse;\n" - "uniform mat4 ModelMatrix;\n" "vec3 srgb_to_linear_attr(vec3 c) {\n" "\tc = max(c, vec3(0.0));\n" "\tvec3 c1 = c * (1.0 / 12.92);\n" @@ -1108,7 +1145,7 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u if (input->source == GPU_SOURCE_ATTR && input->attr_first) { if (input->attr_type == CD_TANGENT) { /* silly exception */ BLI_dynstr_appendf(ds, - "\tvar%d%s.xyz = NormalMatrix * att%d.xyz;\n", + "\tvar%d%s.xyz = transpose(mat3(ModelMatrixInverse)) * att%d.xyz;\n", input->attr_id, use_geom ? "g" : "", input->attr_id); @@ -1167,28 +1204,6 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u BLI_dynstr_append(ds, "}\n"); - if (use_geom) { - /* XXX HACK: Eevee specific. */ - char *vert_new, *vert_new2; - vert_new = BLI_str_replaceN(vert_code, "worldPosition", "worldPositiong"); - vert_new2 = vert_new; - vert_new = BLI_str_replaceN(vert_new2, "viewPosition", "viewPositiong"); - MEM_freeN(vert_new2); - vert_new2 = vert_new; - vert_new = BLI_str_replaceN(vert_new2, "worldNormal", "worldNormalg"); - MEM_freeN(vert_new2); - vert_new2 = vert_new; - vert_new = BLI_str_replaceN(vert_new2, "viewNormal", "viewNormalg"); - MEM_freeN(vert_new2); - - BLI_dynstr_append(ds, vert_new); - - MEM_freeN(vert_new); - } - else { - BLI_dynstr_append(ds, vert_code); - } - code = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); @@ -1494,7 +1509,6 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType input->source = GPU_SOURCE_TEX; input->ima = link->ima; input->iuser = link->iuser; - input->image_isdata = link->image_isdata; break; case GPU_NODE_LINK_ATTR: input->source = GPU_SOURCE_ATTR; @@ -1739,13 +1753,12 @@ GPUNodeLink *GPU_uniform(float *num) return link; } -GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data) +GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser) { GPUNodeLink *link = GPU_node_link_create(); link->link_type = GPU_NODE_LINK_IMAGE_BLENDER; link->ima = ima; link->iuser = iuser; - link->image_isdata = is_data; return link; } diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index 73155c3aafa..d1bb3f26920 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -99,7 +99,6 @@ struct GPUNodeLink { struct { struct Image *ima; struct ImageUser *iuser; - bool image_isdata; }; }; }; @@ -137,7 +136,6 @@ typedef struct GPUInput { struct GPUTexture **coba; /* input texture, only set at runtime */ struct Image *ima; /* image */ struct ImageUser *iuser; /* image user */ - bool image_isdata; /* image does not contain color data */ bool bindtex; /* input is responsible for binding the texture? */ int texid; /* number for multitexture, starting from zero */ eGPUType textype; /* texture type (2D, 1D Array ...) */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index edc2f2171a5..f1c82dc53a7 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -50,6 +50,7 @@ #include "MEM_guardedalloc.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -207,53 +208,232 @@ static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget) return NULL; } -typedef struct VerifyThreadData { - ImBuf *ibuf; - float *srgb_frect; -} VerifyThreadData; +static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget) +{ + uint bindcode = 0; + const bool mipmap = GPU_get_mipmap(); + +#ifdef WITH_DDS + if (ibuf->ftype == IMB_FTYPE_DDS) { + /* DDS is loaded directly in compressed form. */ + GPU_create_gl_tex_compressed( + &bindcode, ibuf->rect, ibuf->x, ibuf->y, textarget, mipmap, ima, ibuf); + return bindcode; + } +#endif + + /* Regular uncompressed texture. */ + float *rect_float = ibuf->rect_float; + uchar *rect = (uchar *)ibuf->rect; + bool compress_as_srgb = false; + + if (rect_float == NULL) { + /* Byte image is in original colorspace from the file. If the file is sRGB + * scene linear, or non-color data no conversion is needed. Otherwise we + * compress as scene linear + sRGB transfer function to avoid precision loss + * in common cases. + * + * We must also convert to premultiplied for correct texture interpolation + * and consistency with float images. */ + if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) { + compress_as_srgb = !IMB_colormanagement_space_is_scene_linear(ibuf->rect_colorspace); + + rect = MEM_mallocN(sizeof(uchar) * 4 * ibuf->x * ibuf->y, __func__); + if (rect == NULL) { + return bindcode; + } + + IMB_colormanagement_imbuf_to_srgb_texture( + rect, 0, 0, ibuf->x, ibuf->y, ibuf, compress_as_srgb); + } + } + else if (ibuf->channels != 4) { + /* Float image is already in scene linear colorspace or non-color data by + * convention, no colorspace conversion needed. But we do require 4 channels + * currently. */ + rect_float = MEM_mallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, __func__); + if (rect_float == NULL) { + return bindcode; + } -static void gpu_verify_high_bit_srgb_buffer_slice(float *srgb_frect, - ImBuf *ibuf, - const int start_line, - const int height) + IMB_buffer_float_from_float(rect_float, + ibuf->rect_float, + ibuf->channels, + IB_PROFILE_LINEAR_RGB, + IB_PROFILE_LINEAR_RGB, + false, + ibuf->x, + ibuf->y, + ibuf->x, + ibuf->x); + } + + /* Create OpenGL texture. */ + GPU_create_gl_tex(&bindcode, + (uint *)rect, + rect_float, + ibuf->x, + ibuf->y, + textarget, + mipmap, + compress_as_srgb, + ima); + + /* Free buffers if needed. */ + if (rect && rect != (uchar *)ibuf->rect) { + MEM_freeN(rect); + } + if (rect_float && rect_float != ibuf->rect_float) { + MEM_freeN(rect_float); + } + + return bindcode; +} + +static void gpu_texture_update_scaled( + uchar *rect, float *rect_float, int full_w, int full_h, int x, int y, int w, int h) { - size_t offset = ibuf->channels * start_line * ibuf->x; - float *current_srgb_frect = srgb_frect + offset; - float *current_rect_float = ibuf->rect_float + offset; - IMB_buffer_float_from_float(current_srgb_frect, - current_rect_float, - ibuf->channels, - IB_PROFILE_SRGB, - IB_PROFILE_LINEAR_RGB, - true, - ibuf->x, - height, - ibuf->x, - ibuf->x); - IMB_buffer_float_unpremultiply(current_srgb_frect, ibuf->x, height); + /* Partial update with scaling. */ + int limit_w = smaller_power_of_2_limit(full_w); + int limit_h = smaller_power_of_2_limit(full_h); + float xratio = limit_w / (float)full_w; + float yratio = limit_h / (float)full_h; + + /* Find sub coordinates in scaled image. Take ceiling because we will be + * losing 1 pixel due to rounding errors in x,y. */ + int sub_x = x * xratio; + int sub_y = y * yratio; + int sub_w = (int)ceil(xratio * w); + int sub_h = (int)ceil(yratio * h); + + /* ...but take back if we are over the limit! */ + if (sub_w + sub_x > limit_w) { + sub_w--; + } + if (sub_h + sub_y > limit_h) { + sub_h--; + } + + /* Scale pixels. */ + ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, w, h); + IMB_scaleImBuf(ibuf, sub_w, sub_h); + + if (ibuf->rect_float) { + glTexSubImage2D( + GL_TEXTURE_2D, 0, sub_x, sub_y, sub_w, sub_h, GL_RGBA, GL_FLOAT, ibuf->rect_float); + } + else { + glTexSubImage2D( + GL_TEXTURE_2D, 0, sub_x, sub_y, sub_w, sub_h, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + } + + IMB_freeImBuf(ibuf); } -static void verify_thread_do(void *data_v, int start_scanline, int num_scanlines) +static void gpu_texture_update_unscaled( + uchar *rect, float *rect_float, int x, int y, int w, int h, GLint tex_stride, GLint tex_offset) { - VerifyThreadData *data = (VerifyThreadData *)data_v; - gpu_verify_high_bit_srgb_buffer_slice( - data->srgb_frect, data->ibuf, start_scanline, num_scanlines); + /* Partial update without scaling. Stride and offset are used to copy only a + * subset of a possible larger buffer than what we are updating. */ + GLint row_length; + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); + glPixelStorei(GL_UNPACK_ROW_LENGTH, tex_stride); + + if (rect_float == NULL) { + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect + tex_offset); + } + else { + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, rect_float + tex_offset); + } + + glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); } -static void gpu_verify_high_bit_srgb_buffer(float *srgb_frect, ImBuf *ibuf) +static void gpu_texture_update_from_ibuf(ImBuf *ibuf, int x, int y, int w, int h) { - if (ibuf->y < 64) { - gpu_verify_high_bit_srgb_buffer_slice(srgb_frect, ibuf, 0, ibuf->y); + /* Partial update of texture for texture painting. This is often much + * quicker than fully updating the texture for high resolution images. + * Assumes the OpenGL texture is bound to 0. */ + const bool scaled = is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y); + + if (scaled) { + /* Extra padding to account for bleed from neighboring pixels. */ + const int padding = 4; + const int xmax = min_ii(x + w + padding, ibuf->x); + const int ymax = min_ii(y + h + padding, ibuf->y); + x = max_ii(x - padding, 0); + y = max_ii(y - padding, 0); + w = xmax - x; + h = ymax - y; + } + + /* Get texture data pointers. */ + float *rect_float = ibuf->rect_float; + uchar *rect = (uchar *)ibuf->rect; + GLint tex_stride = ibuf->x; + GLint tex_offset = ibuf->channels * (y * ibuf->x + x); + + if (rect_float == NULL) { + /* Byte pixels. */ + if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) { + const bool compress_as_srgb = !IMB_colormanagement_space_is_scene_linear( + ibuf->rect_colorspace); + + rect = MEM_mallocN(sizeof(uchar) * 4 * w * h, __func__); + if (rect == NULL) { + return; + } + + tex_stride = w; + tex_offset = 0; + + /* Convert to scene linear with sRGB compression, and premultiplied for + * correct texture interpolation. */ + IMB_colormanagement_imbuf_to_srgb_texture(rect, x, y, w, h, ibuf, compress_as_srgb); + } + } + else if (ibuf->channels != 4 || scaled) { + /* Float pixels. */ + rect_float = MEM_mallocN(sizeof(float) * 4 * x * y, __func__); + if (rect_float == NULL) { + return; + } + + tex_stride = w; + tex_offset = 0; + + size_t ibuf_offset = (y * ibuf->x + x) * ibuf->channels; + IMB_buffer_float_from_float(rect_float, + ibuf->rect_float + ibuf_offset, + ibuf->channels, + IB_PROFILE_LINEAR_RGB, + IB_PROFILE_LINEAR_RGB, + false, + w, + h, + x, + ibuf->x); + } + + if (scaled) { + /* Slower update where we first have to scale the input pixels. */ + gpu_texture_update_scaled(rect, rect_float, ibuf->x, ibuf->y, x, y, w, h); } else { - VerifyThreadData data; - data.ibuf = ibuf; - data.srgb_frect = srgb_frect; - IMB_processor_apply_threaded_scanlines(ibuf->y, verify_thread_do, &data); + /* Fast update at same resolution. */ + gpu_texture_update_unscaled(rect, rect_float, x, y, w, h, tex_stride, tex_offset); + } + + /* Free buffers if needed. */ + if (rect && rect != (uchar *)ibuf->rect) { + MEM_freeN(rect); + } + if (rect_float && rect_float != ibuf->rect_float) { + MEM_freeN(rect_float); } } -GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget, bool is_data) +GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget) { if (ima == NULL) { return NULL; @@ -286,62 +466,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget return *tex; } - /* flag to determine whether deep format is used */ - bool use_high_bit_depth = false, do_color_management = false; - - if (ibuf->rect_float) { - use_high_bit_depth = true; - - /* TODO unneeded when float images are correctly treated as linear always */ - if (!is_data) { - do_color_management = true; - } - } - - const int rectw = ibuf->x; - const int recth = ibuf->y; - uint *rect = ibuf->rect; - float *frect = NULL; - float *srgb_frect = NULL; - - if (use_high_bit_depth) { - if (do_color_management) { - frect = srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(*srgb_frect) * 4, - "floar_buf_col_cor"); - gpu_verify_high_bit_srgb_buffer(srgb_frect, ibuf); - } - else { - frect = ibuf->rect_float; - } - } - - const bool mipmap = GPU_get_mipmap(); - -#ifdef WITH_DDS - if (ibuf->ftype == IMB_FTYPE_DDS) { - GPU_create_gl_tex_compressed(&bindcode, rect, rectw, recth, textarget, mipmap, ima, ibuf); - } - else -#endif - { - GPU_create_gl_tex( - &bindcode, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima); - } - - /* mark as non-color data texture */ - if (bindcode) { - if (is_data) { - ima->gpuflag |= IMA_GPU_IS_DATA; - } - else { - ima->gpuflag &= ~IMA_GPU_IS_DATA; - } - } - - /* clean up */ - if (srgb_frect) { - MEM_freeN(srgb_frect); - } + bindcode = gpu_texture_create_from_ibuf(ima, ibuf, textarget); BKE_image_release_ibuf(ima, ibuf, NULL); @@ -349,15 +474,14 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget return *tex; } -static void **gpu_gen_cube_map( - uint *rect, float *frect, int rectw, int recth, bool use_high_bit_depth) +static void **gpu_gen_cube_map(uint *rect, float *frect, int rectw, int recth) { - size_t block_size = use_high_bit_depth ? sizeof(float[4]) : sizeof(uchar[4]); + size_t block_size = frect ? sizeof(float[4]) : sizeof(uchar[4]); void **sides = NULL; int h = recth / 2; int w = rectw / 3; - if ((use_high_bit_depth && frect == NULL) || (!use_high_bit_depth && rect == NULL) || w != h) { + if (w != h) { return sides; } @@ -376,7 +500,7 @@ static void **gpu_gen_cube_map( * | NegZ | PosZ | PosY | * |______|______|______| */ - if (use_high_bit_depth) { + if (frect) { float(*frectb)[4] = (float(*)[4])frect; float(**fsides)[4] = (float(**)[4])sides; @@ -430,7 +554,7 @@ void GPU_create_gl_tex(uint *bind, int recth, int textarget, bool mipmap, - bool use_high_bit_depth, + bool use_srgb, Image *ima) { ImBuf *ibuf = NULL; @@ -441,7 +565,7 @@ void GPU_create_gl_tex(uint *bind, rectw = smaller_power_of_2_limit(rectw); recth = smaller_power_of_2_limit(recth); - if (use_high_bit_depth) { + if (frect) { ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy); IMB_scaleImBuf(ibuf, rectw, recth); @@ -459,12 +583,15 @@ void GPU_create_gl_tex(uint *bind, glGenTextures(1, (GLuint *)bind); glBindTexture(textarget, *bind); + GLenum internal_format = (frect) ? GL_RGBA16F : (use_srgb) ? GL_SRGB8_ALPHA8 : GL_RGBA8; + if (textarget == GL_TEXTURE_2D) { - if (use_high_bit_depth) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); + if (frect) { + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glTexImage2D( + GL_TEXTURE_2D, 0, internal_format, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); @@ -484,15 +611,14 @@ void GPU_create_gl_tex(uint *bind, int w = rectw / 3, h = recth / 2; if (h == w && is_power_of_2_i(h) && !is_over_resolution_limit(textarget, h, w)) { - void **cube_map = gpu_gen_cube_map(rect, frect, rectw, recth, use_high_bit_depth); - GLenum informat = use_high_bit_depth ? GL_RGBA16F : GL_RGBA8; - GLenum type = use_high_bit_depth ? GL_FLOAT : GL_UNSIGNED_BYTE; + void **cube_map = gpu_gen_cube_map(rect, frect, rectw, recth); + GLenum type = frect ? GL_FLOAT : GL_UNSIGNED_BYTE; if (cube_map) { for (int i = 0; i < 6; i++) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, - informat, + internal_format, w, h, 0, @@ -617,14 +743,14 @@ void GPU_create_gl_tex_compressed( #ifndef WITH_DDS (void)ibuf; /* Fall back to uncompressed if DDS isn't enabled */ - GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima); + GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, true, ima); #else glGenTextures(1, (GLuint *)bind); glBindTexture(textarget, *bind); if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf) == 0) { glDeleteTextures(1, (GLuint *)bind); - GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima); + GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, true, ima); } glBindTexture(textarget, 0); @@ -680,146 +806,20 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap) } } -/* check if image has been downscaled and do scaled partial update */ -static bool gpu_check_scaled_image( - ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h) -{ - if (is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) { - int x_limit = smaller_power_of_2_limit(ibuf->x); - int y_limit = smaller_power_of_2_limit(ibuf->y); - - float xratio = x_limit / (float)ibuf->x; - float yratio = y_limit / (float)ibuf->y; - - /* find new width, height and x,y gpu texture coordinates */ - - /* take ceiling because we will be losing 1 pixel due to rounding errors in x,y... */ - int rectw = (int)ceil(xratio * w); - int recth = (int)ceil(yratio * h); - - x *= xratio; - y *= yratio; - - /* ...but take back if we are over the limit! */ - if (rectw + x > x_limit) { - rectw--; - } - if (recth + y > y_limit) { - recth--; - } - - GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); - - /* float rectangles are already continuous in memory so we can use IMB_scaleImBuf */ - if (frect) { - ImBuf *ibuf_scale = IMB_allocFromBuffer(NULL, frect, w, h); - IMB_scaleImBuf(ibuf_scale, rectw, recth); - - glTexSubImage2D( - GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, GL_FLOAT, ibuf_scale->rect_float); - - IMB_freeImBuf(ibuf_scale); - } - /* byte images are not continuous in memory so do manual interpolation */ - else { - uchar *scalerect = MEM_mallocN(rectw * recth * sizeof(*scalerect) * 4, "scalerect"); - uint *p = (uint *)scalerect; - int i, j; - float inv_xratio = 1.0f / xratio; - float inv_yratio = 1.0f / yratio; - for (i = 0; i < rectw; i++) { - float u = (x + i) * inv_xratio; - for (j = 0; j < recth; j++) { - float v = (y + j) * inv_yratio; - bilinear_interpolation_color_wrap(ibuf, (uchar *)(p + i + j * (rectw)), NULL, u, v); - } - } - - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, scalerect); - - MEM_freeN(scalerect); - } - - if (GPU_get_mipmap()) { - glGenerateMipmap(GL_TEXTURE_2D); - } - else { - ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; - } - - GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); - - return true; - } - - return false; -} - void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, int h) { ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if ((ima->gputexture[TEXTARGET_TEXTURE_2D] == NULL) || (ibuf == NULL) || (w == 0) || (h == 0)) { - /* these cases require full reload still */ + /* Full reload of texture. */ GPU_free_image(ima); } else { - /* for the special case, we can do a partial update - * which is much quicker for painting */ - GLint row_length, skip_pixels, skip_rows; - - /* if color correction is needed, we must update the part that needs updating. */ - if (ibuf->rect_float) { - float *buffer = MEM_mallocN(w * h * sizeof(float) * 4, "temp_texpaint_float_buf"); - bool is_data = (ima->gpuflag & IMA_GPU_IS_DATA) != 0; - IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data); - - if (gpu_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) { - MEM_freeN(buffer); - BKE_image_release_ibuf(ima, ibuf, NULL); - return; - } - - GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer); - - MEM_freeN(buffer); - - if (GPU_get_mipmap()) { - glGenerateMipmap(GL_TEXTURE_2D); - } - else { - ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; - } - - GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); - - BKE_image_release_ibuf(ima, ibuf, NULL); - return; - } - - if (gpu_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) { - BKE_image_release_ibuf(ima, ibuf, NULL); - return; - } - + /* Partial update of texture. */ GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); - glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); - glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); - glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); - glPixelStorei(GL_UNPACK_SKIP_ROWS, y); - - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); - glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); + gpu_texture_update_from_ibuf(ibuf, x, y, w, h); - /* see comment above as to why we are using gpu mipmap generation here */ if (GPU_get_mipmap()) { glGenerateMipmap(GL_TEXTURE_2D); } @@ -1242,7 +1242,7 @@ static void gpu_free_image_immediate(Image *ima) } } - ima->gpuflag &= ~(IMA_GPU_MIPMAP_COMPLETE | IMA_GPU_IS_DATA); + ima->gpuflag &= ~(IMA_GPU_MIPMAP_COMPLETE); } void GPU_free_image(Image *ima) diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 1a668a48eed..de9ed56abf5 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -231,6 +231,12 @@ ListBase *GPU_material_get_inputs(GPUMaterial *material) return &material->inputs; } +/* Return can be NULL if it's a world material. */ +Material *GPU_material_get_material(GPUMaterial *material) +{ + return material->ma; +} + GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material) { return material->ubo; @@ -597,15 +603,6 @@ eGPUMaterialStatus GPU_material_status(GPUMaterial *mat) /* Code generation */ -bool GPU_material_do_color_management(GPUMaterial *mat) -{ - if (!BKE_scene_check_color_management_enabled(mat->scene)) { - return false; - } - - return true; -} - bool GPU_material_use_domain_surface(GPUMaterial *mat) { return (mat->domain & GPU_DOMAIN_SURFACE); @@ -646,6 +643,7 @@ GPUMaterial *GPU_material_from_nodetree_find(ListBase *gpumaterials, * so only do this when they are needed. */ GPUMaterial *GPU_material_from_nodetree(Scene *scene, + struct Material *ma, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, @@ -664,6 +662,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene, /* allocate material */ GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"); + mat->ma = ma; mat->scene = scene; mat->engine_type = engine_type; mat->options = options; diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c index 5d65861c1e2..cc89da19705 100644 --- a/source/blender/gpu/intern/gpu_matrix.c +++ b/source/blender/gpu/intern/gpu_matrix.c @@ -502,19 +502,13 @@ static void gpu_mul_invert_projmat_m4_unmapped_v3(const float projmat[4][4], flo co[2] *= -1; } -bool GPU_matrix_unproject(const float win[3], - const float model[4][4], - const float proj[4][4], - const int view[4], - float world[3]) +void GPU_matrix_unproject_model_inverted(const float win[3], + const float model_inverted[4][4], + const float proj[4][4], + const int view[4], + float world[3]) { float in[3]; - float viewinv[4][4]; - - if (!invert_m4_m4(viewinv, model)) { - zero_v3(world); - return false; - } copy_v3_v3(in, win); @@ -523,8 +517,22 @@ bool GPU_matrix_unproject(const float win[3], in[1] = (in[1] - view[1]) / view[3]; gpu_mul_invert_projmat_m4_unmapped_v3(proj, in); - mul_v3_m4v3(world, viewinv, in); + mul_v3_m4v3(world, model_inverted, in); +} +bool GPU_matrix_unproject(const float win[3], + const float model[4][4], + const float proj[4][4], + const int view[4], + float world[3]) +{ + float model_inverted[4][4]; + + if (!invert_m4_m4(model_inverted, model)) { + zero_v3(world); + return false; + } + GPU_matrix_unproject_model_inverted(win, model_inverted, proj, view, world); return true; } diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c index 3fbc24d6089..56f9ef69221 100644 --- a/source/blender/gpu/intern/gpu_select_sample_query.c +++ b/source/blender/gpu/intern/gpu_select_sample_query.c @@ -104,8 +104,11 @@ void gpu_select_query_begin( /* occlusion queries operates on fragments that pass tests and since we are interested on all * objects in the view frustum independently of their order, we need to disable the depth test */ if (mode == GPU_SELECT_ALL) { - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); + /* glQueries on Windows+Intel drivers only works with depth testing turned on. + * See T62947 for details */ + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + glDepthMask(GL_TRUE); } else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) { glClear(GL_DEPTH_BUFFER_BIT); diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 3d5b0dda5e4..7201025ad8a 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -145,17 +145,8 @@ extern char datatoc_gpu_shader_selection_id_frag_glsl[]; extern char datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl[]; extern char datatoc_gpu_shader_2D_line_dashed_frag_glsl[]; extern char datatoc_gpu_shader_2D_line_dashed_geom_glsl[]; -extern char datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl[]; extern char datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl[]; -extern char datatoc_gpu_shader_edges_front_back_persp_vert_glsl[]; -extern char datatoc_gpu_shader_edges_front_back_persp_geom_glsl[]; -extern char datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl[]; -extern char datatoc_gpu_shader_edges_front_back_ortho_vert_glsl[]; -extern char datatoc_gpu_shader_edges_overlay_vert_glsl[]; -extern char datatoc_gpu_shader_edges_overlay_geom_glsl[]; -extern char datatoc_gpu_shader_edges_overlay_simple_geom_glsl[]; -extern char datatoc_gpu_shader_edges_overlay_frag_glsl[]; extern char datatoc_gpu_shader_text_vert_glsl[]; extern char datatoc_gpu_shader_text_geom_glsl[]; extern char datatoc_gpu_shader_text_frag_glsl[]; @@ -729,23 +720,28 @@ void GPU_shader_uniform_vector( return; } - if (length == 1) { - glUniform1fv(location, arraysize, value); - } - else if (length == 2) { - glUniform2fv(location, arraysize, value); - } - else if (length == 3) { - glUniform3fv(location, arraysize, value); - } - else if (length == 4) { - glUniform4fv(location, arraysize, value); - } - else if (length == 9) { - glUniformMatrix3fv(location, arraysize, 0, value); - } - else if (length == 16) { - glUniformMatrix4fv(location, arraysize, 0, value); + switch (length) { + case 1: + glUniform1fv(location, arraysize, value); + break; + case 2: + glUniform2fv(location, arraysize, value); + break; + case 3: + glUniform3fv(location, arraysize, value); + break; + case 4: + glUniform4fv(location, arraysize, value); + break; + case 9: + glUniformMatrix3fv(location, arraysize, 0, value); + break; + case 16: + glUniformMatrix4fv(location, arraysize, 0, value); + break; + default: + BLI_assert(0); + break; } } @@ -756,17 +752,22 @@ void GPU_shader_uniform_vector_int( return; } - if (length == 1) { - glUniform1iv(location, arraysize, value); - } - else if (length == 2) { - glUniform2iv(location, arraysize, value); - } - else if (length == 3) { - glUniform3iv(location, arraysize, value); - } - else if (length == 4) { - glUniform4iv(location, arraysize, value); + switch (length) { + case 1: + glUniform1iv(location, arraysize, value); + break; + case 2: + glUniform2iv(location, arraysize, value); + break; + case 3: + glUniform3iv(location, arraysize, value); + break; + case 4: + glUniform4iv(location, arraysize, value); + break; + default: + BLI_assert(0); + break; } } @@ -832,30 +833,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = { .vert = datatoc_gpu_shader_keyframe_diamond_vert_glsl, .frag = datatoc_gpu_shader_keyframe_diamond_frag_glsl, }, - /* This version is magical but slow! */ - [GPU_SHADER_EDGES_FRONT_BACK_PERSP] = - { - .vert = datatoc_gpu_shader_edges_front_back_persp_vert_glsl, - .geom = datatoc_gpu_shader_edges_front_back_persp_geom_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - [GPU_SHADER_EDGES_FRONT_BACK_ORTHO] = - { - .vert = datatoc_gpu_shader_edges_front_back_ortho_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - [GPU_SHADER_EDGES_OVERLAY_SIMPLE] = - { - .vert = datatoc_gpu_shader_3D_vert_glsl, - .geom = datatoc_gpu_shader_edges_overlay_simple_geom_glsl, - .frag = datatoc_gpu_shader_edges_overlay_frag_glsl, - }, - [GPU_SHADER_EDGES_OVERLAY] = - { - .vert = datatoc_gpu_shader_edges_overlay_vert_glsl, - .geom = datatoc_gpu_shader_edges_overlay_geom_glsl, - .frag = datatoc_gpu_shader_edges_overlay_frag_glsl, - }, [GPU_SHADER_SIMPLE_LIGHTING] = { .vert = datatoc_gpu_shader_3D_normal_vert_glsl, @@ -1322,28 +1299,8 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, GPUShader **sh_p = &builtin_shaders[sh_cfg][shader]; if (*sh_p == NULL) { - GPUShaderStages stages_legacy = {NULL}; const GPUShaderStages *stages = &builtin_shader_stages[shader]; - if (shader == GPU_SHADER_EDGES_FRONT_BACK_PERSP) { - /* TODO: remove after switch to core profile (maybe) */ - if (!GLEW_VERSION_3_2) { - stages_legacy.vert = datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl; - stages_legacy.frag = datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl; - stages = &stages_legacy; - } - } - else if (shader == GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR) { - /* Dashed need geometry shader, which are not supported by legacy OpenGL, - * fallback to solid lines. */ - /* TODO: remove after switch to core profile (maybe) */ - if (!GLEW_VERSION_3_2) { - stages_legacy.vert = datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl; - stages_legacy.frag = datatoc_gpu_shader_2D_line_dashed_frag_glsl; - stages = &stages_legacy; - } - } - /* common case */ if (sh_cfg == GPU_SHADER_CFG_DEFAULT) { *sh_p = GPU_shader_create( diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c index 698499af1ab..97dbb80d736 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.c +++ b/source/blender/gpu/intern/gpu_shader_interface.c @@ -61,13 +61,10 @@ static const char *BuiltinUniform_name(GPUUniformBuiltin u) [GPU_UNIFORM_VIEWPROJECTION_INV] = "ViewProjectionMatrixInverse", [GPU_UNIFORM_NORMAL] = "NormalMatrix", - [GPU_UNIFORM_NORMAL_INV] = "NormalMatrixInverse", - [GPU_UNIFORM_WORLDNORMAL] = "WorldNormalMatrix", [GPU_UNIFORM_CAMERATEXCO] = "CameraTexCoFactors", [GPU_UNIFORM_ORCO] = "OrcoTexCoFactors", [GPU_UNIFORM_COLOR] = "color", - [GPU_UNIFORM_EYE] = "eye", [GPU_UNIFORM_CALLID] = "callId", [GPU_UNIFORM_OBJECT_INFO] = "unfobjectinfo", diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index ad4831ed903..58d0dd5576f 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -1081,7 +1081,7 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap) /* this binds a texture, so that's why we restore it to 0 */ if (bindcode == 0) { GPU_create_gl_tex( - &bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], GL_TEXTURE_2D, mipmap, 0, NULL); + &bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], GL_TEXTURE_2D, mipmap, false, NULL); } if (tex) { tex->bindcode = bindcode; diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.c b/source/blender/gpu/intern/gpu_vertex_buffer.c index f9823c18723..2f854fe03ea 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer.c +++ b/source/blender/gpu/intern/gpu_vertex_buffer.c @@ -85,17 +85,24 @@ void GPU_vertbuf_init_with_format_ex(GPUVertBuf *verts, } } -void GPU_vertbuf_discard(GPUVertBuf *verts) +/** Same as discard but does not free. */ +void GPU_vertbuf_clear(GPUVertBuf *verts) { if (verts->vbo_id) { GPU_buf_free(verts->vbo_id); + verts->vbo_id = 0; #if VRAM_USAGE vbo_memory_usage -= GPU_vertbuf_size_get(verts); #endif } if (verts->data) { - MEM_freeN(verts->data); + MEM_SAFE_FREE(verts->data); } +} + +void GPU_vertbuf_discard(GPUVertBuf *verts) +{ + GPU_vertbuf_clear(verts); MEM_freeN(verts); } diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c index 388773afbbc..37e1f9cf9da 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.c +++ b/source/blender/gpu/intern/gpu_vertex_format.c @@ -58,12 +58,6 @@ void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src) { /* copy regular struct fields */ memcpy(dest, src, sizeof(GPUVertFormat)); - - for (uint i = 0; i < dest->attr_len; i++) { - for (uint j = 0; j < dest->attrs[i].name_len; j++) { - dest->attrs[i].name[j] = (char *)dest + (src->attrs[i].name[j] - ((char *)src)); - } - } } static GLenum convert_comp_type_to_gl(GPUVertCompType type) @@ -122,32 +116,20 @@ uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len) return format->stride * vertex_len; } -static const char *copy_attr_name(GPUVertFormat *format, const char *name, const char *suffix) +static uchar copy_attr_name(GPUVertFormat *format, const char *name) { /* strncpy does 110% of what we need; let's do exactly 100% */ - char *name_copy = format->names + format->name_offset; - uint available = GPU_VERT_ATTR_NAMES_BUF_LEN - format->name_offset; + uchar name_offset = format->name_offset; + char *name_copy = format->names + name_offset; + uint available = GPU_VERT_ATTR_NAMES_BUF_LEN - name_offset; bool terminated = false; for (uint i = 0; i < available; ++i) { const char c = name[i]; name_copy[i] = c; if (c == '\0') { - if (suffix) { - for (uint j = 0; j < available; ++j) { - const char s = suffix[j]; - name_copy[i + j] = s; - if (s == '\0') { - terminated = true; - format->name_offset += (i + j + 1); - break; - } - } - } - else { - terminated = true; - format->name_offset += (i + 1); - } + terminated = true; + format->name_offset += (i + 1); break; } } @@ -157,7 +139,7 @@ static const char *copy_attr_name(GPUVertFormat *format, const char *name, const #else (void)terminated; #endif - return name_copy; + return name_offset; } uint GPU_vertformat_attr_add(GPUVertFormat *format, @@ -196,7 +178,7 @@ uint GPU_vertformat_attr_add(GPUVertFormat *format, const uint attr_id = format->attr_len++; GPUVertAttr *attr = &format->attrs[attr_id]; - attr->name[attr->name_len++] = copy_attr_name(format, name, NULL); + attr->names[attr->name_len++] = copy_attr_name(format, name); attr->comp_type = comp_type; attr->gl_comp_type = convert_comp_type_to_gl(comp_type); attr->comp_len = (comp_type == GPU_COMP_I10) ? @@ -217,7 +199,7 @@ void GPU_vertformat_alias_add(GPUVertFormat *format, const char *alias) assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES); #endif format->name_len++; /* multiname support */ - attr->name[attr->name_len++] = copy_attr_name(format, alias, NULL); + attr->names[attr->name_len++] = copy_attr_name(format, alias); } int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name) @@ -225,7 +207,8 @@ int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name) for (int i = 0; i < format->attr_len; i++) { const GPUVertAttr *attr = &format->attrs[i]; for (int j = 0; j < attr->name_len; j++) { - if (STREQ(name, attr->name[j])) { + const char *attr_name = GPU_vertformat_attr_name_get(format, attr, j); + if (STREQ(name, attr_name)) { return i; } } @@ -233,41 +216,6 @@ int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name) return -1; } -void GPU_vertformat_triple_load(GPUVertFormat *format) -{ -#if TRUST_NO_ONE - assert(!format->packed); - assert(format->attr_len * 3 < GPU_VERT_ATTR_MAX_LEN); - assert(format->name_len + format->attr_len * 3 < GPU_VERT_ATTR_MAX_LEN); -#endif - - VertexFormat_pack(format); - - uint old_attr_len = format->attr_len; - for (uint a_idx = 0; a_idx < old_attr_len; ++a_idx) { - GPUVertAttr *attr = &format->attrs[a_idx]; - /* Duplicate attr twice */ - for (int i = 1; i < 3; ++i) { - GPUVertAttr *dst_attr = &format->attrs[format->attr_len]; - memcpy(dst_attr, attr, sizeof(GPUVertAttr)); - /* Increase offset to the next vertex. */ - dst_attr->offset += format->stride * i; - /* Only copy first name for now. */ - dst_attr->name_len = 0; - dst_attr->name[dst_attr->name_len++] = copy_attr_name( - format, attr->name[0], (i == 1) ? "1" : "2"); - format->attr_len++; - } - -#if TRUST_NO_ONE - assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES); -#endif - /* Add alias to first attr. */ - format->name_len++; - attr->name[attr->name_len++] = copy_attr_name(format, attr->name[0], "0"); - } -} - uint padding(uint offset, uint alignment) { const uint mod = offset % alignment; @@ -364,7 +312,6 @@ static uint calc_input_component_size(const GPUShaderInput *input) static void get_fetch_mode_and_comp_type(int gl_type, GPUVertCompType *r_comp_type, - uint *r_gl_comp_type, GPUVertFetchMode *r_fetch_mode) { switch (gl_type) { @@ -382,7 +329,6 @@ static void get_fetch_mode_and_comp_type(int gl_type, case GL_FLOAT_MAT4x2: case GL_FLOAT_MAT4x3: *r_comp_type = GPU_COMP_F32; - *r_gl_comp_type = GL_FLOAT; *r_fetch_mode = GPU_FETCH_FLOAT; break; case GL_INT: @@ -390,7 +336,6 @@ static void get_fetch_mode_and_comp_type(int gl_type, case GL_INT_VEC3: case GL_INT_VEC4: *r_comp_type = GPU_COMP_I32; - *r_gl_comp_type = GL_INT; *r_fetch_mode = GPU_FETCH_INT; break; case GL_UNSIGNED_INT: @@ -398,7 +343,6 @@ static void get_fetch_mode_and_comp_type(int gl_type, case GL_UNSIGNED_INT_VEC3: case GL_UNSIGNED_INT_VEC4: *r_comp_type = GPU_COMP_U32; - *r_gl_comp_type = GL_UNSIGNED_INT; *r_fetch_mode = GPU_FETCH_INT; break; default: @@ -424,15 +368,19 @@ void GPU_vertformat_from_interface(GPUVertFormat *format, const GPUShaderInterfa format->name_len++; /* multiname support */ format->attr_len++; + GPUVertCompType comp_type; + GPUVertFetchMode fetch_mode; + get_fetch_mode_and_comp_type(input->gl_type, &comp_type, &fetch_mode); + GPUVertAttr *attr = &format->attrs[input->location]; - attr->name[attr->name_len++] = copy_attr_name( - format, name_buffer + input->name_offset, NULL); + attr->names[attr->name_len++] = copy_attr_name(format, name_buffer + input->name_offset); attr->offset = 0; /* offsets & stride are calculated later (during pack) */ attr->comp_len = calc_input_component_size(input); attr->sz = attr->comp_len * 4; - get_fetch_mode_and_comp_type( - input->gl_type, &attr->comp_type, &attr->gl_comp_type, &attr->fetch_mode); + attr->fetch_mode = fetch_mode; + attr->comp_type = comp_type; + attr->gl_comp_type = convert_comp_type_to_gl(comp_type); } } } diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 558b3f025a8..b825819ceb4 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -27,7 +27,7 @@ #include "BLI_listbase.h" #include "BLI_rect.h" -#include "BLI_mempool.h" +#include "BLI_memblock.h" #include "BIF_gl.h" @@ -48,6 +48,8 @@ static const int default_fbl_len = (sizeof(DefaultFramebufferList)) / sizeof(void *); static const int default_txl_len = (sizeof(DefaultTextureList)) / sizeof(void *); +#define MAX_ENABLE_ENGINE 8 + /* Maximum number of simultaneous engine enabled at the same time. * Setting it lower than the real number will do lead to * higher VRAM usage due to sub-efficient buffer reuse. */ @@ -64,8 +66,11 @@ struct GPUViewport { int samples; int flag; - ListBase data; /* ViewportEngineData wrapped in LinkData */ - uint data_hash; /* If hash mismatch we free all ViewportEngineData in this viewport */ + /* If engine_handles mismatch we free all ViewportEngineData in this viewport */ + struct { + void *handle; + ViewportEngineData *data; + } engine_data[MAX_ENABLE_ENGINE]; DefaultFramebufferList *fbl; DefaultTextureList *txl; @@ -172,7 +177,6 @@ void GPU_viewport_clear_from_offscreen(GPUViewport *viewport) void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type) { - LinkData *ld = MEM_callocN(sizeof(LinkData), "LinkData"); ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData"); int fbl_len, txl_len, psl_len, stl_len; @@ -185,20 +189,25 @@ void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type) data->psl = MEM_callocN((sizeof(void *) * psl_len) + sizeof(PassList), "PassList"); data->stl = MEM_callocN((sizeof(void *) * stl_len) + sizeof(StorageList), "StorageList"); - ld->data = data; - BLI_addtail(&viewport->data, ld); + for (int i = 0; i < MAX_ENABLE_ENGINE; i++) { + if (viewport->engine_data[i].handle == NULL) { + viewport->engine_data[i].handle = engine_type; + viewport->engine_data[i].data = data; + return data; + } + } - return data; + BLI_assert(!"Too many draw engines enabled at the same time"); + return NULL; } static void gpu_viewport_engines_data_free(GPUViewport *viewport) { int fbl_len, txl_len, psl_len, stl_len; - LinkData *next; - for (LinkData *link = viewport->data.first; link; link = next) { - next = link->next; - ViewportEngineData *data = link->data; + for (int i = 0; i < MAX_ENABLE_ENGINE && viewport->engine_data[i].handle; i++) { + ViewportEngineData *data = viewport->engine_data[i].data; + DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, &psl_len, &stl_len); gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len); @@ -219,19 +228,20 @@ static void gpu_viewport_engines_data_free(GPUViewport *viewport) MEM_freeN(data); - BLI_remlink(&viewport->data, link); - MEM_freeN(link); + /* Mark as unused*/ + viewport->engine_data[i].handle = NULL; } gpu_viewport_texture_pool_free(viewport); } -void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type) +void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_handle) { - for (LinkData *link = viewport->data.first; link; link = link->next) { - ViewportEngineData *vdata = link->data; - if (vdata->engine_type == engine_type) { - return vdata; + BLI_assert(engine_handle != NULL); + + for (int i = 0; i < MAX_ENABLE_ENGINE; i++) { + if (viewport->engine_data[i].handle == engine_handle) { + return viewport->engine_data[i].data; } } return NULL; @@ -352,24 +362,22 @@ static void gpu_viewport_texture_pool_free(GPUViewport *viewport) BLI_freelistN(&viewport->tex_pool); } -bool GPU_viewport_engines_data_validate(GPUViewport *viewport, uint hash) +/* Takes an NULL terminated array of engine_handle. Returns true is data is still valid. */ +bool GPU_viewport_engines_data_validate(GPUViewport *viewport, void **engine_handle_array) { - bool dirty = false; - - if (viewport->data_hash != hash) { - gpu_viewport_engines_data_free(viewport); - dirty = true; + for (int i = 0; i < MAX_ENABLE_ENGINE && engine_handle_array[i]; i++) { + if (viewport->engine_data[i].handle != engine_handle_array[i]) { + gpu_viewport_engines_data_free(viewport); + return false; + } } - - viewport->data_hash = hash; - - return dirty; + return true; } void GPU_viewport_cache_release(GPUViewport *viewport) { - for (LinkData *link = viewport->data.first; link; link = link->next) { - ViewportEngineData *data = link->data; + for (int i = 0; i < MAX_ENABLE_ENGINE && viewport->engine_data[i].handle; i++) { + ViewportEngineData *data = viewport->engine_data[i].data; int psl_len; DRW_engine_viewport_data_size_get(data->engine_type, NULL, NULL, &psl_len, NULL); gpu_viewport_passes_free(data->psl, psl_len); @@ -468,8 +476,8 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect) (TextureList *)viewport->txl, default_txl_len); - for (LinkData *link = viewport->data.first; link; link = link->next) { - ViewportEngineData *data = link->data; + for (int i = 0; i < MAX_ENABLE_ENGINE && viewport->engine_data[i].handle; i++) { + ViewportEngineData *data = viewport->engine_data[i].data; DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, NULL, NULL); gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len); } @@ -593,13 +601,7 @@ static void gpu_viewport_storage_free(StorageList *stl, int stl_len) static void gpu_viewport_passes_free(PassList *psl, int psl_len) { - for (int i = 0; i < psl_len; i++) { - struct DRWPass *pass = psl->passes[i]; - if (pass) { - DRW_pass_free(pass); - psl->passes[i] = NULL; - } - } + memset(psl, 0, sizeof(struct DRWPass *) * psl_len); } /* Must be executed inside Drawmanager Opengl Context. */ @@ -618,28 +620,28 @@ void GPU_viewport_free(GPUViewport *viewport) MEM_freeN(viewport->txl); if (viewport->vmempool.calls != NULL) { - BLI_mempool_destroy(viewport->vmempool.calls); + BLI_memblock_destroy(viewport->vmempool.calls, NULL); } if (viewport->vmempool.states != NULL) { - BLI_mempool_destroy(viewport->vmempool.states); + BLI_memblock_destroy(viewport->vmempool.states, NULL); } if (viewport->vmempool.shgroups != NULL) { - BLI_mempool_destroy(viewport->vmempool.shgroups); + BLI_memblock_destroy(viewport->vmempool.shgroups, NULL); } if (viewport->vmempool.uniforms != NULL) { - BLI_mempool_destroy(viewport->vmempool.uniforms); + BLI_memblock_destroy(viewport->vmempool.uniforms, NULL); } if (viewport->vmempool.passes != NULL) { - BLI_mempool_destroy(viewport->vmempool.passes); + BLI_memblock_destroy(viewport->vmempool.passes, NULL); } if (viewport->vmempool.images != NULL) { - BLI_mempool_iter iter; + BLI_memblock_iter iter; GPUTexture **tex; - BLI_mempool_iternew(viewport->vmempool.images, &iter); - while ((tex = BLI_mempool_iterstep(&iter))) { + BLI_memblock_iternew(viewport->vmempool.images, &iter); + while ((tex = BLI_memblock_iterstep(&iter))) { GPU_texture_free(*tex); } - BLI_mempool_destroy(viewport->vmempool.images); + BLI_memblock_destroy(viewport->vmempool.images, NULL); } DRW_instance_data_list_free(viewport->idatalist); diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl deleted file mode 100644 index a71dfba575b..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl +++ /dev/null @@ -1,54 +0,0 @@ - -// Draw "fancy" wireframe, displaying front-facing, back-facing and -// silhouette lines differently. -// Mike Erwin, April 2015 - -uniform bool drawFront = true; -uniform bool drawBack = true; -uniform bool drawSilhouette = true; - -uniform vec4 frontColor; -uniform vec4 backColor; -uniform vec4 silhouetteColor; - -uniform vec3 eye; // direction we are looking - -uniform mat4 ModelViewProjectionMatrix; - -in vec3 pos; - -// normals of faces this edge joins (object coords) -in vec3 N1; -in vec3 N2; - -flat out vec4 finalColor; - -// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley - -// to discard an entire line, set both endpoints to nowhere -// and it won't produce any fragments -const vec4 nowhere = vec4(vec3(0.0), 1.0); - -void main() -{ - bool face_1_front = dot(N1, eye) > 0.0; - bool face_2_front = dot(N2, eye) > 0.0; - - vec4 position = ModelViewProjectionMatrix * vec4(pos, 1.0); - - if (face_1_front && face_2_front) { - // front-facing edge - gl_Position = drawFront ? position : nowhere; - finalColor = frontColor; - } - else if (face_1_front || face_2_front) { - // exactly one face is front-facing, silhouette edge - gl_Position = drawSilhouette ? position : nowhere; - finalColor = silhouetteColor; - } - else { - // back-facing edge - gl_Position = drawBack ? position : nowhere; - finalColor = backColor; - } -} diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl deleted file mode 100644 index 3de14704781..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl +++ /dev/null @@ -1,60 +0,0 @@ - -// Draw "fancy" wireframe, displaying front-facing, back-facing and -// silhouette lines differently. -// Mike Erwin, April 2015 - -// After working with this shader a while, convinced we should make -// separate shaders for perpective & ortho. (Oct 2016) - -// Due to perspective, the line segment's endpoints might disagree on -// whether the adjacent faces are front facing. This geometry shader -// decides which edge type to use if endpoints disagree. - -uniform mat4 ProjectionMatrix; - -uniform bool drawFront = true; -uniform bool drawBack = true; -uniform bool drawSilhouette = true; - -uniform vec4 frontColor; -uniform vec4 backColor; -uniform vec4 silhouetteColor; - -layout(lines) in; -layout(line_strip, max_vertices = 2) out; - -in vec4 MV_pos[]; -in float edgeClass[]; - -flat out vec4 finalColor; - -void emitLine(vec4 color) -{ - gl_Position = ProjectionMatrix * MV_pos[0]; - EmitVertex(); - gl_Position = ProjectionMatrix * MV_pos[1]; - finalColor = color; - EmitVertex(); - EndPrimitive(); -} - -void main() -{ - float finalEdgeClass = max(edgeClass[0], edgeClass[1]); - - if (finalEdgeClass > 0.0f) { - // front-facing edge - if (drawFront) - emitLine(frontColor); - } - else if (finalEdgeClass < 0.0f) { - // back-facing edge - if (drawBack) - emitLine(backColor); - } - else { - // exactly one face is front-facing, silhouette edge - if (drawSilhouette) - emitLine(silhouetteColor); - } -} diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl deleted file mode 100644 index ffd52a0a225..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl +++ /dev/null @@ -1,68 +0,0 @@ - -// Draw "fancy" wireframe, displaying front-facing, back-facing and -// silhouette lines differently. -// Mike Erwin, April 2015 - -// After working with this shader a while, convinced we should make -// separate shaders for perpective & ortho. (Oct 2016) - -// This shader is an imperfect stepping stone until all platforms are -// ready for geometry shaders. - -// Due to perspective, the line segment's endpoints might disagree on -// whether the adjacent faces are front facing. Need to use a geometry -// shader or pass in an extra position attribute (the other endpoint) -// to do this properly. - -uniform bool drawFront = true; -uniform bool drawBack = true; -uniform bool drawSilhouette = true; - -uniform vec4 frontColor; -uniform vec4 backColor; -uniform vec4 silhouetteColor; - -uniform mat4 ModelViewMatrix; -uniform mat4 ModelViewProjectionMatrix; -uniform mat3 NormalMatrix; - -in vec3 pos; - -// normals of faces this edge joins (object coords) -in vec3 N1; -in vec3 N2; - -flat out vec4 finalColor; - -// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley - -// to discard an entire line, set its color to invisible -// (must have GL_BLEND enabled, or discard in fragment shader) -const vec4 invisible = vec4(0.0); - -bool front(vec3 N) -{ - vec4 xformed = ModelViewMatrix * vec4(pos, 1.0); - return dot(NormalMatrix * N, normalize(-xformed.xyz)) > 0.0; -} - -void main() -{ - bool face_1_front = front(N1); - bool face_2_front = front(N2); - - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - - if (face_1_front && face_2_front) { - // front-facing edge - finalColor = drawFront ? frontColor : invisible; - } - else if (face_1_front || face_2_front) { - // exactly one face is front-facing, silhouette edge - finalColor = drawSilhouette ? silhouetteColor : invisible; - } - else { - // back-facing edge - finalColor = drawBack ? backColor : invisible; - } -} diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl deleted file mode 100644 index c8b722e1d7e..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl +++ /dev/null @@ -1,44 +0,0 @@ - -// Draw "fancy" wireframe, displaying front-facing, back-facing and -// silhouette lines differently. -// Mike Erwin, April 2015 - -// After working with this shader a while, convinced we should make -// separate shaders for perpective & ortho. (Oct 2016) - -// Due to perspective, the line segment's endpoints might disagree on -// whether the adjacent faces are front facing. We use a geometry -// shader to resolve this properly. - -uniform mat4 ModelViewMatrix; -uniform mat3 NormalMatrix; - -in vec3 pos; -in vec3 N1, N2; // normals of faces this edge joins (object coords) - -out vec4 MV_pos; -out float edgeClass; - -// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley - -bool front(vec3 N, vec3 eye) -{ - return dot(NormalMatrix * N, eye) > 0.0; -} - -void main() -{ - MV_pos = ModelViewMatrix * vec4(pos, 1.0); - - vec3 eye = normalize(-MV_pos.xyz); - - bool face_1_front = front(N1, eye); - bool face_2_front = front(N2, eye); - - if (face_1_front && face_2_front) - edgeClass = 1.0; // front-facing edge - else if (face_1_front || face_2_front) - edgeClass = 0.0; // exactly one face is front-facing, silhouette edge - else - edgeClass = -1.0; // back-facing edge -} diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl deleted file mode 100644 index 7b35f67dd54..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl +++ /dev/null @@ -1,21 +0,0 @@ - -#define SMOOTH 1 - -const float transitionWidth = 1.0; - -uniform vec4 fillColor = vec4(0); -uniform vec4 outlineColor = vec4(0, 0, 0, 1); - -noperspective in vec3 distanceToOutline; - -out vec4 FragColor; - -void main() -{ - float edgeness = min(min(distanceToOutline.x, distanceToOutline.y), distanceToOutline.z); -#if SMOOTH - FragColor = mix(outlineColor, fillColor, smoothstep(0, transitionWidth, edgeness)); -#else - FragColor = (edgeness <= 0) ? outlineColor : fillColor; -#endif -} diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl deleted file mode 100644 index 48fff1629fd..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl +++ /dev/null @@ -1,72 +0,0 @@ -layout(triangles) in; -layout(triangle_strip, max_vertices = 3) out; - -uniform float outlineWidth = 1.0; -uniform vec2 viewportSize; - -in vec4 pos_xformed[]; -in float widthModulator[]; - -noperspective out vec3 distanceToOutline; - -// project to screen space -vec2 proj(int axis) -{ - vec4 pos = pos_xformed[axis]; - return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; -} - -float dist(vec2 pos[3], int v) -{ - // current vertex position - vec2 vpos = pos[v]; - // endpoints of opposite edge - vec2 e1 = pos[(v + 1) % 3]; - vec2 e2 = pos[(v + 2) % 3]; - - float abs_det = length(cross(vec3(vpos - e1, 0), vec3(vpos - e2, 0))); // could simplify - return abs_det / distance(e2, e1); -} - -vec3 distance[3]; - -void clearEdge(int v) -{ - float distant = 10 * outlineWidth; - for (int i = 0; i < 3; ++i) - distance[i][v] += distant; -} - -void modulateEdge(int v) -{ - float offset = min(widthModulator[v], 1) * outlineWidth; - for (int i = 0; i < 3; ++i) - distance[i][v] -= offset; -} - -void main() -{ - vec2 pos[3] = vec2[3](proj(0), proj(1), proj(2)); - - for (int v = 0; v < 3; ++v) - distance[v] = vec3(0); - - for (int v = 0; v < 3; ++v) { - if (widthModulator[v] > 0) { - distance[v][v] = dist(pos, v); - modulateEdge(v); - } - } - - for (int v = 0; v < 3; ++v) - if (widthModulator[v] <= 0) - clearEdge(v); - - for (int v = 0; v < 3; ++v) { - gl_Position = pos_xformed[v]; - distanceToOutline = distance[v]; - EmitVertex(); - } - - EndPrimitive(); -} diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl deleted file mode 100644 index 12f5a2c7811..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl +++ /dev/null @@ -1,56 +0,0 @@ -layout(triangles) in; -layout(triangle_strip, max_vertices = 3) out; - -uniform float outlineWidth = 1.0; -uniform vec2 viewportSize; - -noperspective out vec3 distanceToOutline; - -// project to screen space -vec2 proj(int axis) -{ - vec4 pos = gl_in[axis].gl_Position; - return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; -} - -float dist(vec2 pos[3], int v) -{ - // current vertex position - vec2 vpos = pos[v]; - // endpoints of opposite edge - vec2 e1 = pos[(v + 1) % 3]; - vec2 e2 = pos[(v + 2) % 3]; - - float abs_det = length(cross(vec3(vpos - e1, 0), vec3(vpos - e2, 0))); // could simplify - return abs_det / distance(e2, e1); -} - -vec3 distance[3]; - -void modulateEdge(int v) -{ - float offset = 0.5 * outlineWidth; - for (int i = 0; i < 3; ++i) - distance[i][v] -= offset; -} - -void main() -{ - vec2 pos[3] = vec2[3](proj(0), proj(1), proj(2)); - - for (int v = 0; v < 3; ++v) - distance[v] = vec3(0); - - for (int v = 0; v < 3; ++v) { - distance[v][v] = dist(pos, v); - modulateEdge(v); - } - - for (int v = 0; v < 3; ++v) { - gl_Position = gl_in[v].gl_Position; - distanceToOutline = distance[v]; - EmitVertex(); - } - - EndPrimitive(); -} diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl deleted file mode 100644 index 33615ac36e5..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl +++ /dev/null @@ -1,14 +0,0 @@ - -uniform mat4 ModelViewProjectionMatrix; - -in vec3 pos; -in float edgeWidthModulator; - -out vec4 pos_xformed; -out float widthModulator; - -void main() -{ - pos_xformed = ModelViewProjectionMatrix * vec4(pos, 1.0); - widthModulator = edgeWidthModulator; -} diff --git a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl index d9e73f81c45..62a526cae49 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl @@ -26,21 +26,21 @@ out vec3 fCol; // TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley -bool front(mat3 NormalMatrix, vec3 N, vec3 eye) +bool front(mat3 normal_matrix, vec3 N, vec3 eye) { - return dot(NormalMatrix * N, eye) > 0.0; + return dot(normal_matrix * N, eye) > 0.0; } void main() { vec3 eye; - mat4 ModelViewMatrix = ViewMatrix * InstanceModelMatrix; + mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix; vec4 pos_4d = vec4(pos, 1.0); - MV_pos = ModelViewMatrix * pos_4d; + MV_pos = model_view_matrix * pos_4d; - mat3 NormalMatrix = transpose(inverse(mat3(ModelViewMatrix))); + mat3 normal_matrix = transpose(inverse(mat3(model_view_matrix))); /* if persp */ if (ProjectionMatrix[3][3] == 0.0) { @@ -50,8 +50,8 @@ void main() eye = vec3(0.0, 0.0, 1.0); } - bool face_1_front = front(NormalMatrix, N1, eye); - bool face_2_front = front(NormalMatrix, N2, eye); + bool face_1_front = front(normal_matrix, N1, eye); + bool face_2_front = front(normal_matrix, N2, eye); if (face_1_front && face_2_front) edgeClass = 1.0; // front-facing edge diff --git a/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl index 9b1a08d8d86..5b3922d7a72 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl @@ -1,5 +1,5 @@ -uniform mat4 ViewMatrix; +uniform mat4 ViewMatrixInverse; uniform mat4 ViewProjectionMatrix; /* ---- Instantiated Attrs ---- */ @@ -15,13 +15,12 @@ flat out vec4 finalColor; void main() { - mat4 ModelViewProjectionMatrix = ViewProjectionMatrix * InstanceModelMatrix; - /* This is slow and run per vertex, but it's still faster than - * doing it per instance on CPU and sending it on via instance attr. */ - mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); + gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(pos, 1.0)); - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - normal = NormalMatrix * nor; + /* This is slow and run per vertex, but it's still faster than + * doing it per instance on CPU and sending it on via instance attribute. */ + mat3 normal_mat = transpose(inverse(mat3(InstanceModelMatrix))); + normal = normalize((transpose(mat3(ViewMatrixInverse)) * (normal_mat * nor))); finalColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 1cbf58f9d16..94770aa2ebf 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -1,14 +1,4 @@ -uniform mat4 ModelViewMatrix; -uniform mat4 ModelViewMatrixInverse; -uniform mat3 NormalMatrix; -uniform mat3 NormalMatrixInverse; - -#ifndef USE_ATTR -uniform mat4 ModelMatrix; -uniform mat4 ModelMatrixInverse; -#endif - /* Converters */ float convert_rgba_to_float(vec4 color) @@ -119,38 +109,6 @@ void hsv_to_rgb(vec4 hsv, out vec4 outcol) outcol = vec4(rgb, hsv.w); } -float srgb_to_linearrgb(float c) -{ - if (c < 0.04045) - return (c < 0.0) ? 0.0 : c * (1.0 / 12.92); - else - return pow((c + 0.055) * (1.0 / 1.055), 2.4); -} - -float linearrgb_to_srgb(float c) -{ - if (c < 0.0031308) - return (c < 0.0) ? 0.0 : c * 12.92; - else - return 1.055 * pow(c, 1.0 / 2.4) - 0.055; -} - -void srgb_to_linearrgb(vec4 col_from, out vec4 col_to) -{ - col_to.r = srgb_to_linearrgb(col_from.r); - col_to.g = srgb_to_linearrgb(col_from.g); - col_to.b = srgb_to_linearrgb(col_from.b); - col_to.a = col_from.a; -} - -void linearrgb_to_srgb(vec4 col_from, out vec4 col_to) -{ - col_to.r = linearrgb_to_srgb(col_from.r); - col_to.g = linearrgb_to_srgb(col_from.g); - col_to.b = linearrgb_to_srgb(col_from.b); - col_to.a = col_from.a; -} - void color_to_normal_new_shading(vec3 color, out vec3 normal) { normal = vec3(2.0) * color - vec3(1.0); @@ -204,9 +162,9 @@ void direction_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) vout = (mat * vec4(vin, 0.0)).xyz; } -void mat3_mul(vec3 vin, mat3 mat, out vec3 vout) +void normal_transform_transposed_m4v3(vec3 vin, mat4 mat, out vec3 vout) { - vout = mat * vin; + vout = transpose(mat3(mat)) * vin; } void point_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) @@ -1276,6 +1234,8 @@ void node_bsdf_principled(vec4 base_color, float ior, float transmission, float transmission_roughness, + vec4 emission, + float alpha, vec3 N, vec3 CN, vec3 T, @@ -1355,6 +1315,8 @@ void node_bsdf_principled(vec4 base_color, # endif result.sss_data.rgb *= (1.0 - transmission); # endif + result.radiance += emission.rgb; + result.opacity = alpha; } void node_bsdf_principled_dielectric(vec4 base_color, @@ -1374,6 +1336,8 @@ void node_bsdf_principled_dielectric(vec4 base_color, float ior, float transmission, float transmission_roughness, + vec4 emission, + float alpha, vec3 N, vec3 CN, vec3 T, @@ -1403,6 +1367,8 @@ void node_bsdf_principled_dielectric(vec4 base_color, result.ssr_data = vec4(ssr_spec, roughness); result.ssr_normal = normal_encode(vN, viewCameraVec); result.ssr_id = int(ssr_id); + result.radiance += emission.rgb; + result.opacity = alpha; } void node_bsdf_principled_metallic(vec4 base_color, @@ -1422,6 +1388,8 @@ void node_bsdf_principled_metallic(vec4 base_color, float ior, float transmission, float transmission_roughness, + vec4 emission, + float alpha, vec3 N, vec3 CN, vec3 T, @@ -1442,6 +1410,8 @@ void node_bsdf_principled_metallic(vec4 base_color, result.ssr_data = vec4(ssr_spec, roughness); result.ssr_normal = normal_encode(vN, viewCameraVec); result.ssr_id = int(ssr_id); + result.radiance += emission.rgb; + result.opacity = alpha; } void node_bsdf_principled_clearcoat(vec4 base_color, @@ -1461,6 +1431,8 @@ void node_bsdf_principled_clearcoat(vec4 base_color, float ior, float transmission, float transmission_roughness, + vec4 emission, + float alpha, vec3 N, vec3 CN, vec3 T, @@ -1490,6 +1462,8 @@ void node_bsdf_principled_clearcoat(vec4 base_color, result.ssr_data = vec4(ssr_spec, roughness); result.ssr_normal = normal_encode(vN, viewCameraVec); result.ssr_id = int(ssr_id); + result.radiance += emission.rgb; + result.opacity = alpha; } void node_bsdf_principled_subsurface(vec4 base_color, @@ -1509,6 +1483,8 @@ void node_bsdf_principled_subsurface(vec4 base_color, float ior, float transmission, float transmission_roughness, + vec4 emission, + float alpha, vec3 N, vec3 CN, vec3 T, @@ -1563,6 +1539,8 @@ void node_bsdf_principled_subsurface(vec4 base_color, result.radiance += (out_diff + out_trans) * mixed_ss_base_color; # endif result.radiance += out_diff * out_sheen; + result.radiance += emission.rgb; + result.opacity = alpha; } void node_bsdf_principled_glass(vec4 base_color, @@ -1582,6 +1560,8 @@ void node_bsdf_principled_glass(vec4 base_color, float ior, float transmission, float transmission_roughness, + vec4 emission, + float alpha, vec3 N, vec3 CN, vec3 T, @@ -1616,6 +1596,8 @@ void node_bsdf_principled_glass(vec4 base_color, result.ssr_data = vec4(ssr_spec, roughness); result.ssr_normal = normal_encode(vN, viewCameraVec); result.ssr_id = int(ssr_id); + result.radiance += emission.rgb; + result.opacity = alpha; } void node_bsdf_translucent(vec4 color, vec3 N, out Closure result) @@ -1744,11 +1726,11 @@ void node_tex_environment_texco(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); + vec3 co = co_homogenous.xyz / co_homogenous.w; # if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) - worldvec = (ViewMatrixInverse * co).xyz; + worldvec = mat3(ViewMatrixInverse) * co; # else - worldvec = (ModelViewMatrixInverse * co).xyz; + worldvec = mat3(ModelMatrixInverse) * (mat3(ViewMatrixInverse) * co); # endif #endif } @@ -2015,18 +1997,13 @@ void tangent_orco_z(vec3 orco_in, out vec3 orco_out) orco_out = orco_in.yxz * vec3(-0.5, 0.5, 0.0) + vec3(0.25, -0.25, 0.0); } -void node_tangentmap(vec4 attr_tangent, mat4 toworld, out vec3 tangent) +void node_tangentmap(vec4 attr_tangent, out vec3 tangent) { - tangent = normalize((toworld * vec4(attr_tangent.xyz, 0.0)).xyz); + tangent = normalize(attr_tangent.xyz); } -void node_tangent(vec3 N, vec3 orco, mat4 objmat, mat4 toworld, out vec3 T) +void node_tangent(vec3 N, vec3 orco, mat4 objmat, out vec3 T) { -#ifndef VOLUMETRICS - N = normalize(gl_FrontFacing ? worldNormal : -worldNormal); -#else - N = (toworld * vec4(N, 0.0)).xyz; -#endif T = (objmat * vec4(orco, 0.0)).xyz; T = cross(N, normalize(cross(T, N))); } @@ -2070,7 +2047,7 @@ void node_geometry(vec3 I, true_normal = normal; # endif tangent_orco_z(orco, orco); - node_tangent(N, orco, objmat, toworld, tangent); + node_tangent(N, orco, objmat, tangent); parametric = vec3(barycentric, 0.0); backfacing = (gl_FrontFacing) ? 0.0 : 1.0; @@ -2092,9 +2069,8 @@ void generated_texco(vec3 I, vec3 attr_orco, out vec3 generated) } void node_tex_coord(vec3 I, - vec3 N, - mat4 viewinvmat, - mat4 obinvmat, + vec3 wN, + mat4 obmatinv, vec4 camerafac, vec3 attr_orco, vec3 attr_uv, @@ -2107,22 +2083,18 @@ void node_tex_coord(vec3 I, out vec3 reflection) { generated = attr_orco; - normal = normalize(NormalMatrixInverse * N); + normal = normalize(normal_world_to_object(wN)); uv = attr_uv; - object = (obinvmat * (viewinvmat * vec4(I, 1.0))).xyz; + object = (obmatinv * (ViewMatrixInverse * vec4(I, 1.0))).xyz; camera = vec3(I.xy, -I.z); vec4 projvec = ProjectionMatrix * vec4(I, 1.0); window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0); - - vec3 shade_I = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - vec3 view_reflection = reflect(shade_I, normalize(N)); - reflection = (viewinvmat * vec4(view_reflection, 0.0)).xyz; + reflection = reflect(cameraVec, normalize(wN)); } void node_tex_coord_background(vec3 I, vec3 N, - mat4 viewinvmat, - mat4 obinvmat, + mat4 obmatinv, vec4 camerafac, vec3 attr_orco, vec3 attr_uv, @@ -2141,11 +2113,7 @@ void node_tex_coord_background(vec3 I, co = normalize(co); -#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) vec3 coords = (ViewMatrixInverse * co).xyz; -#else - vec3 coords = (ModelViewMatrixInverse * co).xyz; -#endif generated = coords; normal = -coords; @@ -2346,6 +2314,21 @@ void node_tex_environment_empty(vec3 co, out vec4 color) /* 16bits floats limits. Higher/Lower values produce +/-inf. */ #define safe_color(a) (clamp(a, -65520.0, 65520.0)) +void tex_color_alpha_clear(vec4 color, out vec4 result) +{ + result = vec4(color.rgb, 1.0); +} + +void tex_color_alpha_unpremultiply(vec4 color, out vec4 result) +{ + if (color.a == 0.0 || color.a == 1.0) { + result = vec4(color.rgb, 1.0); + } + else { + result = vec4(color.rgb / color.a, 1.0); + } +} + void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alpha) { color = safe_color(texture(ima, co.xy)); @@ -3246,6 +3229,7 @@ void node_light_falloff( void node_object_info(mat4 obmat, vec4 info, + float mat_index, out vec3 location, out float object_index, out float material_index, @@ -3253,7 +3237,7 @@ void node_object_info(mat4 obmat, { location = obmat[3].xyz; object_index = info.x; - material_index = info.y; + material_index = mat_index; random = info.z; } @@ -3347,6 +3331,7 @@ void node_vector_displacement_tangent(vec4 vector, mat4 viewmat, out vec3 result) { + /* TODO(fclem) this is broken. revisit latter. */ vec3 N_object = normalize(((vec4(normal, 0.0) * viewmat) * obmat).xyz); vec3 T_object = normalize(((vec4(tangent.xyz, 0.0) * viewmat) * obmat).xyz); vec3 B_object = tangent.w * normalize(cross(N_object, T_object)); @@ -3391,11 +3376,11 @@ void node_output_world(Closure surface, Closure volume, out Closure result) #endif /* VOLUMETRICS */ } -#ifndef VOLUMETRICS /* TODO : clean this ifdef mess */ /* EEVEE output */ void world_normals_get(out vec3 N) { +#ifndef VOLUMETRICS # ifdef HAIR_SHADER vec3 B = normalize(cross(worldNormal, hairTangent)); float cos_theta; @@ -3413,8 +3398,12 @@ void world_normals_get(out vec3 N) # else N = gl_FrontFacing ? worldNormal : -worldNormal; # endif +#else + generated_from_orco(vec3(0.0), N); +#endif } +#ifndef VOLUMETRICS void node_eevee_specular(vec4 diffuse, vec4 specular, float roughness, diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 620f8984d9f..e683d38a0aa 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -58,6 +58,10 @@ void IMB_colormanagement_assign_rect_colorspace(struct ImBuf *ibuf, const char * const char *IMB_colormanagement_get_float_colorspace(struct ImBuf *ibuf); const char *IMB_colormanagement_get_rect_colorspace(struct ImBuf *ibuf); +bool IMB_colormanagement_space_is_data(struct ColorSpace *colorspace); +bool IMB_colormanagement_space_is_scene_linear(struct ColorSpace *colorspace); +bool IMB_colormanagement_space_is_srgb(struct ColorSpace *colorspace); + BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3]); BLI_INLINE unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char[3]); BLI_INLINE void IMB_colormangement_xyz_to_rgb(float rgb[3], const float xyz[3]); @@ -124,6 +128,14 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, struct ColorSpace *colorspace, bool predivide); +void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *rect, + const int x, + const int y, + const int width, + const int height, + const struct ImBuf *ibuf, + const bool compress_as_srgb); + void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3]); void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]); @@ -340,6 +352,7 @@ enum { COLOR_ROLE_DEFAULT_SEQUENCER, COLOR_ROLE_DEFAULT_BYTE, COLOR_ROLE_DEFAULT_FLOAT, + COLOR_ROLE_DATA, }; #include "intern/colormanagement_inline.c" diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index 2566016ffdd..a83f2d60b8c 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -48,6 +48,13 @@ typedef struct ColorSpace { bool is_invertible; bool is_data; + + /* Additional info computed only when needed since it's not cheap. */ + struct { + bool cached; + bool is_srgb; + bool is_scene_linear; + } info; } ColorSpace; typedef struct ColorManagedDisplay { diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index f31d4ede693..b460d268d38 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -65,6 +65,7 @@ #define DISPLAY_BUFFER_CHANNELS 4 /* ** list of all supported color spaces, displays and views */ +static char global_role_data[MAX_COLORSPACE_NAME]; static char global_role_scene_linear[MAX_COLORSPACE_NAME]; static char global_role_color_picking[MAX_COLORSPACE_NAME]; static char global_role_texture_painting[MAX_COLORSPACE_NAME]; @@ -488,6 +489,7 @@ static void colormanage_load_config(OCIO_ConstConfigRcPtr *config) const char *name; /* get roles */ + colormanage_role_color_space_name_get(config, global_role_data, OCIO_ROLE_DATA, NULL); colormanage_role_color_space_name_get( config, global_role_scene_linear, OCIO_ROLE_SCENE_LINEAR, NULL); colormanage_role_color_space_name_get( @@ -1260,6 +1262,8 @@ void IMB_colormanagement_validate_settings(const ColorManagedDisplaySettings *di const char *IMB_colormanagement_role_colorspace_name_get(int role) { switch (role) { + case COLOR_ROLE_DATA: + return global_role_data; case COLOR_ROLE_SCENE_LINEAR: return global_role_scene_linear; case COLOR_ROLE_COLOR_PICKING: @@ -1341,6 +1345,42 @@ const char *IMB_colormanagement_get_rect_colorspace(ImBuf *ibuf) } } +bool IMB_colormanagement_space_is_data(ColorSpace *colorspace) +{ + return (colorspace && colorspace->is_data); +} + +static void colormanage_ensure_srgb_scene_linear_info(ColorSpace *colorspace) +{ + if (!colorspace->info.cached) { + OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); + OCIO_ConstColorSpaceRcPtr *ocio_colorspace = OCIO_configGetColorSpace(config, + colorspace->name); + + bool is_scene_linear, is_srgb; + OCIO_colorSpaceIsBuiltin(config, ocio_colorspace, &is_scene_linear, &is_srgb); + + OCIO_colorSpaceRelease(ocio_colorspace); + OCIO_configRelease(config); + + colorspace->info.is_scene_linear = is_scene_linear; + colorspace->info.is_srgb = is_srgb; + colorspace->info.cached = true; + } +} + +bool IMB_colormanagement_space_is_scene_linear(ColorSpace *colorspace) +{ + colormanage_ensure_srgb_scene_linear_info(colorspace); + return (colorspace && colorspace->info.is_scene_linear); +} + +bool IMB_colormanagement_space_is_srgb(ColorSpace *colorspace) +{ + colormanage_ensure_srgb_scene_linear_info(colorspace); + return (colorspace && colorspace->info.is_srgb); +} + /*********************** Threaded display buffer transform routines *************************/ typedef struct DisplayBufferThread { @@ -2111,6 +2151,57 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, } } +void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer, + const int offset_x, + const int offset_y, + const int width, + const int height, + const struct ImBuf *ibuf, + const bool compress_as_srgb) +{ + /* Convert byte buffer for texture storage on the GPU. These have builtin + * support for converting sRGB to linear, which allows us to store textures + * without precision or performance loss at minimal memory usage. */ + BLI_assert(ibuf->rect && ibuf->rect_float == NULL); + + OCIO_ConstProcessorRcPtr *processor = NULL; + if (compress_as_srgb && ibuf->rect_colorspace && + !IMB_colormanagement_space_is_srgb(ibuf->rect_colorspace)) { + processor = colorspace_to_scene_linear_processor(ibuf->rect_colorspace); + } + + /* TODO(brecht): make this multithreaded, or at least process in batches. */ + const unsigned char *in_buffer = (unsigned char *)ibuf->rect; + + for (int y = 0; y < height; y++) { + const size_t in_offset = (offset_y + y) * ibuf->x + offset_x; + const size_t out_offset = y * width; + const unsigned char *in = in_buffer + in_offset * 4; + unsigned char *out = out_buffer + out_offset * 4; + + if (processor) { + /* Convert to scene linear, to sRGB and premultiply. */ + for (int x = 0; x < width; x++, in += 4, out += 4) { + float pixel[4]; + rgba_uchar_to_float(pixel, in); + OCIO_processorApplyRGB(processor, pixel); + linearrgb_to_srgb_v3_v3(pixel, pixel); + mul_v3_fl(pixel, pixel[3]); + rgba_float_to_uchar(out, pixel); + } + } + else { + /* Premultiply only. */ + for (int x = 0; x < width; x++, in += 4, out += 4) { + out[0] = (in[0] * in[3]) >> 8; + out[1] = (in[1] * in[3]) >> 8; + out[2] = (in[2] * in[3]) >> 8; + out[3] = in[3]; + } + } + } +} + /* Conversion between color picking role. Typically we would expect such a * requirements: * - It is approximately perceptually linear, so that the HSV numbers and diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 14b3d97cef4..5a666653043 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -448,7 +448,9 @@ typedef enum ID_Type { /* No copy-on-write for these types. * Keep in sync with check_datablocks_copy_on_writable and deg_copy_on_write_is_needed */ -#define ID_TYPE_IS_COW(_id_type) (!ELEM(_id_type, ID_BR, ID_LS, ID_PAL, ID_IM)) +/* TODO(sergey): Make Sound copyable. It is here only because the code for dependency graph is + * being work in progress. */ +#define ID_TYPE_IS_COW(_id_type) (!ELEM(_id_type, ID_BR, ID_LS, ID_PAL, ID_IM, ID_SO)) #ifdef GS # undef GS @@ -602,10 +604,6 @@ typedef enum IDRecalcFlag { */ ID_RECALC_COPY_ON_WRITE = (1 << 13), - /* Sequences in the sequencer did change. - * Use this tag with a scene ID which owns the sequences. */ - ID_RECALC_SEQUENCER = (1 << 14), - /*************************************************************************** * Pseudonyms, to have more semantic meaning in the actual code without * using too much low-level and implementation specific tags. */ diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index c524f50ff52..c8a76791cef 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -512,6 +512,12 @@ typedef enum ePose_Flags { POSE_FLAG_DEPRECATED = (1 << 6), /* deprecated. */ /* pose constraint flags needs to be updated */ POSE_CONSTRAINTS_NEED_UPDATE_FLAGS = (1 << 7), + /* Use auto IK in pose mode */ + POSE_AUTO_IK = (1 << 8), + /* Use x-axis mirror in pose mode */ + POSE_MIRROR_EDIT = (1 << 9), + /* Use relative mirroring in mirror mode */ + POSE_MIRROR_RELATIVE = (1 << 10), } ePose_Flags; /* IK Solvers ------------------------------------ */ diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index c76d4895b25..ecf587301c7 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -357,6 +357,7 @@ typedef enum eDriverTarget_TransformChannels { DTAR_TRANSCHAN_SCALEX, DTAR_TRANSCHAN_SCALEY, DTAR_TRANSCHAN_SCALEZ, + DTAR_TRANSCHAN_SCALE_AVG, MAX_DTAR_TRANSCHAN_TYPES, } eDriverTarget_TransformChannels; @@ -969,6 +970,8 @@ typedef enum eInsertKeyFlags { INSERTKEY_DRIVER = (1 << 8), /** for cyclic FCurves, adjust key timing to preserve the cycle period and flow */ INSERTKEY_CYCLE_AWARE = (1 << 9), + /** don't create new F-Curves (implied by INSERTKEY_REPLACE) */ + INSERTKEY_AVAILABLE = (1 << 10), } eInsertKeyFlags; /* ************************************************ */ diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index 483ff3483d3..b18ab503e94 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -104,7 +104,11 @@ typedef struct bArmature { struct AnimData *adt; ListBase bonebase; - ListBase chainbase; + + /** Ghash for quicker lookups of bones by name. */ + struct GHash *bonehash; + void *_pad1; + /** Editbone listbase, we use pointer so we can check state. */ ListBase *edbo; @@ -144,9 +148,9 @@ typedef enum eArmature_Flag { ARM_POSEMODE = (1 << 4), ARM_FLAG_UNUSED_5 = (1 << 5), /* cleared */ ARM_DELAYDEFORM = (1 << 6), - ARM_FLAG_UNUSED_7 = (1 << 7), /* cleared */ + ARM_FLAG_UNUSED_7 = (1 << 7), ARM_MIRROR_EDIT = (1 << 8), - ARM_AUTO_IK = (1 << 9), + ARM_FLAG_UNUSED_9 = (1 << 9), /** made option negative, for backwards compat */ ARM_NO_CUSTOM = (1 << 10), /** draw custom colors */ diff --git a/source/blender/makesdna/DNA_collection_types.h b/source/blender/makesdna/DNA_collection_types.h index b935acd5a24..c7f3ef4156d 100644 --- a/source/blender/makesdna/DNA_collection_types.h +++ b/source/blender/makesdna/DNA_collection_types.h @@ -76,10 +76,10 @@ typedef struct Collection { /* Collection->flag */ enum { - COLLECTION_RESTRICT_VIEW = (1 << 0), /* Hidden in viewport. */ + COLLECTION_RESTRICT_VIEWPORT = (1 << 0), /* Disable in viewports. */ COLLECTION_RESTRICT_SELECT = (1 << 1), /* Not selectable in viewport. */ COLLECTION_DISABLED_DEPRECATED = (1 << 2), /* Not used anymore */ - COLLECTION_RESTRICT_RENDER = (1 << 3), /* Hidden in renders. */ + COLLECTION_RESTRICT_RENDER = (1 << 3), /* Disable in renders. */ COLLECTION_HAS_OBJECT_CACHE = (1 << 4), /* Runtime: object_cache is populated. */ COLLECTION_IS_MASTER = (1 << 5), /* Is master collection embedded in the scene. */ }; diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index f839f22ec9f..c09ea400f4c 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -289,14 +289,16 @@ typedef struct bLocateLikeConstraint { typedef struct bSizeLikeConstraint { struct Object *tar; int flag; - int reserved1; + float power; /** MAX_ID_NAME-2. */ char subtarget[64]; } bSizeLikeConstraint; /* Maintain Volume Constraint */ typedef struct bSameVolumeConstraint { - int flag; + char free_axis; + char mode; + char _pad[2]; float volume; } bSameVolumeConstraint; @@ -758,12 +760,22 @@ typedef enum eTransform_ToFrom { TRANS_SCALE = 2, } eTransform_ToFrom; -/* bSameVolumeConstraint.flag */ -typedef enum eSameVolume_Modes { +/* bSameVolumeConstraint.free_axis */ +typedef enum eSameVolume_Axis { SAMEVOL_X = 0, SAMEVOL_Y = 1, SAMEVOL_Z = 2, -} eSameVolume_Modes; +} eSameVolume_Axis; + +/* bSameVolumeConstraint.mode */ +typedef enum eSameVolume_Mode { + /* Strictly maintain the volume, overriding non-free axis scale. */ + SAMEVOL_STRICT = 0, + /* Maintain the volume when scale is uniform, pass non-uniform other axis scale through. */ + SAMEVOL_UNIFORM = 1, + /* Maintain the volume when scaled only on the free axis, pass other axis scale through. */ + SAMEVOL_SINGLE_AXIS = 2, +} eSameVolume_Mode; /* bActionConstraint.flag */ typedef enum eActionConstraint_Flags { @@ -894,6 +906,9 @@ typedef enum eSplineIK_Flags { /* for "volumetric" xz scale mode, limit the minimum or maximum scale values */ CONSTRAINT_SPLINEIK_USE_BULGE_MIN = (1 << 5), CONSTRAINT_SPLINEIK_USE_BULGE_MAX = (1 << 6), + + /* apply volume preservation over original scaling of the bone */ + CONSTRAINT_SPLINEIK_USE_ORIGINAL_SCALE = (1 << 7), } eSplineIK_Flags; /* bSplineIKConstraint->xzScaleMode */ diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index fec5f96b4f3..0aceeda20d5 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -191,8 +191,6 @@ enum { IMA_GPU_REFRESH = (1 << 0), /** All mipmap levels in OpenGL texture set? */ IMA_GPU_MIPMAP_COMPLETE = (1 << 1), - /** OpenGL image texture bound as non-color data. */ - IMA_GPU_IS_DATA = (1 << 2), }; /* ima->type and ima->source moved to BKE_image.h, for API */ diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index dd8adeaf153..5f64e3220b7 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -133,7 +133,7 @@ enum { LAYER_COLLECTION_EXCLUDE = (1 << 4), LAYER_COLLECTION_HOLDOUT = (1 << 5), LAYER_COLLECTION_INDIRECT_ONLY = (1 << 6), - LAYER_COLLECTION_RESTRICT_VIEW = (1 << 7), + LAYER_COLLECTION_HIDE = (1 << 7), }; /* Layer Collection->runtime_flag */ diff --git a/source/blender/makesdna/DNA_light_types.h b/source/blender/makesdna/DNA_light_types.h index 6bd118b7be9..5e881053910 100644 --- a/source/blender/makesdna/DNA_light_types.h +++ b/source/blender/makesdna/DNA_light_types.h @@ -66,6 +66,9 @@ typedef struct Light { short area_shape; float area_size, area_sizey, area_sizez; + float sun_angle; + char _pad3[4]; + /* texact is for buttons */ short texact, shadhalostep; diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 02f8245413d..d65a4896758 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -99,6 +99,9 @@ typedef struct MaterialGPencilStyle { /** Factor used to mix texture and stroke color. */ float mix_stroke_factor; + /** Mode used to align Dots and Boxes with stroke drawing path and object rotation */ + int alignment_mode; + char _pad[4]; } MaterialGPencilStyle; /* MaterialGPencilStyle->flag */ @@ -123,8 +126,6 @@ typedef enum eMaterialGPencilStyle_Flag { GP_STYLE_STROKE_SHOW = (1 << 8), /* Fill show main switch */ GP_STYLE_FILL_SHOW = (1 << 9), - /* Don't rotate dots/boxes */ - GP_STYLE_COLOR_LOCK_DOTS = (1 << 10), /* mix stroke texture */ GP_STYLE_STROKE_TEX_MIX = (1 << 11), } eMaterialGPencilStyle_Flag; @@ -315,7 +316,7 @@ enum { enum { MA_BL_HIDE_BACKFACE = (1 << 0), MA_BL_SS_REFRACTION = (1 << 1), - MA_BL_FLAG_UNUSED_2 = (1 << 2), /* cleared */ + MA_BL_CULL_BACKFACE = (1 << 2), MA_BL_TRANSLUCENCY = (1 << 3), }; @@ -347,4 +348,10 @@ enum { GP_STYLE_GRADIENT_RADIAL, }; +/* Grease Pencil Follow Drawing Modes */ +enum { + GP_STYLE_FOLLOW_PATH = 0, + GP_STYLE_FOLLOW_OBJ, + GP_STYLE_FOLLOW_FIXED, +}; #endif diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 226e1d2f841..3890fc63f3f 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -832,7 +832,7 @@ typedef struct NodeTexSky { typedef struct NodeTexImage { NodeTexBase base; ImageUser iuser; - int color_space; + int color_space DNA_DEPRECATED; int projection; float projection_blend; int interpolation; @@ -853,7 +853,7 @@ typedef struct NodeTexBrick { typedef struct NodeTexEnvironment { NodeTexBase base; ImageUser iuser; - int color_space; + int color_space DNA_DEPRECATED; int projection; int interpolation; char _pad[4]; @@ -1121,10 +1121,6 @@ typedef struct NodeCryptomatte { #define SHD_SKY_OLD 0 #define SHD_SKY_NEW 1 -/* image/environment texture */ -#define SHD_COLORSPACE_NONE 0 -#define SHD_COLORSPACE_COLOR 1 - /* environment texture */ #define SHD_PROJ_EQUIRECTANGULAR 0 #define SHD_PROJ_MIRROR_BALL 1 diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 1aeb4a2f4d2..a73c762e3bf 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -136,6 +136,10 @@ typedef struct Object_Runtime { /** Only used for drawing the parent/child help-line. */ float parent_display_origin[3]; + /** Selection id of this object; only available in the original object */ + int select_id; + char _pad1[4]; + /** Axis aligned boundbox (in localspace). */ struct BoundBox *bb; @@ -365,9 +369,7 @@ typedef struct Object { char empty_image_visibility_flag; char empty_image_depth; char empty_image_flag; - char _pad8[1]; - - int select_id; + char _pad8[5]; /** Contains data for levels of detail. */ ListBase lodlevels; @@ -600,7 +602,7 @@ enum { /* ob->restrictflag */ enum { - OB_RESTRICT_VIEW = 1 << 0, + OB_RESTRICT_VIEWPORT = 1 << 0, OB_RESTRICT_SELECT = 1 << 1, OB_RESTRICT_RENDER = 1 << 2, }; diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index e014de183e3..f5c2a518ef6 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -139,7 +139,7 @@ typedef struct Panel { struct uiLayout *layout; /** Defined as UI_MAX_NAME_STR. */ - char panelname[64], tabname[64]; + char panelname[64]; /** Panel name is identifier for restoring location. */ char drawname[64]; /** Offset within the region. */ @@ -155,8 +155,6 @@ typedef struct Panel { short snap; /** Panels are aligned according to increasing sort-order. */ int sortorder; - /** This panel is tabbed in *paneltab. */ - struct Panel *paneltab; /** Runtime for panel manipulation. */ void *activedata; /** Sub panels. */ diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 5240de4aff9..c21fa2ba64e 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -232,9 +232,6 @@ typedef struct Sequence { int cache_flag; int _pad2[3]; - - struct Sequence *orig_sequence; - void *_pad3; } Sequence; typedef struct MetaStack { diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 9e8ece0c6e8..20d4f7d96e4 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -247,7 +247,7 @@ typedef struct SpaceOutliner { short flag, outlinevis, storeflag, search_flags; int filter; char filter_state; - char _pad; + char show_restrict_flags; short filter_id_type; /** @@ -260,7 +260,7 @@ typedef struct SpaceOutliner { typedef enum eSpaceOutliner_Flag { SO_TESTBLOCKS = (1 << 0), SO_NEWSELECTED = (1 << 1), - SO_HIDE_RESTRICTCOLS = (1 << 2), + SO_FLAG_UNUSED_1 = (1 << 2), /* cleared */ SO_HIDE_KEYINGSETINFO = (1 << 3), SO_SKIP_SORT_ALPHA = (1 << 4), } eSpaceOutliner_Flag; @@ -309,6 +309,17 @@ typedef enum eSpaceOutliner_StateFilter { SO_FILTER_OB_ACTIVE = 3, } eSpaceOutliner_StateFilter; +/* SpaceOutliner.show_restrict_flags */ +typedef enum eSpaceOutliner_ShowRestrictFlag { + SO_RESTRICT_ENABLE = (1 << 0), + SO_RESTRICT_SELECT = (1 << 1), + SO_RESTRICT_HIDE = (1 << 2), + SO_RESTRICT_VIEWPORT = (1 << 3), + SO_RESTRICT_RENDER = (1 << 4), + SO_RESTRICT_HOLDOUT = (1 << 5), + SO_RESTRICT_INDIRECT_ONLY = (1 << 6), +} eSpaceOutliner_Restrict; + /* SpaceOutliner.outlinevis */ typedef enum eSpaceOutliner_Mode { SO_SCENES = 0, diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index e3773e8b670..2247ec2e6ee 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -38,11 +38,6 @@ struct ColorBand; #define MAX_STYLE_NAME 64 -#define GPU_VIEWPORT_QUALITY_FXAA 0.10f -#define GPU_VIEWPORT_QUALITY_TAA8 0.25f -#define GPU_VIEWPORT_QUALITY_TAA16 0.6f -#define GPU_VIEWPORT_QUALITY_TAA32 0.8f - /** default offered by Blender. * #uiFont.uifont_id */ typedef enum eUIFont_ID { @@ -189,6 +184,8 @@ typedef struct ThemeUI { char gizmo_b[4]; /* Icon Colors. */ + /** Scene items. */ + char icon_scene[4]; /** Collection items. */ char icon_collection[4]; /** Object items. */ @@ -199,6 +196,9 @@ typedef struct ThemeUI { char icon_modifier[4]; /** Shading related items. */ char icon_shading[4]; + /** Intensity of the border icons. >0 will render an border around themed + * icons. */ + float icon_border_intensity; } ThemeUI; /* try to put them all in one, if needed a special struct can be created as well @@ -283,6 +283,8 @@ typedef struct ThemeSpace { char cframe[4]; char time_keyframe[4], time_gp_keyframe[4]; char freestyle_edge_mark[4], freestyle_face_mark[4]; + char scrubbing_background[4]; + char _pad5[4]; char nurb_uline[4], nurb_vline[4]; char act_spline[4], nurb_sel_uline[4], nurb_sel_vline[4], lastsel_point[4]; @@ -535,6 +537,11 @@ typedef struct WalkNavigation { char _pad0[6]; } WalkNavigation; +typedef struct UserDef_Runtime { + char is_dirty; + char _pad0[7]; +} UserDef_Runtime; + typedef struct UserDef { /* UserDef has separate do-version handling, and can be read from other files */ int versionfile, subversionfile; @@ -542,8 +549,12 @@ typedef struct UserDef { /** #eUserPref_Flag. */ int flag; /** #eDupli_ID_Flags. */ - int dupflag; - int savetime; + short dupflag; + /** + * #eUserPref_PrefFlag preferences for the preferences. */ + char pref_flag; + char savetime; + char _pad4[4]; /** FILE_MAXDIR length. */ char tempdir[768]; char fontdir[768]; @@ -600,6 +611,7 @@ typedef struct UserDef { int dpi; /** Runtime, multiplier to scale UI elements based on DPI. */ float dpi_fac; + float inv_dpi_fac; /** Runtime, line width and point size based on DPI. */ float pixelsize; /** Deprecated, for forward compatibility. */ @@ -609,7 +621,7 @@ typedef struct UserDef { int scrollback; /** Node insert offset (aka auto-offset) margin, but might be useful for later stuff as well. */ char node_margin; - char _pad2[5]; + char _pad2[1]; /** #eUserpref_Translation_Flags. */ short transopts; short menuthreshold1, menuthreshold2; @@ -633,7 +645,7 @@ typedef struct UserDef { short undosteps; char _pad1[2]; int undomemory; - float gpu_viewport_quality; + float gpu_viewport_quality DNA_DEPRECATED; short gp_manhattendist, gp_euclideandist, gp_eraser; /** #eGP_UserdefSettings. */ short gp_settings; @@ -643,7 +655,7 @@ typedef struct UserDef { char _pad3[4]; short gizmo_flag, gizmo_size; short edit_studio_light; - short lookdev_ball_size; + short lookdev_sphere_size; short vbotimeout, vbocollectrate; short textimeout, texcollectrate; int memcachelimit; @@ -761,7 +773,12 @@ typedef struct UserDef { char factor_display_type; - char _pad5[3]; + char viewport_aa; + + char _pad5[2]; + + /** Runtime data (keep last). */ + UserDef_Runtime runtime; } UserDef; /* from blenkernel blender.c */ @@ -816,7 +833,7 @@ typedef enum eUserPref_Flag { USER_TOOLTIPS = (1 << 11), USER_TWOBUTTONMOUSE = (1 << 12), USER_NONUMPAD = (1 << 13), - USER_FLAG_UNUSED_14 = (1 << 14), /* cleared */ + USER_ADD_CURSORALIGNED = (1 << 14), USER_FILECOMPRESS = (1 << 15), USER_SAVE_PREVIEWS = (1 << 16), USER_CUSTOM_RANGE = (1 << 17), @@ -831,6 +848,10 @@ typedef enum eUserPref_Flag { USER_TOOLTIPS_PYTHON = (1 << 26), } eUserPref_Flag; +typedef enum eUserPref_PrefFlag { + USER_PREF_FLAG_SAVE = (1 << 0), +} eUserPref_PrefFlag; + /** #bPathCompare.flag */ typedef enum ePathCompare_Flag { USER_PATHCMP_GLOB = (1 << 0), diff --git a/source/blender/makesdna/DNA_view2d_types.h b/source/blender/makesdna/DNA_view2d_types.h index 0f25b47cb0b..8734a73c07a 100644 --- a/source/blender/makesdna/DNA_view2d_types.h +++ b/source/blender/makesdna/DNA_view2d_types.h @@ -151,10 +151,10 @@ enum { V2D_SCROLL_BOTTOM = (1 << 3), /* UNUSED = (1 << 4), */ V2D_SCROLL_HORIZONTAL = (V2D_SCROLL_TOP | V2D_SCROLL_BOTTOM), - /* scale markings - vertical */ - V2D_SCROLL_SCALE_VERTICAL = (1 << 5), - /* scale markings - horizontal */ - V2D_SCROLL_SCALE_HORIZONTAL = (1 << 6), + /* display vertical scale handles */ + V2D_SCROLL_VERTICAL_HANDLES = (1 << 5), + /* display horizontal scale handles */ + V2D_SCROLL_HORIZONTAL_HANDLES = (1 << 6), /* induce hiding of scrollbars - set by region drawing in response to size of region */ V2D_SCROLL_VERTICAL_HIDE = (1 << 7), V2D_SCROLL_HORIZONTAL_HIDE = (1 << 8), diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h index b9e0853b1ab..3aa0ff4b28a 100644 --- a/source/blender/makesdna/intern/dna_rename_defs.h +++ b/source/blender/makesdna/intern/dna_rename_defs.h @@ -58,12 +58,12 @@ DNA_STRUCT_RENAME(SpaceIpo, SpaceGraph) DNA_STRUCT_RENAME(SpaceOops, SpaceOutliner) DNA_STRUCT_RENAME_ELEM(BPoint, alfa, tilt) DNA_STRUCT_RENAME_ELEM(BezTriple, alfa, tilt) -DNA_STRUCT_RENAME_ELEM(Bone, scaleIn, scale_in_x) -DNA_STRUCT_RENAME_ELEM(Bone, scaleOut, scale_out_x) DNA_STRUCT_RENAME_ELEM(Bone, curveInX, curve_in_x) DNA_STRUCT_RENAME_ELEM(Bone, curveInY, curve_in_y) DNA_STRUCT_RENAME_ELEM(Bone, curveOutX, curve_out_x) DNA_STRUCT_RENAME_ELEM(Bone, curveOutY, curve_out_y) +DNA_STRUCT_RENAME_ELEM(Bone, scaleIn, scale_in_x) +DNA_STRUCT_RENAME_ELEM(Bone, scaleOut, scale_out_x) DNA_STRUCT_RENAME_ELEM(Camera, YF_dofdist, dof_distance) DNA_STRUCT_RENAME_ELEM(Camera, clipend, clip_end) DNA_STRUCT_RENAME_ELEM(Camera, clipsta, clip_start) @@ -77,12 +77,13 @@ DNA_STRUCT_RENAME_ELEM(ParticleSettings, dup_ob, instance_object) DNA_STRUCT_RENAME_ELEM(ParticleSettings, dupliweights, instance_weights) DNA_STRUCT_RENAME_ELEM(View3D, far, clip_end) DNA_STRUCT_RENAME_ELEM(View3D, near, clip_start) -DNA_STRUCT_RENAME_ELEM(bPoseChannel, scaleIn, scale_in_x) -DNA_STRUCT_RENAME_ELEM(bPoseChannel, scaleOut, scale_out_x) DNA_STRUCT_RENAME_ELEM(bPoseChannel, curveInX, curve_in_x) DNA_STRUCT_RENAME_ELEM(bPoseChannel, curveInY, curve_in_y) DNA_STRUCT_RENAME_ELEM(bPoseChannel, curveOutX, curve_out_x) DNA_STRUCT_RENAME_ELEM(bPoseChannel, curveOutY, curve_out_y) +DNA_STRUCT_RENAME_ELEM(bPoseChannel, scaleIn, scale_in_x) +DNA_STRUCT_RENAME_ELEM(bPoseChannel, scaleOut, scale_out_x) +DNA_STRUCT_RENAME_ELEM(bSameVolumeConstraint, flag, free_axis) DNA_STRUCT_RENAME_ELEM(bTheme, tact, space_action) DNA_STRUCT_RENAME_ELEM(bTheme, tbuts, space_properties) DNA_STRUCT_RENAME_ELEM(bTheme, tclip, space_clip) diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index 119186ff748..02aaef44a1f 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -96,6 +96,7 @@ extern const EnumPropertyItem rna_enum_keyblock_type_items[]; extern const EnumPropertyItem rna_enum_keyingset_path_grouping_items[]; extern const EnumPropertyItem rna_enum_keying_flag_items[]; +extern const EnumPropertyItem rna_enum_keying_flag_items_api[]; extern const EnumPropertyItem rna_enum_keyframe_paste_offset_items[]; extern const EnumPropertyItem rna_enum_keyframe_paste_merge_items[]; diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 0122587920c..2f063e4219a 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -2024,7 +2024,7 @@ static void rna_def_function_funcs_header(FILE *f, StructRNA *srna, FunctionDefR char funcname[2048]; rna_construct_wrapper_function_name( - funcname, sizeof(funcname), srna->identifier, func->identifier, NULL); + funcname, sizeof(funcname), srna->identifier, func->identifier, "func"); rna_generate_static_parameter_prototypes(f, srna, dfunc, funcname, 1); } @@ -2452,7 +2452,7 @@ static void rna_def_struct_function_call_impl_cpp(FILE *f, StructRNA *srna, Func int first = 1; rna_construct_wrapper_function_name( - funcname, sizeof(funcname), srna->identifier, func->identifier, NULL); + funcname, sizeof(funcname), srna->identifier, func->identifier, "func"); fprintf(f, "%s(", funcname); @@ -2615,7 +2615,7 @@ static void rna_def_function_wrapper_funcs(FILE *f, StructDefRNA *dsrna, Functio } rna_construct_wrapper_function_name( - funcname, sizeof(funcname), srna->identifier, func->identifier, NULL); + funcname, sizeof(funcname), srna->identifier, func->identifier, "func"); rna_generate_static_parameter_prototypes(f, srna, dfunc, funcname, 0); diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index 15429ec6b5e..6a5bae28cc1 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -72,6 +72,43 @@ const EnumPropertyItem rna_enum_keying_flag_items[] = { {0, NULL, 0, NULL, NULL}, }; +/* Contains additional flags suitable for use in Python API functions. */ +const EnumPropertyItem rna_enum_keying_flag_items_api[] = { + {INSERTKEY_NEEDED, + "INSERTKEY_NEEDED", + 0, + "Only Needed", + "Only insert keyframes where they're needed in the relevant F-Curves"}, + {INSERTKEY_MATRIX, + "INSERTKEY_VISUAL", + 0, + "Visual Keying", + "Insert keyframes based on 'visual transforms'"}, + {INSERTKEY_XYZ2RGB, + "INSERTKEY_XYZ_TO_RGB", + 0, + "XYZ=RGB Colors", + "Color for newly added transformation F-Curves (Location, Rotation, Scale) " + "and also Color is based on the transform axis"}, + {INSERTKEY_REPLACE, + "INSERTKEY_REPLACE", + 0, + "Replace Existing", + "Only replace existing keyframes"}, + {INSERTKEY_AVAILABLE, + "INSERTKEY_AVAILABLE", + 0, + "Only Available", + "Don't create F-Curves when they don't already exist"}, + {INSERTKEY_CYCLE_AWARE, + "INSERTKEY_CYCLE_AWARE", + 0, + "Cycle Aware Keying", + "When inserting into a curve with cyclic extrapolation, remap the keyframe inside " + "the cycle time range, and if changing an end key, also update the other one"}, + {0, NULL, 0, NULL, NULL}, +}; + #ifdef RNA_RUNTIME # include "BLI_math_base.h" @@ -1266,6 +1303,9 @@ static void rna_def_animdata(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Use NLA Tweak Mode", "Whether to enable or disable tweak mode in NLA"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, "rna_AnimData_update"); + + /* Animation Data API */ + RNA_api_animdata(srna); } /* --- */ diff --git a/source/blender/makesrna/intern/rna_animation_api.c b/source/blender/makesrna/intern/rna_animation_api.c index f201b8e6e99..e063e5de22c 100644 --- a/source/blender/makesrna/intern/rna_animation_api.c +++ b/source/blender/makesrna/intern/rna_animation_api.c @@ -37,6 +37,7 @@ # include "BKE_context.h" # include "BKE_report.h" +# include "BKE_nla.h" # include "ED_keyframing.h" @@ -59,6 +60,11 @@ static void rna_KeyingSet_context_refresh(KeyingSet *ks, bContext *C, ReportList } } +static float rna_AnimData_nla_tweak_strip_time_to_scene(AnimData *adt, float frame, bool invert) +{ + return BKE_nla_tweakedit_remap(adt, frame, invert ? NLATIME_CONVERT_UNMAP : NLATIME_CONVERT_MAP); +} + #else void RNA_api_keyingset(StructRNA *srna) @@ -75,4 +81,25 @@ void RNA_api_keyingset(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS); } +void RNA_api_animdata(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *parm; + + /* Convert between action time and scene time when tweaking a NLA strip. */ + func = RNA_def_function( + srna, "nla_tweak_strip_time_to_scene", "rna_AnimData_nla_tweak_strip_time_to_scene"); + RNA_def_function_ui_description(func, + "Convert a time value from the local time of the tweaked strip " + "to scene time, exactly as done by built-in key editing tools. " + "Returns the input time unchanged if not tweaking."); + parm = RNA_def_float( + func, "frame", 0.0, MINAFRAME, MAXFRAME, "", "Input time", MINAFRAME, MAXFRAME); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + RNA_def_boolean(func, "invert", false, "Invert", "Convert scene time to action time"); + parm = RNA_def_float( + func, "result", 0.0, MINAFRAME, MAXFRAME, "", "Converted time", MINAFRAME, MAXFRAME); + RNA_def_function_return(func, parm); +} + #endif diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 5461aaa0f1a..0eec5973ab0 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -575,6 +575,20 @@ static void rna_Armature_bones_next(CollectionPropertyIterator *iter) iter->valid = (internal->link != NULL); } +/* not essential, but much faster then the default lookup function */ +static int rna_Armature_bones_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) +{ + bArmature *arm = (bArmature *)ptr->data; + Bone *bone = BKE_armature_find_bone_name(arm, key); + if (bone) { + RNA_pointer_create(ptr->id.data, &RNA_Bone, bone, r_ptr); + return true; + } + else { + return false; + } +} + static bool rna_Armature_is_editmode_get(PointerRNA *ptr) { bArmature *arm = (bArmature *)ptr->id.data; @@ -621,9 +635,10 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) if (is_posebone == false) { prop = RNA_def_property(srna, "use_endroll_as_inroll", PROP_BOOLEAN, PROP_NONE); RNA_def_property_ui_text( - prop, "Inherit End Roll", "Use Roll Out of parent bone as Roll In of its children"); + prop, "Inherit End Roll", "Add Roll Out of the Start Handle bone to the Roll In value"); RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_ADD_PARENT_END_ROLL); - RNA_def_property_update(prop, 0, "rna_Armature_update_data"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_Armature_dependency_update"); } /* Curve X/Y Offsets */ @@ -1285,8 +1300,15 @@ static void rna_def_armature(BlenderRNA *brna) /* Collections */ prop = RNA_def_property(srna, "bones", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "bonebase", NULL); - RNA_def_property_collection_funcs( - prop, NULL, "rna_Armature_bones_next", NULL, NULL, NULL, NULL, NULL, NULL); + RNA_def_property_collection_funcs(prop, + NULL, + "rna_Armature_bones_next", + NULL, + NULL, + NULL, + NULL, + "rna_Armature_bones_lookup_string", + NULL); RNA_def_property_struct_type(prop, "Bone"); RNA_def_property_ui_text(prop, "Bones", ""); rna_def_armature_bones(brna, prop); @@ -1359,13 +1381,6 @@ static void rna_def_armature(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - prop = RNA_def_property(srna, "use_auto_ik", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_AUTO_IK); - RNA_def_property_ui_text( - prop, "Auto IK", "Add temporary IK constraints while grabbing bones in Pose Mode"); - RNA_def_property_update(prop, 0, "rna_Armature_redraw_data"); - RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); - prop = RNA_def_property(srna, "show_bone_custom_shapes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ARM_NO_CUSTOM); RNA_def_property_ui_text( diff --git a/source/blender/makesrna/intern/rna_collection.c b/source/blender/makesrna/intern/rna_collection.c index 501895eefc8..ae944f59a35 100644 --- a/source/blender/makesrna/intern/rna_collection.c +++ b/source/blender/makesrna/intern/rna_collection.c @@ -405,15 +405,15 @@ void RNA_def_collections(BlenderRNA *brna) RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1); - RNA_def_property_ui_text(prop, "Disable Select", "Disable collection for viewport selection"); + RNA_def_property_ui_text(prop, "Disable Selection", "Disable selection in viewport"); RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update"); prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_VIEW); + RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_VIEWPORT); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1); - RNA_def_property_ui_text(prop, "Disable Viewport", "Disable collection in viewport"); + RNA_def_property_ui_text(prop, "Disable in Viewports", "Globally disable in viewports"); RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update"); prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); @@ -421,7 +421,7 @@ void RNA_def_collections(BlenderRNA *brna) RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1); - RNA_def_property_ui_text(prop, "Disable Render", "Disable collection in renders"); + RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders"); RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update"); } diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 40ee069657c..8ba1f5440be 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -525,6 +525,22 @@ static char *rna_ColorManagedViewSettings_path(PointerRNA *UNUSED(ptr)) return BLI_strdup("view_settings"); } +static bool rna_ColorManagedColorspaceSettings_is_data_get(struct PointerRNA *ptr) +{ + ColorManagedColorspaceSettings *colorspace = (ColorManagedColorspaceSettings *)ptr->data; + const char *data_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DATA); + return STREQ(colorspace->name, data_name); +} + +static void rna_ColorManagedColorspaceSettings_is_data_set(struct PointerRNA *ptr, bool value) +{ + ColorManagedColorspaceSettings *colorspace = (ColorManagedColorspaceSettings *)ptr->data; + if (value) { + const char *data_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DATA); + STRNCPY(colorspace->name, data_name); + } +} + static int rna_ColorManagedColorspaceSettings_colorspace_get(struct PointerRNA *ptr) { ColorManagedColorspaceSettings *colorspace = (ColorManagedColorspaceSettings *)ptr->data; @@ -1227,6 +1243,7 @@ static void rna_def_colormanage(BlenderRNA *brna) prop = RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE); RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_enum_items(prop, color_space_items); RNA_def_property_enum_funcs(prop, "rna_ColorManagedColorspaceSettings_colorspace_get", @@ -1235,6 +1252,17 @@ static void rna_def_colormanage(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Input Color Space", "Color space of the image or movie on disk"); RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update"); + prop = RNA_def_property(srna, "is_data", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_funcs(prop, + "rna_ColorManagedColorspaceSettings_is_data_get", + "rna_ColorManagedColorspaceSettings_is_data_set"); + RNA_def_property_ui_text( + prop, + "Is Data", + "Treat image as non-color data without color management, like normal or displacement maps"); + RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update"); + // srna = RNA_def_struct(brna, "ColorManagedSequencerColorspaceSettings", NULL); RNA_def_struct_path_func(srna, "rna_ColorManagedSequencerColorspaceSettings_path"); diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index c1c235d497b..41ad94f6119 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -1327,6 +1327,13 @@ static void rna_def_constraint_size_like(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Copy Z", "Copy the target's Z scale"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "power", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "power"); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 3); + RNA_def_property_ui_text(prop, "Power", "Raise the target's scale to the specified power"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_OFFSET); RNA_def_property_ui_text(prop, "Offset", "Combine original scale with copied scale"); @@ -1346,13 +1353,34 @@ static void rna_def_constraint_same_volume(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - static const EnumPropertyItem volume_items[] = { + static const EnumPropertyItem axis_items[] = { {SAMEVOL_X, "SAMEVOL_X", 0, "X", ""}, {SAMEVOL_Y, "SAMEVOL_Y", 0, "Y", ""}, {SAMEVOL_Z, "SAMEVOL_Z", 0, "Z", ""}, {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem mode_items[] = { + {SAMEVOL_STRICT, + "STRICT", + 0, + "Strict", + "Volume is strictly preserved, overriding the scaling of non-free axes"}, + {SAMEVOL_UNIFORM, + "UNIFORM", + 0, + "Uniform", + "Volume is preserved when the object is scaled uniformly. " + "Deviations from uniform scale on non-free axes are passed through"}, + {SAMEVOL_SINGLE_AXIS, + "SINGLE_AXIS", + 0, + "Single Axis", + "Volume is preserved when the object is scaled only on the free axis. " + "Non-free axis scaling is passed through"}, + {0, NULL, 0, NULL, NULL}, + }; + srna = RNA_def_struct(brna, "MaintainVolumeConstraint", "Constraint"); RNA_def_struct_ui_text(srna, "Maintain Volume Constraint", @@ -1360,11 +1388,18 @@ static void rna_def_constraint_same_volume(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bSameVolumeConstraint", "data"); prop = RNA_def_property(srna, "free_axis", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "flag"); - RNA_def_property_enum_items(prop, volume_items); + RNA_def_property_enum_sdna(prop, NULL, "free_axis"); + RNA_def_property_enum_items(prop, axis_items); RNA_def_property_ui_text(prop, "Free Axis", "The free scaling axis of the object"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mode"); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text( + prop, "Mode", "The way the constraint treats original non-free axis scaling"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + prop = RNA_def_property(srna, "volume", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_range(prop, 0.001f, 100.0f); RNA_def_property_ui_text(prop, "Volume", "Volume of the bone at rest"); @@ -2576,6 +2611,13 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) "on top of the shape and scaling of the curve itself"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + /* take original scaling of the bone into account in volume preservation */ + prop = RNA_def_property(srna, "use_original_scale", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_USE_ORIGINAL_SCALE); + RNA_def_property_ui_text( + prop, "Use Original Scale", "Apply volume preservation over the original scaling"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + /* volume presevation for "volumetric" scale mode */ prop = RNA_def_property(srna, "bulge", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 100.f); diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 20fbbed572c..8e24e9a8364 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -890,9 +890,9 @@ StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRN srna->description = ""; /* may be overwritten later RNA_def_struct_translation_context */ srna->translation_context = BLT_I18NCONTEXT_DEFAULT_BPYRNA; - srna->flag |= STRUCT_UNDO; if (!srnafrom) { srna->icon = ICON_DOT; + srna->flag |= STRUCT_UNDO; } if (DefRNA.preprocess) { diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index c8df01a7dc7..63feceb4a8a 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -1534,6 +1534,7 @@ static void rna_def_fmodifier(BlenderRNA *brna) prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_enum_items(prop, rna_enum_fmodifier_type_items); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ACTION); RNA_def_property_ui_text(prop, "Type", "F-Curve Modifier Type"); /* settings */ @@ -1645,6 +1646,7 @@ static void rna_def_drivertarget(BlenderRNA *brna) {DTAR_TRANSCHAN_SCALEX, "SCALE_X", 0, "X Scale", ""}, {DTAR_TRANSCHAN_SCALEY, "SCALE_Y", 0, "Y Scale", ""}, {DTAR_TRANSCHAN_SCALEZ, "SCALE_Z", 0, "Z Scale", ""}, + {DTAR_TRANSCHAN_SCALE_AVG, "SCALE_AVG", 0, "Average Scale", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 34373e469c1..83ec33286f4 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -406,7 +406,8 @@ static void rna_Image_pixels_set(PointerRNA *ptr, const float *values) ((unsigned char *)ibuf->rect)[i] = unit_float_to_uchar_clamp(values[i]); } - ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID | IB_MIPMAP_INVALID; + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_MIPMAP_INVALID; + BKE_image_mark_dirty(ima, ibuf); if (!G.background) { GPU_free_image(ima); } diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index ca75f862b11..553dbeeb97b 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -211,69 +211,30 @@ static void rna_Image_scale(Image *image, ReportList *reports, int width, int he } } -static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int filter, int mag) +static int rna_Image_gl_load(Image *image, ReportList *reports, int frame) { - GPUTexture *tex = image->gputexture[TEXTARGET_TEXTURE_2D]; - int error = GL_NO_ERROR; - - if (tex) - return error; - ImageUser iuser = {NULL}; iuser.framenr = frame; iuser.ok = true; - void *lock; - ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); - - /* clean glError buffer */ - while (glGetError() != GL_NO_ERROR) { - } + GPUTexture *tex = GPU_texture_from_blender(image, &iuser, GL_TEXTURE_2D); - if (ibuf == NULL || ibuf->rect == NULL) { - BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); - BKE_image_release_ibuf(image, ibuf, lock); + if (tex == NULL) { + BKE_reportf(reports, RPT_ERROR, "Failed to load image texture '%s'", image->id.name + 2); return (int)GL_INVALID_OPERATION; } - unsigned int bindcode = 0; - GPU_create_gl_tex(&bindcode, - ibuf->rect, - ibuf->rect_float, - ibuf->x, - ibuf->y, - GL_TEXTURE_2D, - (filter != GL_NEAREST && filter != GL_LINEAR), - false, - image); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)mag); - - /* TODO(merwin): validate input (dimensions, filter, mag) before calling OpenGL - * instead of trusting input & testing for error after */ - error = glGetError(); - - if (error) { - glDeleteTextures(1, (GLuint *)&bindcode); - } - else { - image->gputexture[TEXTARGET_TEXTURE_2D] = GPU_texture_from_bindcode(GL_TEXTURE_2D, bindcode); - } - - BKE_image_release_ibuf(image, ibuf, lock); - - return error; + return GL_NO_ERROR; } -static int rna_Image_gl_touch(Image *image, ReportList *reports, int frame, int filter, int mag) +static int rna_Image_gl_touch(Image *image, ReportList *reports, int frame) { int error = GL_NO_ERROR; BKE_image_tag_time(image); if (image->gputexture[TEXTARGET_TEXTURE_2D] == NULL) - error = rna_Image_gl_load(image, reports, frame, filter, mag); + error = rna_Image_gl_load(image, reports, frame); return error; } @@ -367,52 +328,20 @@ void RNA_api_image(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_int( func, "frame", 0, 0, INT_MAX, "Frame", "Frame of image sequence or movie", 0, INT_MAX); - RNA_def_int(func, - "filter", - GL_LINEAR_MIPMAP_NEAREST, - -INT_MAX, - INT_MAX, - "Filter", - "The texture minifying function to use if the image wasn't loaded", - -INT_MAX, - INT_MAX); - RNA_def_int(func, - "mag", - GL_LINEAR, - -INT_MAX, - INT_MAX, - "Magnification", - "The texture magnification function to use if the image wasn't loaded", - -INT_MAX, - INT_MAX); /* return value */ parm = RNA_def_int( func, "error", 0, -INT_MAX, INT_MAX, "Error", "OpenGL error value", -INT_MAX, INT_MAX); RNA_def_function_return(func, parm); func = RNA_def_function(srna, "gl_load", "rna_Image_gl_load"); - RNA_def_function_ui_description(func, "Load the image into OpenGL graphics memory"); + RNA_def_function_ui_description( + func, + "Load the image into an OpenGL texture. On success, image.bindcode will contain the " + "OpenGL texture bindcode. Colors read from the texture will be in scene linear color space " + "and have premultiplied alpha."); RNA_def_function_flag(func, FUNC_USE_REPORTS); RNA_def_int( func, "frame", 0, 0, INT_MAX, "Frame", "Frame of image sequence or movie", 0, INT_MAX); - RNA_def_int(func, - "filter", - GL_LINEAR_MIPMAP_NEAREST, - -INT_MAX, - INT_MAX, - "Filter", - "The texture minifying function", - -INT_MAX, - INT_MAX); - RNA_def_int(func, - "mag", - GL_LINEAR, - -INT_MAX, - INT_MAX, - "Magnification", - "The texture magnification function", - -INT_MAX, - INT_MAX); /* return value */ parm = RNA_def_int( func, "error", 0, -INT_MAX, INT_MAX, "Error", "OpenGL error value", -INT_MAX, INT_MAX); diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 75c6011bbe8..e4311f238af 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -343,6 +343,7 @@ char *rna_Node_ImageUser_path(struct PointerRNA *ptr); /* API functions */ void RNA_api_action(StructRNA *srna); +void RNA_api_animdata(struct StructRNA *srna); void RNA_api_armature_edit_bone(StructRNA *srna); void RNA_api_bone(StructRNA *srna); void RNA_api_camera(StructRNA *srna); diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index a71adec4e5c..c8af49c47ff 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -187,6 +187,15 @@ static void rna_ObjectBase_select_update(Main *UNUSED(bmain), ED_object_base_select(base, mode); } +static void rna_ObjectBase_hide_viewport_update(bContext *C, PointerRNA *UNUSED(ptr)) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + BKE_layer_collection_sync(scene, view_layer); + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); +} + static void rna_LayerCollection_name_get(struct PointerRNA *ptr, char *value) { ID *id = (ID *)((LayerCollection *)ptr->data)->collection; @@ -199,12 +208,29 @@ int rna_LayerCollection_name_length(PointerRNA *ptr) return strlen(id->name + 2); } +static void rna_LayerCollection_exclude_update_recursive(ListBase *lb, const bool exclude) +{ + for (LayerCollection *lc = lb->first; lc; lc = lc->next) { + if (exclude) { + lc->flag |= LAYER_COLLECTION_EXCLUDE; + } + else { + lc->flag &= ~LAYER_COLLECTION_EXCLUDE; + } + rna_LayerCollection_exclude_update_recursive(&lc->layer_collections, exclude); + } +} + static void rna_LayerCollection_exclude_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->id.data; LayerCollection *lc = (LayerCollection *)ptr->data; ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc); + /* Set/Unset it recursively to match the behaviour of excluding via the menu or shortcuts. */ + rna_LayerCollection_exclude_update_recursive(&lc->layer_collections, + (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0); + BKE_layer_collection_sync(scene, view_layer); DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); @@ -266,21 +292,26 @@ static void rna_def_layer_collection(BlenderRNA *brna) RNA_def_property_struct_type(prop, "LayerCollection"); RNA_def_property_ui_text(prop, "Children", "Child layer collections"); + /* Restriction flags. */ prop = RNA_def_property(srna, "exclude", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_EXCLUDE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Exclude", "Exclude collection from view layer"); + RNA_def_property_ui_text(prop, "Exclude from View Layer", "Exclude from view layer"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_icon(prop, ICON_CHECKBOX_HLT, -1); RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_exclude_update"); prop = RNA_def_property(srna, "holdout", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_HOLDOUT); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_icon(prop, ICON_CLIPUV_HLT, -1); RNA_def_property_ui_text(prop, "Holdout", "Mask out objects in collection from view layer"); RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_update"); prop = RNA_def_property(srna, "indirect_only", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_INDIRECT_ONLY); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_icon(prop, ICON_MOD_PHYSICS, 0); RNA_def_property_ui_text( prop, "Indirect Only", @@ -289,14 +320,13 @@ static void rna_def_layer_collection(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_update"); prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_RESTRICT_VIEW); + RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_HIDE); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1); - RNA_def_property_ui_text( - prop, "Disable Viewport", "Disable collection in viewport for this view layer"); + RNA_def_property_ui_text(prop, "Hide in Viewport", "Temporarily hide in viewport"); RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_update"); + /* Run-time flags. */ prop = RNA_def_property(srna, "is_visible", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "runtime_flag", LAYER_COLLECTION_VISIBLE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -374,6 +404,14 @@ static void rna_def_object_base(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", BASE_SELECTED); RNA_def_property_ui_text(prop, "Select", "Object base selection state"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ObjectBase_select_update"); + + prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", BASE_HIDDEN); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); + RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1); + RNA_def_property_ui_text(prop, "Hide in Viewport", "Temporarily hide in viewport"); + RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ObjectBase_hide_viewport_update"); } void RNA_def_view_layer(BlenderRNA *brna) @@ -428,7 +466,7 @@ void RNA_def_view_layer(BlenderRNA *brna) /* layer options */ prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", VIEW_LAYER_RENDER); - RNA_def_property_ui_text(prop, "Enabled", "Disable or enable the render layer"); + RNA_def_property_ui_text(prop, "Enabled", "Enable or disable rendering of this View Layer"); RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL); prop = RNA_def_property(srna, "use_freestyle", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c index da2b5752a0f..54c8049d4d2 100644 --- a/source/blender/makesrna/intern/rna_light.c +++ b/source/blender/makesrna/intern/rna_light.c @@ -545,12 +545,20 @@ static void rna_def_spot_light(BlenderRNA *brna) static void rna_def_sun_light(BlenderRNA *brna) { StructRNA *srna; + PropertyRNA *prop; srna = RNA_def_struct(brna, "SunLight", "Light"); RNA_def_struct_sdna(srna, "Light"); RNA_def_struct_ui_text(srna, "Sun Light", "Constant direction parallel ray Light"); RNA_def_struct_ui_icon(srna, ICON_LIGHT_SUN); + prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "sun_angle"); + RNA_def_property_float_default(prop, DEG2RADF(0.526f)); + RNA_def_property_range(prop, DEG2RADF(0.0f), DEG2RADF(180.0f)); + RNA_def_property_ui_text(prop, "Angle", "Angular diameter of the Sun as seen from the Earth"); + RNA_def_property_update(prop, 0, "rna_Light_update"); + rna_def_light_energy(srna, true); rna_def_light_shadow(srna, true); } diff --git a/source/blender/makesrna/intern/rna_lightprobe.c b/source/blender/makesrna/intern/rna_lightprobe.c index 125d2ade567..8b6b248eac2 100644 --- a/source/blender/makesrna/intern/rna_lightprobe.c +++ b/source/blender/makesrna/intern/rna_lightprobe.c @@ -77,7 +77,7 @@ static void rna_def_lightprobe(BlenderRNA *brna) srna = RNA_def_struct(brna, "LightProbe", "ID"); RNA_def_struct_ui_text( srna, "LightProbe", "Light Probe data-block for lighting capture objects"); - RNA_def_struct_ui_icon(srna, ICON_OUTLINER_OB_LIGHTPROBE); + RNA_def_struct_ui_icon(srna, ICON_OUTLINER_DATA_LIGHTPROBE); prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, lightprobe_type_items); diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index d66b4e5be44..edfdbe293a3 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -440,6 +440,17 @@ static void rna_def_material_greasepencil(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static EnumPropertyItem alignment_draw_items[] = { + {GP_STYLE_FOLLOW_PATH, "PATH", 0, "Path", "Follow stroke drawing path and object rotation"}, + {GP_STYLE_FOLLOW_OBJ, "OBJECT", 0, "Object", "Follow object rotation only"}, + {GP_STYLE_FOLLOW_FIXED, + "FIXED", + 0, + "Fixed", + "Do not follow drawing path or object rotation and keeps aligned with viewport"}, + {0, NULL, 0, NULL, NULL}, + }; + srna = RNA_def_struct(brna, "MaterialGPencilStyle", NULL); RNA_def_struct_sdna(srna, "MaterialGPencilStyle"); RNA_def_struct_ui_text(srna, "Grease Pencil Color", ""); @@ -611,10 +622,12 @@ static void rna_def_material_greasepencil(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Fill", "Show stroke fills of this material"); RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update"); - /* keep Dots and Boxes aligned to screen and not to drawing path */ - prop = RNA_def_property(srna, "use_follow_path", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_STYLE_COLOR_LOCK_DOTS); - RNA_def_property_ui_text(prop, "Follow Path", "Keep Dots and Boxes aligned to drawing path"); + /* Mode to align Dots and Boxes to drawing path and object rotation */ + prop = RNA_def_property(srna, "alignment_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "alignment_mode"); + RNA_def_property_enum_items(prop, alignment_draw_items); + RNA_def_property_ui_text( + prop, "Alignment", "Defines how align Dots and Boxes with drawing path and object rotation"); RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_nopreview_update"); /* pass index for future compositing and editing tools */ @@ -778,6 +791,12 @@ void RNA_def_material(BlenderRNA *brna) "(avoids transparency sorting problems)"); RNA_def_property_update(prop, 0, "rna_Material_draw_update"); + prop = RNA_def_property(srna, "use_backface_culling", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MA_BL_CULL_BACKFACE); + RNA_def_property_ui_text( + prop, "Backface Culling", "Use back face culling to hide the back side of faces"); + RNA_def_property_update(prop, 0, "rna_Material_draw_update"); + prop = RNA_def_property(srna, "use_screen_refraction", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MA_BL_SS_REFRACTION); RNA_def_property_ui_text( diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 6ab83bc063c..ede1bf89e06 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -445,6 +445,8 @@ const EnumPropertyItem rna_enum_axis_flag_xyz_items[] = { # include "BKE_object.h" # include "BKE_particle.h" +# include "BLI_sort_utils.h" + # include "DEG_depsgraph.h" # include "DEG_depsgraph_build.h" # include "DEG_depsgraph_query.h" @@ -743,12 +745,79 @@ RNA_MOD_OBJECT_SET(SurfaceDeform, target, OB_MESH); static void rna_HookModifier_object_set(PointerRNA *ptr, PointerRNA value) { + Object *owner = (Object *)ptr->id.data; HookModifierData *hmd = ptr->data; Object *ob = (Object *)value.data; hmd->object = ob; id_lib_extern((ID *)ob); - BKE_object_modifier_hook_reset(ob, hmd); + BKE_object_modifier_hook_reset(owner, hmd); +} + +static void rna_HookModifier_subtarget_set(PointerRNA *ptr, const char *value) +{ + Object *owner = (Object *)ptr->id.data; + HookModifierData *hmd = ptr->data; + + BLI_strncpy(hmd->subtarget, value, sizeof(hmd->subtarget)); + BKE_object_modifier_hook_reset(owner, hmd); +} + +static int rna_HookModifier_vertex_indices_get_length(PointerRNA *ptr, + int length[RNA_MAX_ARRAY_DIMENSION]) +{ + HookModifierData *hmd = ptr->data; + int totindex = hmd->indexar ? hmd->totindex : 0; + return (length[0] = totindex); +} + +static void rna_HookModifier_vertex_indices_get(PointerRNA *ptr, int *values) +{ + HookModifierData *hmd = ptr->data; + if (hmd->indexar != NULL) { + memcpy(values, hmd->indexar, sizeof(int) * hmd->totindex); + } +} + +static void rna_HookModifier_vertex_indices_set(HookModifierData *hmd, + ReportList *reports, + int indices_len, + int *indices) +{ + if (indices_len == 0) { + MEM_SAFE_FREE(hmd->indexar); + hmd->totindex = 0; + } + else { + /* Reject negative indices. */ + for (int i = 0; i < indices_len; i++) { + if (indices[i] < 0) { + BKE_reportf(reports, RPT_ERROR, "Negative vertex index in vertex_indices_set"); + return; + } + } + + /* Copy and sort the index array. */ + size_t size = sizeof(int) * indices_len; + int *buffer = MEM_mallocN(size, "hook indexar"); + memcpy(buffer, indices, size); + + qsort(buffer, indices_len, sizeof(int), BLI_sortutil_cmp_int); + + /* Reject duplicate indices. */ + for (int i = 1; i < indices_len; i++) { + if (buffer[i] == buffer[i - 1]) { + BKE_reportf(reports, RPT_ERROR, "Duplicate index %d in vertex_indices_set", buffer[i]); + MEM_freeN(buffer); + return; + } + } + + /* Success - save the new array. */ + MEM_SAFE_FREE(hmd->indexar); + hmd->indexar = buffer; + hmd->totindex = indices_len; + } } static PointerRNA rna_UVProjector_object_get(PointerRNA *ptr) @@ -2151,6 +2220,8 @@ static void rna_def_modifier_hook(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + FunctionRNA *func; + PropertyRNA *parm; srna = RNA_def_struct(brna, "HookModifier", "Modifier"); RNA_def_struct_ui_text( @@ -2183,9 +2254,10 @@ static void rna_def_modifier_hook(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Falloff Curve", "Custom falloff curve"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - prop = RNA_def_property(srna, "center", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "center", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_float_sdna(prop, NULL, "cent"); - RNA_def_property_ui_text(prop, "Hook Center", ""); + RNA_def_property_ui_text( + prop, "Hook Center", "Center of the hook, used for falloff and display"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "matrix_inverse", PROP_FLOAT, PROP_MATRIX); @@ -2208,6 +2280,7 @@ static void rna_def_modifier_hook(BlenderRNA *brna) prop, "Sub-Target", "Name of Parent Bone for hook (if applicable), also recalculates and clears offset"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_HookModifier_subtarget_set"); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "use_falloff_uniform", PROP_BOOLEAN, PROP_NONE); @@ -2223,6 +2296,26 @@ static void rna_def_modifier_hook(BlenderRNA *brna) "Name of Vertex Group which determines influence of modifier per point"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_HookModifier_name_set"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "vertex_indices", PROP_INT, PROP_UNSIGNED); + RNA_def_property_array(prop, RNA_MAX_ARRAY_LENGTH); + RNA_def_property_flag(prop, PROP_DYNAMIC); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_dynamic_array_funcs(prop, "rna_HookModifier_vertex_indices_get_length"); + RNA_def_property_int_funcs(prop, "rna_HookModifier_vertex_indices_get", NULL, NULL); + RNA_def_property_ui_text(prop, + "Vertex Indices", + "Indices of vertices bound to the modifier. For bezier curves, " + "handles count as additional vertices"); + + func = RNA_def_function(srna, "vertex_indices_set", "rna_HookModifier_vertex_indices_set"); + RNA_def_function_ui_description( + func, "Validates and assigns the array of vertex indices bound to the modifier"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_int_array( + func, "indices", 1, NULL, INT_MIN, INT_MAX, "", "Vertex Indices", 0, INT_MAX); + RNA_def_property_array(parm, RNA_MAX_ARRAY_LENGTH); + RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); } static void rna_def_modifier_softbody(BlenderRNA *brna) @@ -3102,6 +3195,7 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna) prop = RNA_def_property(srna, "use_children", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Children); RNA_def_property_ui_text(prop, "Children", "Create instances from child particles"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_PARTICLESETTINGS); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "use_path", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index e4270f3854e..4906f8ac28e 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -3987,21 +3987,6 @@ static void def_sh_tex_sky(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } -static const EnumPropertyItem sh_tex_prop_color_space_items[] = { - {SHD_COLORSPACE_COLOR, - "COLOR", - 0, - "Color", - "Image contains color data, and will be converted to linear color for rendering"}, - {SHD_COLORSPACE_NONE, - "NONE", - 0, - "Non-Color Data", - "Image contains non-color data, for example a displacement or normal map, " - "and will not be converted"}, - {0, NULL, 0, NULL, NULL}, -}; - static const EnumPropertyItem sh_tex_prop_interpolation_items[] = { {SHD_INTERP_LINEAR, "Linear", 0, "Linear", "Linear interpolation"}, {SHD_INTERP_CLOSEST, "Closest", 0, "Closest", "No interpolation (sample closest texel)"}, @@ -4038,12 +4023,6 @@ static void def_sh_tex_environment(StructRNA *srna) RNA_def_struct_sdna_from(srna, "NodeTexEnvironment", "storage"); def_sh_tex(srna); - prop = RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, sh_tex_prop_color_space_items); - RNA_def_property_enum_default(prop, SHD_COLORSPACE_COLOR); - RNA_def_property_ui_text(prop, "Color Space", "Image file color space"); - RNA_def_property_update(prop, 0, "rna_Node_update"); - prop = RNA_def_property(srna, "projection", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_projection_items); RNA_def_property_ui_text(prop, "Projection", "Projection of the input image"); @@ -4122,12 +4101,6 @@ static void def_sh_tex_image(StructRNA *srna) RNA_def_struct_sdna_from(srna, "NodeTexImage", "storage"); def_sh_tex(srna); - prop = RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, sh_tex_prop_color_space_items); - RNA_def_property_enum_default(prop, SHD_COLORSPACE_COLOR); - RNA_def_property_ui_text(prop, "Color Space", "Image file color space"); - RNA_def_property_update(prop, 0, "rna_Node_update"); - prop = RNA_def_property(srna, "projection", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_projection_items); RNA_def_property_ui_text( diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 219445f629f..b2cbfbbf6f0 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2801,9 +2801,9 @@ static void rna_def_object(BlenderRNA *brna) /* restrict */ prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_VIEW); + RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_VIEWPORT); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); - RNA_def_property_ui_text(prop, "Disable View", "Disable object in the viewport"); + RNA_def_property_ui_text(prop, "Disable in Viewports", "Globally disable in viewports"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); @@ -2811,14 +2811,14 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_SELECT); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); - RNA_def_property_ui_text(prop, "Disable Select", "Disable object selection in the viewport"); + RNA_def_property_ui_text(prop, "Disable Selection", "Disable selection in viewport"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_RENDER); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); - RNA_def_property_ui_text(prop, "Disable Render", "Disable object in renders"); + RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 5f41bf68572..c997a82f02d 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -398,7 +398,7 @@ static PointerRNA rna_Object_shape_key_add( if ((kb = BKE_object_shapekey_insert(bmain, ob, name, from_mix))) { PointerRNA keyptr; - RNA_pointer_create((ID *)ob->data, &RNA_ShapeKey, kb, &keyptr); + RNA_pointer_create((ID *)BKE_key_from_object(ob), &RNA_ShapeKey, kb, &keyptr); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); return keyptr; diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index c4f0eb35627..2abb1f3227a 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -754,7 +754,7 @@ static void rna_def_pointcache_common(StructRNA *srna) static const EnumPropertyItem point_cache_compress_items[] = { {PTCACHE_COMPRESS_NO, "NO", 0, "None", "No compression"}, - {PTCACHE_COMPRESS_LZO, "LIGHT", 0, "Light", "Fast but not so effective compression"}, + {PTCACHE_COMPRESS_LZO, "LIGHT", 0, "Lite", "Fast but not so effective compression"}, {PTCACHE_COMPRESS_LZMA, "HEAVY", 0, "Heavy", "Effective but slow compression"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 1b4a7efbdd8..2f7f8c70760 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -122,6 +122,11 @@ static void rna_Pose_IK_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe BIK_clear_data(ob->pose); } +static char *rna_Pose_path(PointerRNA *UNUSED(ptr)) +{ + return BLI_strdup("pose"); +} + static char *rna_PoseBone_path(PointerRNA *ptr) { bPoseChannel *pchan = ptr->data; @@ -284,6 +289,18 @@ static void rna_PoseChannel_name_set(PointerRNA *ptr, const char *value) ED_armature_bone_rename(G_MAIN, ob->data, oldname, newname); } +static PointerRNA rna_PoseChannel_bone_get(PointerRNA *ptr) +{ + Object *ob = (Object *)ptr->id.data; + bPoseChannel *pchan = (bPoseChannel *)ptr->data; + PointerRNA tmp_ptr = *ptr; + + /* Replace the id_data pointer with the Armature ID. */ + tmp_ptr.id.data = ob->data; + + return rna_pointer_inherit_refine(&tmp_ptr, &RNA_Bone, pchan->bone); +} + static bool rna_PoseChannel_has_ik_get(PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; @@ -911,6 +928,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) prop = RNA_def_property(srna, "bone", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_struct_type(prop, "Bone"); + RNA_def_property_pointer_funcs(prop, "rna_PoseChannel_bone_get", NULL, NULL, NULL); RNA_def_property_flag(prop, PROP_PTR_NO_OWNERSHIP); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Bone", "Bone associated with this PoseBone"); @@ -1551,6 +1569,31 @@ static void rna_def_pose(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "IK Param", "Parameters for IK solver"); + /* pose edit options */ + prop = RNA_def_property(srna, "use_mirror_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", POSE_MIRROR_EDIT); + RNA_def_property_ui_text( + prop, "X-Axis Mirror", "Apply changes to matching bone on opposite side of X-Axis"); + RNA_def_struct_path_func(srna, "rna_Pose_path"); + RNA_def_property_update(prop, 0, "rna_Pose_update"); + RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); + + prop = RNA_def_property(srna, "use_mirror_relative", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", POSE_MIRROR_RELATIVE); + RNA_def_property_ui_text( + prop, "Relative Mirror", "Apply relative transformations in X-mirror mode"); + RNA_def_struct_path_func(srna, "rna_Pose_path"); + RNA_def_property_update(prop, 0, "rna_Pose_update"); + RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); + + prop = RNA_def_property(srna, "use_auto_ik", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", POSE_AUTO_IK); + RNA_def_property_ui_text( + prop, "Auto IK", "Add temporary IK constraints while grabbing bones in Pose Mode"); + RNA_def_struct_path_func(srna, "rna_Pose_path"); + RNA_def_property_update(prop, 0, "rna_Pose_update"); + RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); + /* animviz */ rna_def_animviz_common(srna); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 5f9e72f74b4..83d7fae14c0 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2856,7 +2856,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "proportional_objects", 0); RNA_def_property_ui_text( prop, "Proportional Editing Objects", "Proportional editing object mode"); - RNA_def_property_ui_icon(prop, ICON_PROP_ON, 0); + RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ prop = RNA_def_property(srna, "use_proportional_projected", PROP_BOOLEAN, PROP_NONE); @@ -2900,6 +2900,8 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_enum_items(prop, rna_enum_proportional_falloff_items); RNA_def_property_ui_text( prop, "Proportional Editing Falloff", "Falloff type for proportional editing mode"); + /* Abusing id_curve :/ */ + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ prop = RNA_def_property(srna, "proportional_size", PROP_FLOAT, PROP_DISTANCE); @@ -3619,7 +3621,8 @@ static void rna_def_unit_settings(BlenderRNA *brna) /* Units */ prop = RNA_def_property(srna, "system", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, unit_systems); - RNA_def_property_ui_text(prop, "Unit System", "The unit system to use for user interface controls"); + RNA_def_property_ui_text( + prop, "Unit System", "The unit system to use for user interface controls"); RNA_def_property_update(prop, NC_WINDOW, "rna_UnitSettings_system_update"); prop = RNA_def_property(srna, "system_rotation", PROP_ENUM, PROP_NONE); @@ -6642,13 +6645,14 @@ static void rna_def_scene_display(BlenderRNA *brna) prop = RNA_def_property(srna, "render_aa", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_scene_display_aa_methods); - RNA_def_property_ui_text(prop, "Render Anti-Aliasing", "Method of anti-aliasing when rendering"); + RNA_def_property_ui_text( + prop, "Render Anti-Aliasing", "Method of anti-aliasing when rendering final image"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); prop = RNA_def_property(srna, "viewport_aa", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_scene_display_aa_methods); RNA_def_property_ui_text( - prop, "Viewport Anti-Aliasing", "Method of anti-aliasing in 3d viewport"); + prop, "Viewport Anti-Aliasing", "Method of anti-aliasing when rendering 3d viewport"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* OpenGL render engine settings. */ diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index b6486d7a3f4..f4fba02efe5 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -463,7 +463,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}}; static const EnumPropertyItem smoke_cache_comp_items[] = { - {SM_CACHE_LIGHT, "CACHELIGHT", 0, "Light", "Fast but not so effective compression"}, + {SM_CACHE_LIGHT, "CACHELIGHT", 0, "Lite", "Fast but not so effective compression"}, {SM_CACHE_HEAVY, "CACHEHEAVY", 0, "Heavy", "Effective but slow compression"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 1e14fd06b4f..f6515648164 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -644,6 +644,20 @@ static void rna_Space_show_region_header_update(bContext *C, PointerRNA *ptr) rna_Space_bool_from_region_flag_update_by_type(C, ptr, RGN_TYPE_HEADER, RGN_FLAG_HIDDEN); } +/* Footer Region. */ +static bool rna_Space_show_region_footer_get(PointerRNA *ptr) +{ + return !rna_Space_bool_from_region_flag_get_by_type(ptr, RGN_TYPE_FOOTER, RGN_FLAG_HIDDEN); +} +static void rna_Space_show_region_footer_set(PointerRNA *ptr, bool value) +{ + rna_Space_bool_from_region_flag_set_by_type(ptr, RGN_TYPE_FOOTER, RGN_FLAG_HIDDEN, !value); +} +static void rna_Space_show_region_footer_update(bContext *C, PointerRNA *ptr) +{ + rna_Space_bool_from_region_flag_update_by_type(C, ptr, RGN_TYPE_FOOTER, RGN_FLAG_HIDDEN); +} + /* Tool Header Region. * * This depends on the 'RGN_TYPE_TOOL_HEADER' @@ -2460,6 +2474,10 @@ static void rna_def_space_generic_show_region_toggles(StructRNA *srna, int regio region_type_mask &= ~(1 << RGN_TYPE_HEADER); DEF_SHOW_REGION_PROPERTY(show_region_header, "Header", ""); } + if (region_type_mask & (1 << RGN_TYPE_FOOTER)) { + region_type_mask &= ~(1 << RGN_TYPE_FOOTER); + DEF_SHOW_REGION_PROPERTY(show_region_footer, "Footer", ""); + } if (region_type_mask & (1 << RGN_TYPE_TOOLS)) { region_type_mask &= ~(1 << RGN_TYPE_TOOLS); DEF_SHOW_REGION_PROPERTY(show_region_toolbar, "Toolbar", ""); @@ -2750,25 +2768,60 @@ static void rna_def_space_outliner(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "search_flags", SO_FIND_CASE_SENSITIVE); RNA_def_property_ui_text( prop, "Case Sensitive Matches Only", "Only use case sensitive matches of search string"); - RNA_def_property_ui_icon(prop, ICON_SYNTAX_OFF, 0); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); prop = RNA_def_property(srna, "use_filter_complete", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "search_flags", SO_FIND_COMPLETE); RNA_def_property_ui_text( prop, "Complete Matches Only", "Only use complete matches of search string"); - RNA_def_property_ui_icon(prop, ICON_OUTLINER_DATA_FONT, 0); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); prop = RNA_def_property(srna, "use_sort_alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SO_SKIP_SORT_ALPHA); RNA_def_property_ui_text(prop, "Sort Alphabetically", ""); - RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); - prop = RNA_def_property(srna, "show_restrict_columns", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SO_HIDE_RESTRICTCOLS); - RNA_def_property_ui_text(prop, "Show Restriction Columns", "Show column"); + /* Granular restriction column option. */ + prop = RNA_def_property(srna, "show_restrict_column_enable", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_ENABLE); + RNA_def_property_ui_text(prop, "Exclude from View Layer", "Exclude from view layer"); + RNA_def_property_ui_icon(prop, ICON_CHECKBOX_HLT, 0); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); + + prop = RNA_def_property(srna, "show_restrict_column_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_SELECT); + RNA_def_property_ui_text(prop, "Selectable", "Selectable"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 0); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); + + prop = RNA_def_property(srna, "show_restrict_column_hide", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_HIDE); + RNA_def_property_ui_text(prop, "Hide in Viewport", "Temporarily hide in viewport"); + RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, 0); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); + + prop = RNA_def_property(srna, "show_restrict_column_viewport", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_VIEWPORT); + RNA_def_property_ui_text(prop, "Disable in Viewports", "Globally disable in viewports"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 0); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); + + prop = RNA_def_property(srna, "show_restrict_column_render", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_RENDER); + RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 0); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); + + prop = RNA_def_property(srna, "show_restrict_column_holdout", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_HOLDOUT); + RNA_def_property_ui_text(prop, "Holdout", "Holdout"); + RNA_def_property_ui_icon(prop, ICON_CLIPUV_DEHLT, 0); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); + + prop = RNA_def_property(srna, "show_restrict_column_indirect_only", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_INDIRECT_ONLY); + RNA_def_property_ui_text(prop, "Indirect Only", "Indirect only"); + RNA_def_property_ui_icon(prop, ICON_MOD_PHYSICS, 0); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); /* Filters. */ @@ -3275,7 +3328,7 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) prop = RNA_def_property(srna, "show_look_dev", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_LOOK_DEV); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Look Dev Preview", "Show look development balls and palette"); + RNA_def_property_ui_text(prop, "Look Dev Preview", "Show look development spheres and palette"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "show_wireframes", PROP_BOOLEAN, PROP_NONE); @@ -4473,7 +4526,7 @@ static void rna_def_space_text(BlenderRNA *brna) RNA_def_struct_sdna(srna, "SpaceText"); RNA_def_struct_ui_text(srna, "Space Text Editor", "Text editor space data"); - rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_UI)); + rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_UI) | (1 << RGN_TYPE_FOOTER)); /* text */ prop = RNA_def_property(srna, "text", PROP_POINTER, PROP_NONE); @@ -5146,7 +5199,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna) "Show/hide Paint Curve data-blocks"}, {FILTER_ID_LP, "LIGHT_PROBE", - ICON_LIGHTPROBE_CUBEMAP, + ICON_OUTLINER_DATA_LIGHTPROBE, "Light Probes", "Show/hide Light Probe data-blocks"}, {FILTER_ID_SCE, "SCENE", ICON_SCENE_DATA, "Scenes", "Show/hide Scene data-blocks"}, diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index a9bec8262dd..38877ba6fdd 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -42,6 +42,8 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "UI_interface_icons.h" + #include "rna_internal.h" #include "WM_api.h" @@ -99,6 +101,45 @@ static const EnumPropertyItem rna_enum_studio_light_type_items[] = { {0, NULL, 0, NULL, NULL}, }; +static const EnumPropertyItem rna_enum_userdef_viewport_aa_items[] = { + {SCE_DISPLAY_AA_OFF, + "OFF", + 0, + "No Anti-Aliasing", + "Scene will be rendering without any anti-aliasing"}, + {SCE_DISPLAY_AA_FXAA, + "FXAA", + 0, + "Single Pass Anti-Aliasing", + "Scene will be rendered using a single pass anti-aliasing method (FXAA)"}, + {SCE_DISPLAY_AA_SAMPLES_5, + "5", + 0, + "5 Samples", + "Scene will be rendered using 5 anti-aliasing samples"}, + {SCE_DISPLAY_AA_SAMPLES_8, + "8", + 0, + "8 Samples", + "Scene will be rendered using 8 anti-aliasing samples"}, + {SCE_DISPLAY_AA_SAMPLES_11, + "11", + 0, + "11 Samples", + "Scene will be rendered using 11 anti-aliasing samples"}, + {SCE_DISPLAY_AA_SAMPLES_16, + "16", + 0, + "16 Samples", + "Scene will be rendered using 16 anti-aliasing samples"}, + {SCE_DISPLAY_AA_SAMPLES_32, + "32", + 0, + "32 Samples", + "Scene will be rendered using 32 anti-aliasing samples"}, + {0, NULL, 0, NULL, NULL}, +}; + #ifdef RNA_RUNTIME # include "BLI_math_vector.h" @@ -143,8 +184,19 @@ static void rna_userdef_version_get(PointerRNA *ptr, int *value) value[2] = userdef->subversionfile; } +static void rna_userdef_ui_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *UNUSED(ptr)) +{ + WM_main_add_notifier(NC_WINDOW, NULL); +} + static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) { + /* We can't use 'ptr->data' because this update function + * is used for themes and other nested data. */ + U.runtime.is_dirty = true; + WM_main_add_notifier(NC_WINDOW, NULL); } @@ -156,6 +208,12 @@ static void rna_userdef_theme_update(Main *bmain, Scene *scene, PointerRNA *ptr) rna_userdef_update(bmain, scene, ptr); } +static void rna_userdef_theme_update_icons(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + UI_icons_reload_internal_textures(); + rna_userdef_theme_update(bmain, scene, ptr); +} + /* also used by buffer swap switching */ static void rna_userdef_dpi_update(Main *UNUSED(bmain), Scene *UNUSED(scene), @@ -401,6 +459,7 @@ static bAddon *rna_userdef_addon_new(void) ListBase *addons_list = &U.addons; bAddon *addon = BKE_addon_new(); BLI_addtail(addons_list, addon); + U.runtime.is_dirty = true; return addon; } @@ -415,12 +474,14 @@ static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *addon_ptr) BLI_remlink(addons_list, addon); BKE_addon_free(addon); RNA_POINTER_INVALIDATE(addon_ptr); + U.runtime.is_dirty = true; } static bPathCompare *rna_userdef_pathcompare_new(void) { bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare"); BLI_addtail(&U.autoexec_paths, path_cmp); + U.runtime.is_dirty = true; return path_cmp; } @@ -434,6 +495,7 @@ static void rna_userdef_pathcompare_remove(ReportList *reports, PointerRNA *path BLI_freelinkN(&U.autoexec_paths, path_cmp); RNA_POINTER_INVALIDATE(path_cmp_ptr); + U.runtime.is_dirty = true; } static void rna_userdef_temp_update(Main *UNUSED(bmain), @@ -1338,6 +1400,12 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); /* Icon colors. */ + prop = RNA_def_property(srna, "icon_scene", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "icon_scene"); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Scene", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "icon_collection", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "icon_collection"); RNA_def_property_array(prop, 4); @@ -1367,6 +1435,13 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Shading", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + + prop = RNA_def_property(srna, "icon_border_intensity", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "icon_border_intensity"); + RNA_def_property_ui_text( + prop, "Icon Border", "Control the intensity of the border around themes icons"); + RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 2); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update_icons"); } static void rna_def_userdef_theme_space_common(StructRNA *srna) @@ -2065,6 +2140,11 @@ static void rna_def_userdef_theme_space_graph(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Current Frame", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "scrubbing_background", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "window_sliders", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "shade1"); RNA_def_property_array(prop, 3); @@ -2759,6 +2839,11 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Current Frame", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "scrubbing_background", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "keyframe", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "vertex_select"); RNA_def_property_array(prop, 3); @@ -2816,6 +2901,11 @@ static void rna_def_userdef_theme_space_action(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Current Frame", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "scrubbing_background", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "value_sliders", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "face"); RNA_def_property_array(prop, 3); @@ -3108,6 +3198,11 @@ static void rna_def_userdef_theme_space_nla(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Current Frame", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + + prop = RNA_def_property(srna, "scrubbing_background", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); } static void rna_def_userdef_theme_colorset(BlenderRNA *brna) @@ -3215,6 +3310,11 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Current Frame", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "scrubbing_background", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "strips", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "strip"); RNA_def_property_array(prop, 3); @@ -4109,12 +4209,12 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_userdef_update"); /* Lookdev */ - prop = RNA_def_property(srna, "lookdev_ball_size", PROP_INT, PROP_PIXEL); - RNA_def_property_int_sdna(prop, NULL, "lookdev_ball_size"); + prop = RNA_def_property(srna, "lookdev_sphere_size", PROP_INT, PROP_PIXEL); + RNA_def_property_int_sdna(prop, NULL, "lookdev_sphere_size"); RNA_def_property_range(prop, 50, 400); RNA_def_property_int_default(prop, 150); RNA_def_property_ui_text( - prop, "LookDev Balls Size", "Maximum diameter of the LookDev balls size"); + prop, "Look Dev Spheres Size", "Maximum diameter of the look development sphere size"); RNA_def_property_update(prop, 0, "rna_userdef_update"); /* View2D Grid Displays */ @@ -4247,7 +4347,12 @@ static void rna_def_userdef_edit(BlenderRNA *brna) "VIEW", 0, "View", - "Align newly added objects facing the active 3D View direction"}, + "Align newly added objects to the active 3D View direction"}, + {USER_ADD_CURSORALIGNED, + "CURSOR", + 0, + "3D Cursor", + "Align newly added objects to the 3D Cursor's rotation"}, {0, NULL, 0, NULL, NULL}, }; @@ -4706,12 +4811,11 @@ static void rna_def_userdef_system(BlenderRNA *brna) prop, "Region Overlap", "Draw tool/property regions over the main region"); RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); - prop = RNA_def_property(srna, "gpu_viewport_quality", PROP_FLOAT, PROP_FACTOR); - RNA_def_property_float_sdna(prop, NULL, "gpu_viewport_quality"); - RNA_def_property_float_default(prop, 0.6f); - RNA_def_property_range(prop, 0.0f, 1.0f); + prop = RNA_def_property(srna, "viewport_aa", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_userdef_viewport_aa_items); RNA_def_property_ui_text( - prop, "Viewport Quality", "Quality setting for Solid mode rendering in the 3d viewport"); + prop, "Viewport Anti-Aliasing", "Method of anti-aliasing in 3d viewport"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, 0, "rna_userdef_update"); prop = RNA_def_property(srna, "solid_lights", PROP_COLLECTION, PROP_NONE); @@ -5499,7 +5603,7 @@ void RNA_def_userdef(BlenderRNA *brna) RNA_def_property_enum_items(prop, preference_section_items); RNA_def_property_ui_text( prop, "Active Section", "Active section of the preferences shown in the user interface"); - RNA_def_property_update(prop, 0, "rna_userdef_update"); + RNA_def_property_update(prop, 0, "rna_userdef_ui_update"); /* don't expose this directly via the UI, modify via an operator */ prop = RNA_def_property(srna, "app_template", PROP_STRING, PROP_NONE); @@ -5595,6 +5699,16 @@ void RNA_def_userdef(BlenderRNA *brna) NULL); RNA_def_property_ui_text(prop, "Studio Lights", ""); + /* Preferences Flags */ + prop = RNA_def_property(srna, "use_preferences_save", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pref_flag", USER_PREF_FLAG_SAVE); + RNA_def_property_ui_text(prop, "Save on Exit", "Save modified preferences on exit"); + + prop = RNA_def_property(srna, "is_dirty", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "runtime.is_dirty", 0); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Dirty", "Preferences have changed"); + rna_def_userdef_view(brna); rna_def_userdef_edit(brna); rna_def_userdef_input(brna); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 3f904df6e00..e4af1b549d6 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -1868,6 +1868,7 @@ static void rna_def_operator(BlenderRNA *brna) RNA_def_struct_idprops_func(srna, "rna_OperatorProperties_idprops"); RNA_def_struct_property_tags(srna, rna_enum_operator_property_tags); RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); + RNA_def_struct_clear_flag(srna, STRUCT_UNDO); } static void rna_def_macro_operator(BlenderRNA *brna) @@ -2105,6 +2106,7 @@ static void rna_def_event(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "shift", 1); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Shift", "True when the Shift key is held"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_WINDOWMANAGER); prop = RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ctrl", 1); @@ -2601,6 +2603,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) /* RNA_def_property_enum_sdna(prop, NULL, "shift"); */ /* RNA_def_property_enum_items(prop, keymap_modifiers_items); */ RNA_def_property_ui_text(prop, "Shift", "Shift key pressed"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_WINDOWMANAGER); RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop = RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c index a473f97d554..22162aa017b 100644 --- a/source/blender/makesrna/intern/rna_wm_gizmo.c +++ b/source/blender/makesrna/intern/rna_wm_gizmo.c @@ -384,6 +384,7 @@ static void rna_Gizmo_matrix_world_get(PointerRNA *ptr, float value[16]) RNA_GIZMO_GENERIC_FLOAT_RW_DEF(scale_basis, scale_basis); RNA_GIZMO_GENERIC_FLOAT_RW_DEF(line_width, line_width); +RNA_GIZMO_GENERIC_FLOAT_RW_DEF(select_bias, select_bias); RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_use_draw_hover, flag, WM_GIZMO_DRAW_HOVER); RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_use_draw_modal, flag, WM_GIZMO_DRAW_MODAL); @@ -1159,6 +1160,12 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_range(prop, 0.0f, FLT_MAX); RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL); + prop = RNA_def_property(srna, "select_bias", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Select Bias", "Depth bias used for selection"); + RNA_def_property_float_funcs( + prop, "rna_Gizmo_select_bias_get", "rna_Gizmo_select_bias_set", NULL); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + /* wmGizmo.flag */ /* WM_GIZMO_HIDDEN */ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index 6e5426bbf40..c61ebe0448c 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -195,7 +195,14 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes * Annoying and not so much black-boxed as far as sculpting goes, and * surely there is a better way of solving this. */ if (ctx->object->sculpt != NULL) { - ctx->object->sculpt->subdiv_ccg = result->runtime.subdiv_ccg; + SculptSession *sculpt_session = ctx->object->sculpt; + sculpt_session->subdiv_ccg = result->runtime.subdiv_ccg; + sculpt_session->multires = mmd; + sculpt_session->totvert = mesh->totvert; + sculpt_session->totpoly = mesh->totpoly; + sculpt_session->mvert = NULL; + sculpt_session->mpoly = NULL; + sculpt_session->mloop = NULL; } /* NOTE: CCG becomes an owner of Subdiv descriptor, so can not share * this pointer. Not sure if it's needed, but might have a second look diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h index 916cb81953e..165ada05a56 100644 --- a/source/blender/nodes/shader/node_shader_util.h +++ b/source/blender/nodes/shader/node_shader_util.h @@ -67,6 +67,7 @@ #include "RE_shader_ext.h" #include "GPU_material.h" +#include "GPU_texture.h" #include "GPU_uniformbuffer.h" bool sh_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree); diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c index 37c35c0adc8..6c3e082f36a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c @@ -39,6 +39,8 @@ static bNodeSocketTemplate sh_node_bsdf_principled_in[] = { {SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, {SOCK_FLOAT, 1, N_("Transmission"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, {SOCK_FLOAT, 1, N_("Transmission Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + {SOCK_RGBA, 1, N_("Emission"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, + {SOCK_FLOAT, 1, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, {SOCK_VECTOR, 1, N_("Normal"), @@ -99,26 +101,25 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, GPUNodeLink *sss_scale; /* Normals */ - if (!in[17].link) { - GPU_link(mat, "world_normals_get", &in[17].link); + if (!in[19].link) { + GPU_link(mat, "world_normals_get", &in[19].link); } /* Clearcoat Normals */ - if (!in[18].link) { - GPU_link(mat, "world_normals_get", &in[18].link); + if (!in[20].link) { + GPU_link(mat, "world_normals_get", &in[20].link); } /* Tangents */ - if (!in[19].link) { + if (!in[21].link) { GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); - GPU_link(mat, "tangent_orco_z", orco, &in[19].link); + GPU_link(mat, "tangent_orco_z", orco, &in[21].link); GPU_link(mat, "node_tangent", - GPU_builtin(GPU_VIEW_NORMAL), - in[19].link, + GPU_builtin(GPU_WORLD_NORMAL), + in[21].link, GPU_builtin(GPU_OBJECT_MATRIX), - GPU_builtin(GPU_INVERSE_VIEW_MATRIX), - &in[19].link); + &in[21].link); } /* SSS Profile */ diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c index d769a219fa0..4976d038065 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c @@ -84,52 +84,33 @@ static int gpu_shader_normal_map(GPUMaterial *mat, realnorm = GPU_constant(in[1].vec); } - negnorm = GPU_builtin(GPU_VIEW_NORMAL); + negnorm = GPU_builtin(GPU_WORLD_NORMAL); GPU_link(mat, "math_max", strength, GPU_constant(d), &strength); const char *color_to_normal_fnc_name = "color_to_normal_new_shading"; if (nm->space == SHD_SPACE_BLENDER_OBJECT || nm->space == SHD_SPACE_BLENDER_WORLD) { color_to_normal_fnc_name = "color_to_blender_normal_new_shading"; } + + GPU_link(mat, color_to_normal_fnc_name, realnorm, &realnorm); switch (nm->space) { case SHD_SPACE_TANGENT: - GPU_link(mat, "color_to_normal_new_shading", realnorm, &realnorm); GPU_link(mat, "node_normal_map", GPU_builtin(GPU_OBJECT_INFO), GPU_attribute(CD_TANGENT, nm->uv_map), - negnorm, + GPU_builtin(GPU_WORLD_NORMAL), realnorm, &realnorm); - GPU_link( - mat, "vec_math_mix", strength, realnorm, GPU_builtin(GPU_VIEW_NORMAL), &out[0].link); - /* for uniform scale this is sufficient to match Cycles */ - GPU_link(mat, - "direction_transform_m4v3", - out[0].link, - GPU_builtin(GPU_INVERSE_VIEW_MATRIX), - &out[0].link); - GPU_link(mat, "vect_normalize", out[0].link, &out[0].link); - return true; + break; case SHD_SPACE_OBJECT: case SHD_SPACE_BLENDER_OBJECT: - GPU_link(mat, - "direction_transform_m4v3", - negnorm, - GPU_builtin(GPU_INVERSE_VIEW_MATRIX), - &negnorm); - GPU_link(mat, color_to_normal_fnc_name, realnorm, &realnorm); GPU_link( mat, "direction_transform_m4v3", realnorm, GPU_builtin(GPU_OBJECT_MATRIX), &realnorm); break; case SHD_SPACE_WORLD: case SHD_SPACE_BLENDER_WORLD: - GPU_link(mat, - "direction_transform_m4v3", - negnorm, - GPU_builtin(GPU_INVERSE_VIEW_MATRIX), - &negnorm); - GPU_link(mat, color_to_normal_fnc_name, realnorm, &realnorm); + /* Nothing to do. */ break; } diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c index 5520f6f325f..118b8136693 100644 --- a/source/blender/nodes/shader/nodes/node_shader_object_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c @@ -35,13 +35,17 @@ static int node_shader_gpu_object_info(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { + Material *ma = GPU_material_get_material(mat); + /* Convert to float. */ + float index = ma ? ma->index : 0; return GPU_stack_link(mat, node, "node_object_info", in, out, GPU_builtin(GPU_OBJECT_MATRIX), - GPU_builtin(GPU_OBJECT_INFO)); + GPU_builtin(GPU_OBJECT_INFO), + GPU_constant(&index)); } static void node_shader_exec_object_info(void *UNUSED(data), diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c index 5512754d9a2..6795f48edb3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tangent.c +++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c @@ -42,13 +42,7 @@ static int node_shader_gpu_tangent(GPUMaterial *mat, NodeShaderTangent *attr = node->storage; if (attr->direction_type == SHD_TANGENT_UVMAP) { - return GPU_stack_link(mat, - node, - "node_tangentmap", - in, - out, - GPU_attribute(CD_TANGENT, ""), - GPU_builtin(GPU_INVERSE_VIEW_MATRIX)); + return GPU_stack_link(mat, node, "node_tangentmap", in, out, GPU_attribute(CD_TANGENT, "")); } else { GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); @@ -68,10 +62,9 @@ static int node_shader_gpu_tangent(GPUMaterial *mat, "node_tangent", in, out, - GPU_builtin(GPU_VIEW_NORMAL), + GPU_builtin(GPU_WORLD_NORMAL), orco, - GPU_builtin(GPU_OBJECT_MATRIX), - GPU_builtin(GPU_INVERSE_VIEW_MATRIX)); + GPU_builtin(GPU_OBJECT_MATRIX)); } } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c index fd62e8ce960..0e34f2ca9b1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c @@ -42,10 +42,6 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, { Object *ob = (Object *)node->id; - if (ob != NULL) { - invert_m4_m4(ob->imat, ob->obmat); - } - GPUNodeLink *inv_obmat = (ob != NULL) ? GPU_uniform(&ob->imat[0][0]) : GPU_builtin(GPU_INVERSE_OBJECT_MATRIX); @@ -60,8 +56,7 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, in, out, GPU_builtin(GPU_VIEW_POSITION), - GPU_builtin(GPU_VIEW_NORMAL), - GPU_builtin(GPU_INVERSE_VIEW_MATRIX), + GPU_builtin(GPU_WORLD_NORMAL), inv_obmat, GPU_builtin(GPU_CAMERA_TEXCO_FACTORS), orco, diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index c3b8bc8bfd0..615f55e4350 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -46,7 +46,6 @@ static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *no NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment"); BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); BKE_texture_colormapping_default(&tex->base.color_mapping); - tex->color_space = SHD_COLORSPACE_COLOR; tex->projection = SHD_PROJ_EQUIRECTANGULAR; BKE_imageuser_default(&tex->iuser); @@ -68,7 +67,6 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, NodeTexImage *tex_original = node_original->storage; ImageUser *iuser = &tex_original->iuser; - int isdata = tex->color_space == SHD_COLORSPACE_NONE; GPUNodeLink *outalpha; if (!ima) { @@ -89,7 +87,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, "node_tex_environment_equirectangular", in[0].link, GPU_constant(&clamp_size), - GPU_image(ima, iuser, isdata), + GPU_image(ima, iuser), &in[0].link); } else { @@ -104,7 +102,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, GPU_link(mat, "node_tex_image_linear_no_mip", in[0].link, - GPU_image(ima, iuser, isdata), + GPU_image(ima, iuser), &out[0].link, &outalpha); break; @@ -112,26 +110,19 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, GPU_link(mat, "node_tex_image_nearest", in[0].link, - GPU_image(ima, iuser, isdata), + GPU_image(ima, iuser), &out[0].link, &outalpha); break; default: - GPU_link(mat, - "node_tex_image_cubic", - in[0].link, - GPU_image(ima, iuser, isdata), - &out[0].link, - &outalpha); + GPU_link( + mat, "node_tex_image_cubic", in[0].link, GPU_image(ima, iuser), &out[0].link, &outalpha); break; } - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && - GPU_material_do_color_management(mat)) { - GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); + if (out[0].hasoutput) { + GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); } - BKE_image_release_ibuf(ima, ibuf, NULL); return true; } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 91d58bc41d0..924714e561a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -57,7 +57,6 @@ static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node) NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage"); BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); BKE_texture_colormapping_default(&tex->base.color_mapping); - tex->color_space = SHD_COLORSPACE_COLOR; BKE_imageuser_default(&tex->iuser); node->storage = tex; @@ -99,7 +98,6 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, const char *gpu_node_name = (tex->projection == SHD_PROJ_BOX) ? names_box[tex->interpolation] : names[tex->interpolation]; - bool do_color_correction = false; bool do_texco_extend = (tex->extension != SHD_IMAGE_EXTENSION_REPEAT); const bool do_texco_clip = (tex->extension == SHD_IMAGE_EXTENSION_CLIP); @@ -111,23 +109,13 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, } GPUNodeLink *norm, *col1, *col2, *col3, *input_coords, *gpu_image; - GPUNodeLink *vnor, *nor_mat_inv, *blend; + GPUNodeLink *vnor, *ob_mat, *blend; GPUNodeLink **texco = &in[0].link; - int isdata = tex->color_space == SHD_COLORSPACE_NONE; - if (!ima) { return GPU_stack_link(mat, node, "node_tex_image_empty", in, out); } - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - if ((tex->color_space == SHD_COLORSPACE_COLOR) && ibuf && - (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && - GPU_material_do_color_management(mat)) { - do_color_correction = true; - } - BKE_image_release_ibuf(ima, ibuf, NULL); - if (!*texco) { *texco = GPU_attribute(CD_MTFACE, ""); } @@ -140,25 +128,20 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, GPU_link(mat, "set_rgb", *texco, &input_coords); } if (do_texco_extend) { - GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser, isdata), texco); + GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco); } - GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata)); + GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser)); break; case SHD_PROJ_BOX: - vnor = GPU_builtin(GPU_VIEW_NORMAL); - nor_mat_inv = GPU_builtin(GPU_INVERSE_NORMAL_MATRIX); + vnor = GPU_builtin(GPU_WORLD_NORMAL); + ob_mat = GPU_builtin(GPU_OBJECT_MATRIX); blend = GPU_uniform(&tex->projection_blend); - gpu_image = GPU_image(ima, iuser, isdata); - - GPU_link(mat, "mat3_mul", vnor, nor_mat_inv, &norm); - GPU_link( - mat, gpu_node_name, *texco, norm, GPU_image(ima, iuser, isdata), &col1, &col2, &col3); - if (do_color_correction) { - GPU_link(mat, "srgb_to_linearrgb", col1, &col1); - GPU_link(mat, "srgb_to_linearrgb", col2, &col2); - GPU_link(mat, "srgb_to_linearrgb", col3, &col3); - } + gpu_image = GPU_image(ima, iuser); + + /* equivalent to normal_world_to_object */ + GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &norm); + GPU_link(mat, gpu_node_name, *texco, norm, GPU_image(ima, iuser), &col1, &col2, &col3); GPU_stack_link( mat, node, "node_tex_image_box", in, out, norm, col1, col2, col3, gpu_image, blend); break; @@ -170,9 +153,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, GPU_link(mat, "set_rgb", *texco, &input_coords); } if (do_texco_extend) { - GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser, isdata), texco); + GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco); } - GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata)); + GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser)); break; case SHD_PROJ_TUBE: @@ -182,20 +165,26 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, GPU_link(mat, "set_rgb", *texco, &input_coords); } if (do_texco_extend) { - GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser, isdata), texco); + GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco); } - GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata)); + GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser)); break; } if (tex->projection != SHD_PROJ_BOX) { if (do_texco_clip) { gpu_node_name = names_clip[tex->interpolation]; - GPU_stack_link( - mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata), out[0].link); + in[0].link = input_coords; + GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser), out[0].link); + } + } + + if (out[0].hasoutput) { + if (out[1].hasoutput) { + GPU_link(mat, "tex_color_alpha_unpremultiply", out[0].link, &out[0].link); } - if (do_color_correction) { - GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); + else { + GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link); } } diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c index cbc012040b0..ac8b49c4572 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c +++ b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c @@ -61,7 +61,7 @@ static int gpu_shader_vector_displacement(GPUMaterial *mat, in, out, GPU_attribute(CD_TANGENT, ""), - GPU_builtin(GPU_VIEW_NORMAL), + GPU_builtin(GPU_WORLD_NORMAL), GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_VIEW_MATRIX)); } diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index 79c31c8caad..710ae0433e0 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -263,8 +263,9 @@ static int pyrna_struct_keyframe_parse(PointerRNA *ptr, /* flag may be null (no option currently for remove keyframes e.g.). */ if (r_options) { - if (pyoptions && (pyrna_set_to_enum_bitfield( - rna_enum_keying_flag_items, pyoptions, r_options, error_prefix) == -1)) { + if (pyoptions && + (pyrna_set_to_enum_bitfield( + rna_enum_keying_flag_items_api, pyoptions, r_options, error_prefix) == -1)) { return -1; } @@ -299,8 +300,11 @@ char pyrna_struct_keyframe_insert_doc[] = "F-Curves.\n" " - ``INSERTKEY_VISUAL`` Insert keyframes based on 'visual transforms'.\n" " - ``INSERTKEY_XYZ_TO_RGB`` Color for newly added transformation F-Curves (Location, " - "Rotation, Scale)\n" - " and also Color is based on the transform axis.\n" + "Rotation, Scale) is based on the transform axis.\n" + " - ``INSERTKEY_REPLACE`` Only replace already exising keyframes.\n" + " - ``INSERTKEY_AVAILABLE`` Only insert into already existing F-Curves.\n" + " - ``INSERTKEY_CYCLE_AWARE`` Take cyclic extrapolation into account " + "(Cycle-Aware Keying option).\n" " :type flag: set\n" " :return: Success of keyframe insertion.\n" " :rtype: boolean\n"; diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 46d2df0acb5..db051d58d6c 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -284,21 +284,21 @@ bool RE_WriteRenderViewsMovie(struct ReportList *reports, bool preview); /* only RE_NewRender() needed, main Blender render calls */ -void RE_BlenderFrame(struct Render *re, - struct Main *bmain, - struct Scene *scene, - struct ViewLayer *single_layer, - struct Object *camera_override, - int frame, - const bool write_still); -void RE_BlenderAnim(struct Render *re, +void RE_RenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, struct ViewLayer *single_layer, struct Object *camera_override, - int sfra, - int efra, - int tfra); + int frame, + const bool write_still); +void RE_RenderAnim(struct Render *re, + struct Main *bmain, + struct Scene *scene, + struct ViewLayer *single_layer, + struct Object *camera_override, + int sfra, + int efra, + int tfra); #ifdef WITH_FREESTYLE void RE_RenderFreestyleStrokes(struct Render *re, struct Main *bmain, @@ -307,6 +307,9 @@ void RE_RenderFreestyleStrokes(struct Render *re, void RE_RenderFreestyleExternal(struct Render *re); #endif +/* Free memory and clear runtime data which is only needed during rendering. */ +void RE_CleanAfterRender(struct Render *re); + void RE_SetActiveRenderView(struct Render *re, const char *viewname); const char *RE_GetActiveRenderView(struct Render *re); diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c index 237debceb83..878a774ab37 100644 --- a/source/blender/render/intern/source/multires_bake.c +++ b/source/blender/render/intern/source/multires_bake.c @@ -1458,7 +1458,8 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter); - ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID; + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + BKE_image_mark_dirty(ima, ibuf); if (ibuf->rect_float) { ibuf->userflags |= IB_RECT_INVALID; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 7d3002ea71d..9c1c713ab94 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1988,7 +1988,7 @@ const char *RE_GetActiveRenderView(Render *re) /* evaluating scene options for general Blender render */ static int render_initialize_from_main(Render *re, - RenderData *rd, + const RenderData *rd, Main *bmain, Scene *scene, ViewLayer *single_layer, @@ -2072,13 +2072,13 @@ void RE_SetReports(Render *re, ReportList *reports) } /* general Blender frame render call */ -void RE_BlenderFrame(Render *re, - Main *bmain, - Scene *scene, - ViewLayer *single_layer, - Object *camera_override, - int frame, - const bool write_still) +void RE_RenderFrame(Render *re, + Main *bmain, + Scene *scene, + ViewLayer *single_layer, + Object *camera_override, + int frame, + const bool write_still) { BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT); @@ -2090,6 +2090,7 @@ void RE_BlenderFrame(Render *re, if (render_initialize_from_main( re, &scene->r, bmain, scene, single_layer, camera_override, 0, 0)) { + const RenderData rd = scene->r; MEM_reset_peak_memory(); BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE); @@ -2097,18 +2098,18 @@ void RE_BlenderFrame(Render *re, do_render_all_options(re); if (write_still && !G.is_break) { - if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { + if (BKE_imtype_is_movie(rd.im_format.imtype)) { /* operator checks this but in case its called from elsewhere */ printf("Error: cant write single images with a movie format!\n"); } else { char name[FILE_MAX]; BKE_image_path_from_imformat(name, - scene->r.pic, + rd.pic, BKE_main_blendfile_path(bmain), scene->r.cfra, - &scene->r.im_format, - (scene->r.scemode & R_EXTENSION) != 0, + &rd.im_format, + (rd.scemode & R_EXTENSION) != 0, false, NULL); @@ -2117,7 +2118,8 @@ void RE_BlenderFrame(Render *re, } } - BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */ + /* keep after file save */ + BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); if (write_still) { BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE); } @@ -2126,8 +2128,7 @@ void RE_BlenderFrame(Render *re, BLI_callback_exec( re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE); - /* Destroy the opengl context in the correct thread. */ - RE_gl_context_destroy(re); + RE_CleanAfterRender(re); /* UGLY WARNING */ G.is_rendering = false; @@ -2427,7 +2428,10 @@ static int do_write_image_or_movie(Render *re, return ok; } -static void get_videos_dimensions(Render *re, RenderData *rd, size_t *r_width, size_t *r_height) +static void get_videos_dimensions(const Render *re, + const RenderData *rd, + size_t *r_width, + size_t *r_height) { size_t width, height; if (re->r.mode & R_BORDER) { @@ -2461,23 +2465,23 @@ static void re_movie_free_all(Render *re, bMovieHandle *mh, int totvideos) } /* saves images to disk */ -void RE_BlenderAnim(Render *re, - Main *bmain, - Scene *scene, - ViewLayer *single_layer, - Object *camera_override, - int sfra, - int efra, - int tfra) -{ - RenderData rd = scene->r; +void RE_RenderAnim(Render *re, + Main *bmain, + Scene *scene, + ViewLayer *single_layer, + Object *camera_override, + int sfra, + int efra, + int tfra) +{ + const RenderData rd = scene->r; bMovieHandle *mh = NULL; - int cfrao = scene->r.cfra; + const int cfrao = rd.cfra; int nfra, totrendered = 0, totskipped = 0; const int totvideos = BKE_scene_multiview_num_videos_get(&rd); - const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype); - const bool is_multiview_name = ((scene->r.scemode & R_MULTIVIEW) != 0 && - (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)); + const bool is_movie = BKE_imtype_is_movie(rd.im_format.imtype); + const bool is_multiview_name = ((rd.scemode & R_MULTIVIEW) != 0 && + (rd.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL)); BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT); @@ -2493,7 +2497,7 @@ void RE_BlenderAnim(Render *re, get_videos_dimensions(re, &rd, &width, &height); - mh = BKE_movie_handle_get(scene->r.im_format.imtype); + mh = BKE_movie_handle_get(rd.im_format.imtype); if (mh == NULL) { BKE_report(re->reports, RPT_ERROR, "Movie format unsupported"); return; @@ -2530,23 +2534,6 @@ void RE_BlenderAnim(Render *re, for (nfra = sfra, scene->r.cfra = sfra; scene->r.cfra <= efra; scene->r.cfra++) { char name[FILE_MAX]; - /* Special case for 'mh->get_next_frame' - * this overrides regular frame stepping logic */ - if (mh && mh->get_next_frame) { - while (G.is_break == false) { - int nfra_test = mh->get_next_frame(re->movie_ctx_arr[0], &re->r, re->reports); - if (nfra_test >= 0 && nfra_test >= sfra && nfra_test <= efra) { - nfra = nfra_test; - break; - } - else { - if (re->test_break(re->tbh)) { - G.is_break = true; - } - } - } - } - /* Here is a feedback loop exists -- render initialization requires updated * render layers settings which could be animated, but scene evaluation for * the frame happens later because it depends on what layers are visible to @@ -2582,18 +2569,18 @@ void RE_BlenderAnim(Render *re, /* Touch/NoOverwrite options are only valid for image's */ if (is_movie == false) { - if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH)) { + if (rd.mode & (R_NO_OVERWRITE | R_TOUCH)) { BKE_image_path_from_imformat(name, - scene->r.pic, + rd.pic, BKE_main_blendfile_path(bmain), scene->r.cfra, - &scene->r.im_format, - (scene->r.scemode & R_EXTENSION) != 0, + &rd.im_format, + (rd.scemode & R_EXTENSION) != 0, true, NULL); } - if (scene->r.mode & R_NO_OVERWRITE) { + if (rd.mode & R_NO_OVERWRITE) { if (!is_multiview_name) { if (BLI_exists(name)) { printf("skipping existing frame \"%s\"\n", name); @@ -2626,7 +2613,7 @@ void RE_BlenderAnim(Render *re, } } - if (scene->r.mode & R_TOUCH) { + if (rd.mode & R_TOUCH) { if (!is_multiview_name) { if (!BLI_exists(name)) { BLI_make_existing_file(name); /* makes the dir if its not there */ @@ -2675,7 +2662,7 @@ void RE_BlenderAnim(Render *re, if (G.is_break == true) { /* remove touched file */ if (is_movie == false) { - if ((scene->r.mode & R_TOUCH)) { + if ((rd.mode & R_TOUCH)) { if (!is_multiview_name) { if ((BLI_file_size(name) == 0)) { /* BLI_exists(name) is implicit */ @@ -2706,8 +2693,8 @@ void RE_BlenderAnim(Render *re, } if (G.is_break == false) { - BLI_callback_exec( - re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */ + /* keep after file save */ + BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE); } } @@ -2730,8 +2717,7 @@ void RE_BlenderAnim(Render *re, re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE); BKE_sound_reset_scene_specs(scene); - /* Destroy the opengl context in the correct thread. */ - RE_gl_context_destroy(re); + RE_CleanAfterRender(re); /* UGLY WARNING */ G.is_rendering = false; @@ -2756,6 +2742,12 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce) do_render_3d(re); } +void RE_CleanAfterRender(Render *re) +{ + /* Destroy the opengl context in the correct thread. */ + RE_gl_context_destroy(re); +} + /* note; repeated win/disprect calc... solve that nicer, also in compo */ /* only the temp file! */ diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index f1037dadf85..bd02a1e13c1 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -373,7 +373,8 @@ int WM_operator_confirm_message_ex(struct bContext *C, struct wmOperator *op, const char *title, const int icon, - const char *message); + const char *message, + const short opcontext); int WM_operator_confirm_message(struct bContext *C, struct wmOperator *op, const char *message); /* operator api */ @@ -660,6 +661,7 @@ enum { WM_JOB_TYPE_SHADER_COMPILATION, WM_JOB_TYPE_STUDIOLIGHT, WM_JOB_TYPE_LIGHT_BAKE, + WM_JOB_TYPE_FSMENU_BOOKMARK_VALIDATE, /* add as needed, screencast, seq proxy build * if having hard coded values is a problem */ }; diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 154c4837a68..b3c36857dce 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -605,7 +605,7 @@ typedef struct wmOperatorType { * that the operator might still fail to execute even if this return true */ bool (*poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT; - /* Use to check of properties should be displayed in auto-generated UI. + /* Use to check if properties should be displayed in auto-generated UI. * Use 'check' callback to enforce refreshing. */ bool (*poll_property)(const struct bContext *C, struct wmOperator *op, diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h index 1c298f378a4..7d38194db1b 100644 --- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h +++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h @@ -198,6 +198,10 @@ struct wmGizmo { /** For single click button gizmos, use a different part as a fallback, -1 when unused. */ int drag_part; + /** Distance to bias this gizmo above others when picking + * (in worldspace, scaled by the gizmo scale - when used). */ + float select_bias; + /** * Transformation of the gizmo in 2d or 3d space. * - Matrix axis are expected to be unit length (scale is applied after). diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c index 31c5e1fb94c..9f36af8b616 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c @@ -25,8 +25,10 @@ #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_math_bits.h" #include "BLI_rect.h" #include "BLI_ghash.h" +#include "BLI_array.h" #include "BKE_context.h" #include "BKE_global.h" @@ -470,7 +472,8 @@ void WM_gizmomap_draw(wmGizmoMap *gzmap, static void gizmo_draw_select_3D_loop(const bContext *C, ListBase *visible_gizmos, - const wmGizmo *gz_stop) + const wmGizmo *gz_stop, + bool *r_use_select_bias) { int select_id = 0; wmGizmo *gz; @@ -511,6 +514,10 @@ static void gizmo_draw_select_3D_loop(const bContext *C, is_depth_skip_prev = is_depth_skip; } + if (gz->select_bias != 0.0) { + *r_use_select_bias = true; + } + /* pass the selection id shifted by 8 bits. Last 8 bits are used for selected gizmo part id */ gz->type->draw_select(C, gz, select_id << 8); @@ -543,24 +550,68 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos, ED_view3d_draw_setup_view( CTX_wm_window(C), CTX_data_depsgraph(C), CTX_data_scene(C), ar, v3d, NULL, NULL, &rect); + bool use_select_bias = false; + GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0); /* do the drawing */ - gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop); + gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop, &use_select_bias); hits = GPU_select_end(); if (hits > 0) { GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits); - gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop); + gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop, &use_select_bias); GPU_select_end(); } ED_view3d_draw_setup_view( CTX_wm_window(C), CTX_data_depsgraph(C), CTX_data_scene(C), ar, v3d, NULL, NULL, NULL); - const GLuint *hit_near = GPU_select_buffer_near(buffer, hits); - - return hit_near ? hit_near[3] : -1; + if (use_select_bias && (hits > 1)) { + wmGizmo **gizmo_table = NULL; + BLI_array_staticdeclare(gizmo_table, 1024); + for (LinkData *link = visible_gizmos->first; link; link = link->next) { + BLI_array_append(gizmo_table, link->data); + } + float co_direction[3]; + float co_screen[3] = {co[0], co[1], 0.0f}; + ED_view3d_win_to_vector(ar, (float[2]){UNPACK2(co)}, co_direction); + + RegionView3D *rv3d = ar->regiondata; + const int viewport[4] = {0, 0, ar->winx, ar->winy}; + float co_3d_origin[3]; + + GPU_matrix_unproject_model_inverted( + co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin); + + GLuint *buf_iter = buffer; + int hit_found = -1; + float dot_best = FLT_MAX; + + for (int i = 0; i < hits; i++, buf_iter += 4) { + BLI_assert(buf_iter[3] != -1); + wmGizmo *gz = gizmo_table[buf_iter[3] >> 8]; + float co_3d[3]; + co_screen[2] = int_as_float(buf_iter[1]); + GPU_matrix_unproject_model_inverted(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d); + float select_bias = gz->select_bias; + if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) { + select_bias *= gz->scale_final; + } + sub_v3_v3(co_3d, co_3d_origin); + const float dot_test = dot_v3v3(co_3d, co_direction) - select_bias; + if (dot_best > dot_test) { + dot_best = dot_test; + hit_found = buf_iter[3]; + } + } + BLI_array_free(gizmo_table); + return hit_found; + } + else { + const GLuint *hit_near = GPU_select_buffer_near(buffer, hits); + return hit_near ? hit_near[3] : -1; + } } /** diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index 30311d83509..e4ecf7e6e94 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -442,7 +442,7 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect) drag_rect_minmax(rect, x, y, x + iconsize, y + iconsize); } else { - UI_icon_draw_aspect(x, y, drag->icon, 1.0f / UI_DPI_FAC, 0.8, text_col); + UI_icon_draw_ex(x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false); } } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index a13b28b7853..13b6260e2b9 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -86,7 +86,6 @@ #include "RNA_enum_types.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" /* Motion in pixels allowed before we don't consider single/double click, * or detect the start of a tweak event. */ @@ -3091,12 +3090,10 @@ void wm_event_do_handlers(bContext *C) wm_event_free_all(win); } else { - Depsgraph *depsgraph = CTX_data_depsgraph(C); Scene *scene = WM_window_get_active_scene(win); - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); if (scene) { - const int is_playing_sound = BKE_sound_scene_playing(scene_eval); + int is_playing_sound = BKE_sound_scene_playing(scene); if (is_playing_sound != -1) { bool is_playing_screen; @@ -3116,6 +3113,7 @@ void wm_event_do_handlers(bContext *C) int ncfra = time * (float)FPS + 0.5f; if (ncfra != scene->r.cfra) { scene->r.cfra = ncfra; + Depsgraph *depsgraph = CTX_data_depsgraph(C); ED_update_for_newframe(CTX_data_main(C), depsgraph); WM_event_add_notifier(C, NC_WINDOW, NULL); } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 6d90d4745a6..304daa2dd00 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -716,26 +716,6 @@ const char *WM_init_state_app_template_get(void) return wm_init_state_app_template.override ? wm_init_state_app_template.app_template : NULL; } -static bool wm_app_template_has_userpref(const char *app_template) -{ - /* Test if app template provides a userpref.blend. If not, we will - * share user preferences with the rest of Blender. */ - if (!app_template && app_template[0]) { - return false; - } - - char app_template_path[FILE_MAX]; - if (!BKE_appdir_app_template_id_search( - app_template, app_template_path, sizeof(app_template_path))) { - return false; - } - - char userpref_path[FILE_MAX]; - BLI_path_join( - userpref_path, sizeof(userpref_path), app_template_path, BLENDER_USERPREF_FILE, NULL); - return BLI_exists(userpref_path); -} - /** * Called on startup, (context entirely filled with NULLs) * or called for 'New File' both startup.blend and userpref.blend are checked. @@ -758,6 +738,7 @@ void wm_homefile_read(bContext *C, ReportList *reports, bool use_factory_settings, bool use_empty_data, + bool use_data, bool use_userdef, const char *filepath_startup_override, const char *app_template_override, @@ -788,7 +769,14 @@ void wm_homefile_read(bContext *C, * And in this case versioning code is to be run. */ bool read_userdef_from_memory = false; - eBLOReadSkip skip_flags = use_userdef ? 0 : BLO_READ_SKIP_USERDEF; + eBLOReadSkip skip_flags = 0; + + if (use_data == false) { + skip_flags |= BLO_READ_SKIP_DATA; + } + if (use_userdef == false) { + skip_flags |= BLO_READ_SKIP_USERDEF; + } /* True if we load startup.blend from memory * or use app-template startup.blend which the user hasn't saved. */ @@ -801,14 +789,16 @@ void wm_homefile_read(bContext *C, SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_FLAG_SCRIPT_AUTOEXEC); } - BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); + if (use_data) { + BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); - UI_view2d_zoom_cache_reset(); + G.relbase_valid = 0; - G.relbase_valid = 0; + /* put aside screens to match with persistent windows later */ + wm_window_match_init(C, &wmbase); + } - /* put aside screens to match with persistent windows later */ - wm_window_match_init(C, &wmbase); + UI_view2d_zoom_cache_reset(); filepath_startup[0] = '\0'; filepath_userdef[0] = '\0'; @@ -931,7 +921,9 @@ void wm_homefile_read(bContext *C, } if (success) { if (update_defaults) { - BLO_update_defaults_startup_blend(CTX_data_main(C), app_template); + if (use_data) { + BLO_update_defaults_startup_blend(CTX_data_main(C), app_template); + } } is_factory_startup = filepath_startup_is_factory; } @@ -1010,10 +1002,12 @@ void wm_homefile_read(bContext *C, BLI_strncpy(U.app_template, app_template_override, sizeof(U.app_template)); } - /* Prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. - * Screws up autosaves otherwise can remove this eventually, - * only in a 2.53 and older, now its not written. */ - G.fileflags &= ~G_FILE_RELATIVE_REMAP; + if (use_data) { + /* Prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. + * Screws up autosaves otherwise can remove this eventually, + * only in a 2.53 and older, now its not written. */ + G.fileflags &= ~G_FILE_RELATIVE_REMAP; + } bmain = CTX_data_main(C); @@ -1023,8 +1017,10 @@ void wm_homefile_read(bContext *C, reset_app_template = true; } - /* match the read WM with current WM */ - wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm); + if (use_data) { + /* match the read WM with current WM */ + wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm); + } if (use_factory_settings) { /* Clear keymaps because the current default keymap may have been initialized @@ -1036,14 +1032,16 @@ void wm_homefile_read(bContext *C, } } - WM_check(C); /* opens window(s), checks keymaps */ + if (use_data) { + WM_check(C); /* opens window(s), checks keymaps */ - bmain->name[0] = '\0'; + bmain->name[0] = '\0'; - /* start with save preference untitled.blend */ - G.save_over = 0; + /* start with save preference untitled.blend */ + G.save_over = 0; - wm_file_read_post(C, true, is_factory_startup, reset_app_template); + wm_file_read_post(C, true, is_factory_startup, reset_app_template); + } if (r_is_factory_startup) { *r_is_factory_startup = is_factory_startup; @@ -1694,69 +1692,138 @@ void WM_OT_userpref_autoexec_path_remove(wmOperatorType *ot) static int wm_userpref_write_exec(bContext *C, wmOperator *op) { wmWindowManager *wm = CTX_wm_manager(C); - char filepath[FILE_MAX]; - const char *cfgdir; - bool ok = true; - bool use_template_userpref = wm_app_template_has_userpref(U.app_template); - /* update keymaps in user preferences */ + /* Update keymaps in user preferences. */ WM_keyconfig_update(wm); - if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) { - bool ok_write; - BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); + const bool ok = BKE_blendfile_userdef_write_all(op->reports); - printf("Writing userprefs: '%s' ", filepath); - if (use_template_userpref) { - ok_write = BKE_blendfile_userdef_write_app_template(filepath, op->reports); - } - else { - ok_write = BKE_blendfile_userdef_write(filepath, op->reports); - } + return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} - if (ok_write) { - printf("ok\n"); - } - else { - printf("fail\n"); - ok = false; - } - } - else { - BKE_report(op->reports, RPT_ERROR, "Unable to create userpref path"); - } +void WM_OT_save_userpref(wmOperatorType *ot) +{ + ot->name = "Save Preferences"; + ot->idname = "WM_OT_save_userpref"; + ot->description = "Save preferences separately, overrides startup file preferences"; - if (use_template_userpref) { - if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) { - /* Also save app-template prefs */ - BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); + ot->invoke = WM_operator_confirm; + ot->exec = wm_userpref_write_exec; +} - printf("Writing userprefs app-template: '%s' ", filepath); - if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) { - printf("ok\n"); +static void rna_struct_update_when_changed(bContext *C, + Main *bmain, + PointerRNA *ptr_a, + PointerRNA *ptr_b) +{ + CollectionPropertyIterator iter; + PropertyRNA *iterprop = RNA_struct_iterator_property(ptr_a->type); + BLI_assert(ptr_a->type == ptr_b->type); + RNA_property_collection_begin(ptr_a, iterprop, &iter); + for (; iter.valid; RNA_property_collection_next(&iter)) { + PropertyRNA *prop = iter.ptr.data; + if (STREQ(RNA_property_identifier(prop), "rna_type")) { + continue; + } + switch (RNA_property_type(prop)) { + case PROP_POINTER: { + PointerRNA ptr_sub_a = RNA_property_pointer_get(ptr_a, prop); + PointerRNA ptr_sub_b = RNA_property_pointer_get(ptr_b, prop); + rna_struct_update_when_changed(C, bmain, &ptr_sub_a, &ptr_sub_b); + break; } - else { - printf("fail\n"); - ok = false; + case PROP_COLLECTION: + /* Don't handle collections. */ + break; + default: { + if (!RNA_property_equals(bmain, ptr_a, ptr_b, prop, RNA_EQ_STRICT)) { + RNA_property_update(C, ptr_b, prop); + } } } - else { - BKE_report(op->reports, RPT_ERROR, "Unable to create app-template userpref path"); - ok = false; - } } + RNA_property_collection_end(&iter); +} - return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +static void wm_userpref_update_when_changed(bContext *C, + Main *bmain, + UserDef *userdef_prev, + UserDef *userdef_curr) +{ + PointerRNA ptr_a, ptr_b; + RNA_pointer_create(NULL, &RNA_Preferences, userdef_prev, &ptr_a); + RNA_pointer_create(NULL, &RNA_Preferences, userdef_curr, &ptr_b); + const bool is_dirty = userdef_curr->runtime.is_dirty; + + rna_struct_update_when_changed(C, bmain, &ptr_a, &ptr_b); + +#ifdef WITH_PYTHON + BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()"); +#endif + + WM_keyconfig_reload(C); + userdef_curr->runtime.is_dirty = is_dirty; } -void WM_OT_save_userpref(wmOperatorType *ot) +static int wm_userpref_read_exec(bContext *C, wmOperator *op) { - ot->name = "Save Preferences"; - ot->idname = "WM_OT_save_userpref"; - ot->description = "Save preferences separately, overrides startup file preferences"; + const bool use_data = false; + const bool use_userdef = true; + const bool use_factory_settings = STREQ(op->type->idname, "WM_OT_read_factory_userpref"); + + UserDef U_backup = U; + + wm_homefile_read(C, + op->reports, + use_factory_settings, + false, + use_data, + use_userdef, + NULL, + WM_init_state_app_template_get(), + NULL); + +#define USERDEF_RESTORE(member) \ + { \ + U.member = U_backup.member; \ + } \ + ((void)0) + + USERDEF_RESTORE(userpref); + +#undef USERDEF_RESTORE + + Main *bmain = CTX_data_main(C); + + wm_userpref_update_when_changed(C, bmain, &U_backup, &U); + + if (use_factory_settings) { + U.runtime.is_dirty = true; + } + + WM_event_add_notifier(C, NC_WINDOW, NULL); + + return OPERATOR_FINISHED; +} + +void WM_OT_read_userpref(wmOperatorType *ot) +{ + ot->name = "Load Preferences"; + ot->idname = "WM_OT_read_userpref"; + ot->description = "Load last saved preferences"; ot->invoke = WM_operator_confirm; - ot->exec = wm_userpref_write_exec; + ot->exec = wm_userpref_read_exec; +} + +void WM_OT_read_factory_userpref(wmOperatorType *ot) +{ + ot->name = "Load Factory Preferences"; + ot->idname = "WM_OT_read_factory_userpref"; + ot->description = "Load default preferences"; + + ot->invoke = WM_operator_confirm; + ot->exec = wm_userpref_read_exec; } static int wm_history_file_read_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) @@ -1816,14 +1883,15 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op) PropertyRNA *prop_app_template = RNA_struct_find_property(op->ptr, "app_template"); const bool use_splash = !use_factory_settings && RNA_boolean_get(op->ptr, "use_splash"); const bool use_empty_data = RNA_boolean_get(op->ptr, "use_empty"); + const bool use_temporary_preferences = RNA_boolean_get(op->ptr, "use_temporary_preferences"); if (prop_app_template && RNA_property_is_set(op->ptr, prop_app_template)) { RNA_property_string_get(op->ptr, prop_app_template, app_template_buf); app_template = app_template_buf; /* Always load preferences when switching templates with own preferences. */ - use_userdef = wm_app_template_has_userpref(app_template) || - wm_app_template_has_userpref(U.app_template); + use_userdef = BKE_appdir_app_template_has_userpref(app_template) || + BKE_appdir_app_template_has_userpref(U.app_template); /* Turn override off, since we're explicitly loading a different app-template. */ WM_init_state_app_template_set(NULL); @@ -1833,10 +1901,12 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op) app_template = WM_init_state_app_template_get(); } + bool use_data = true; wm_homefile_read(C, op->reports, use_factory_settings, use_empty_data, + use_data, use_userdef, filepath, app_template, @@ -1844,6 +1914,8 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op) if (use_splash) { WM_init_splash(C); } + SET_FLAG_FROM_TEST(G.f, use_temporary_preferences, G_FLAG_USERPREF_NO_SAVE_ON_EXIT); + return OPERATOR_FINISHED; } @@ -1858,6 +1930,24 @@ static int wm_homefile_read_invoke(bContext *C, wmOperator *op, const wmEvent *U } } +static void read_homefile_props(wmOperatorType *ot) +{ + PropertyRNA *prop; + + prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + prop = RNA_def_boolean(ot->srna, + "use_temporary_preferences", + false, + "Temporary Preferences", + "Don't save preferences on exit"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); +} + void WM_OT_read_homefile(wmOperatorType *ot) { PropertyRNA *prop; @@ -1877,23 +1967,17 @@ void WM_OT_read_homefile(wmOperatorType *ot) ot->srna, "load_ui", true, "Load UI", "Load user interface setup from the .blend file"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - /* So the splash can be kept open after loading a file (for templates). */ prop = RNA_def_boolean(ot->srna, "use_splash", false, "Splash", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + read_homefile_props(ot); /* omit poll to run in background mode */ } void WM_OT_read_factory_settings(wmOperatorType *ot) { - PropertyRNA *prop; - ot->name = "Load Factory Settings"; ot->idname = "WM_OT_read_factory_settings"; ot->description = "Load default file and preferences"; @@ -1901,12 +1985,7 @@ void WM_OT_read_factory_settings(wmOperatorType *ot) ot->invoke = WM_operator_confirm; ot->exec = wm_homefile_read_exec; - prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - - prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - + read_homefile_props(ot); /* omit poll to run in background mode */ } @@ -1939,13 +2018,83 @@ static bool wm_file_read_opwrap(bContext *C, return success; } -/* currently fits in a pointer */ -struct FileRuntime { - bool is_untrusted; +/* Generic operator state utilities + *********************************************/ + +static void create_operator_state(wmOperatorType *ot, int first_state) +{ + PropertyRNA *prop = RNA_def_int( + ot->srna, "state", first_state, INT32_MIN, INT32_MAX, "State", "", INT32_MIN, INT32_MAX); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_flag(prop, PROP_HIDDEN); +} + +static int get_operator_state(wmOperator *op) +{ + return RNA_int_get(op->ptr, "state"); +} + +static void set_next_operator_state(wmOperator *op, int state) +{ + RNA_int_set(op->ptr, "state", state); +} + +typedef struct OperatorDispatchTarget { + int state; + int (*run)(bContext *C, wmOperator *op); +} OperatorDispatchTarget; + +static int operator_state_dispatch(bContext *C, wmOperator *op, OperatorDispatchTarget *targets) +{ + int state = get_operator_state(op); + for (int i = 0; targets[i].run; i++) { + OperatorDispatchTarget target = targets[i]; + if (target.state == state) { + return target.run(C, op); + } + } + BLI_assert(false); + return OPERATOR_CANCELLED; +} + +/* Open Mainfile operator + ********************************************/ + +enum { + OPEN_MAINFILE_STATE_DISCARD_CHANGES, + OPEN_MAINFILE_STATE_SELECT_FILE_PATH, + OPEN_MAINFILE_STATE_OPEN, }; -static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int wm_open_mainfile_dispatch(bContext *C, wmOperator *op); + +static int wm_open_mainfile__discard_changes(bContext *C, wmOperator *op) +{ + if (RNA_boolean_get(op->ptr, "display_file_selector")) { + set_next_operator_state(op, OPEN_MAINFILE_STATE_SELECT_FILE_PATH); + } + else { + set_next_operator_state(op, OPEN_MAINFILE_STATE_OPEN); + } + + wmWindowManager *wm = CTX_wm_manager(C); + if (U.uiflag & USER_SAVE_PROMPT && !wm->file_saved) { + return WM_operator_confirm_message_ex(C, + op, + "Warning", + ICON_INFO, + "Changes in current file will be lost. Continue?", + WM_OP_INVOKE_DEFAULT); + } + else { + return wm_open_mainfile_dispatch(C, op); + } +} + +static int wm_open_mainfile__select_file_path(bContext *C, wmOperator *op) { + set_next_operator_state(op, OPEN_MAINFILE_STATE_OPEN); + Main *bmain = CTX_data_main(C); const char *openname = BKE_main_blendfile_path(bmain); @@ -1973,7 +2122,7 @@ static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U return OPERATOR_RUNNING_MODAL; } -static int wm_open_mainfile_exec(bContext *C, wmOperator *op) +static int wm_open_mainfile__open(bContext *C, wmOperator *op) { char filepath[FILE_MAX]; bool success; @@ -2011,6 +2160,33 @@ static int wm_open_mainfile_exec(bContext *C, wmOperator *op) } } +static OperatorDispatchTarget wm_open_mainfile_dispatch_targets[] = { + {OPEN_MAINFILE_STATE_DISCARD_CHANGES, wm_open_mainfile__discard_changes}, + {OPEN_MAINFILE_STATE_SELECT_FILE_PATH, wm_open_mainfile__select_file_path}, + {OPEN_MAINFILE_STATE_OPEN, wm_open_mainfile__open}, + {0, NULL}, +}; + +static int wm_open_mainfile_dispatch(bContext *C, wmOperator *op) +{ + return operator_state_dispatch(C, op, wm_open_mainfile_dispatch_targets); +} + +static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + return wm_open_mainfile_dispatch(C, op); +} + +static int wm_open_mainfile_exec(bContext *C, wmOperator *op) +{ + return wm_open_mainfile__open(C, op); +} + +/* currently fits in a pointer */ +struct FileRuntime { + bool is_untrusted; +}; + static bool wm_open_mainfile_check(bContext *UNUSED(C), wmOperator *op) { struct FileRuntime *file_info = (struct FileRuntime *)&op->customdata; @@ -2091,6 +2267,12 @@ void WM_OT_open_mainfile(wmOperatorType *ot) "Trusted Source", "Allow .blend file to execute scripts automatically, default available from " "system preferences"); + + PropertyRNA *prop = RNA_def_boolean( + ot->srna, "display_file_selector", true, "Display File Selector", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + create_operator_state(ot, OPEN_MAINFILE_STATE_DISCARD_CHANGES); } /** \} */ @@ -2629,7 +2811,7 @@ void wm_test_autorun_warning(bContext *C) if (win) { wmWindow *prevwin = CTX_wm_window(C); CTX_wm_window_set(C, win); - UI_popup_block_invoke(C, block_create_autorun_warning, NULL); + UI_popup_block_invoke(C, block_create_autorun_warning, NULL, NULL); CTX_wm_window_set(C, prevwin); } } diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 5529aec1aa5..04a3115992f 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -52,6 +52,7 @@ #include "BLO_writefile.h" #include "BLO_undofile.h" +#include "BKE_blendfile.h" #include "BKE_blender.h" #include "BKE_blender_undo.h" #include "BKE_context.h" @@ -64,8 +65,6 @@ #include "BKE_node.h" #include "BKE_report.h" #include "BKE_screen.h" -#include "BKE_scene.h" -#include "BKE_sound.h" #include "BKE_keyconfig.h" #include "BKE_addon.h" @@ -124,7 +123,6 @@ #include "COM_compositor.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "DRW_engine.h" @@ -197,30 +195,6 @@ void WM_init_opengl(Main *bmain) opengl_is_init = true; } -static void sound_jack_sync_callback(Main *bmain, int mode, float time) -{ - /* Ugly: Blender doesn't like it when the animation is played back during rendering. */ - if (G.is_rendering) { - return; - } - - wmWindowManager *wm = bmain->wm.first; - - for (wmWindow *window = wm->windows.first; window != NULL; window = window->next) { - Scene *scene = WM_window_get_active_scene(window); - if ((scene->audio.flag & AUDIO_SYNC) == 0) { - continue; - } - ViewLayer *view_layer = WM_window_get_active_view_layer(window); - Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false); - if (depsgraph == NULL) { - continue; - } - Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); - BKE_sound_jack_scene_update(scene_eval, mode, time); - } -} - /* only called once, for startup */ void WM_init(bContext *C, int argc, const char **argv) { @@ -228,7 +202,6 @@ void WM_init(bContext *C, int argc, const char **argv) if (!G.background) { wm_ghost_init(C); /* note: it assigns C to ghost! */ wm_init_cursor_data(); - BKE_sound_jack_sync_callback_set(sound_jack_sync_callback); } GHOST_CreateSystemPaths(); @@ -282,11 +255,15 @@ void WM_init(bContext *C, int argc, const char **argv) /* get the default database, plus a wm */ bool is_factory_startup = true; + const bool use_data = true; + const bool use_userdef = true; + wm_homefile_read(C, NULL, G.factory_startup, false, - true, + use_data, + use_userdef, NULL, WM_init_state_app_template_get(), &is_factory_startup); @@ -497,6 +474,14 @@ void WM_exit_ext(bContext *C, const bool do_python) WM_event_remove_handlers(C, &win->modalhandlers); ED_screen_exit(C, win, WM_window_get_active_screen(win)); } + + if (!G.background) { + if ((U.pref_flag & USER_PREF_FLAG_SAVE) && ((G.f & G_FLAG_USERPREF_NO_SAVE_ON_EXIT) == 0)) { + if (U.runtime.is_dirty) { + BKE_blendfile_userdef_write_all(NULL); + } + } + } } BLI_timer_free(); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index bae9a5de1e6..4bcbce028b1 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -310,6 +310,7 @@ bool WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf) if (BLI_findindex(&wm->keyconfigs, keyconf) != -1) { if (STREQLEN(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr))) { BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr)); + U.runtime.is_dirty = true; WM_keyconfig_update_tag(NULL, NULL); } @@ -360,6 +361,9 @@ void WM_keyconfig_set_active(wmWindowManager *wm, const char *idname) WM_keyconfig_update(wm); BLI_strncpy(U.keyconfigstr, idname, sizeof(U.keyconfigstr)); + if (wm->initialized & WM_KEYCONFIG_IS_INITIALIZED) { + U.runtime.is_dirty = true; + } WM_keyconfig_update_tag(NULL, NULL); WM_keyconfig_update(wm); @@ -1120,7 +1124,8 @@ const char *WM_key_event_string(const short type, const bool compact) if (platform == MACOS) { icon_glyph = "\xe2\x87\xa7"; } - return key_event_icon_or_text(font_id, IFACE_("Shift"), icon_glyph); + return key_event_icon_or_text( + font_id, CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "Shift"), icon_glyph); } case LEFTCTRLKEY: case RIGHTCTRLKEY: diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index ece57f5a63b..3ad7247d993 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -94,7 +94,9 @@ void WM_operator_properties_filesel(wmOperatorType *ot, } if (flag & WM_FILESEL_FILES) { - RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", ""); + prop = RNA_def_collection_runtime( + ot->srna, "files", &RNA_OperatorFileListElement, "Files", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } if (action == FILE_SAVE) { @@ -344,11 +346,11 @@ void WM_operator_properties_gesture_box(wmOperatorType *ot) void WM_operator_properties_select_operation(wmOperatorType *ot) { static const EnumPropertyItem select_mode_items[] = { - {SEL_OP_SET, "SET", 0, "New", ""}, - {SEL_OP_ADD, "ADD", 0, "Add", ""}, - {SEL_OP_SUB, "SUB", 0, "Subtract", ""}, - {SEL_OP_XOR, "XOR", 0, "Difference", ""}, - {SEL_OP_AND, "AND", 0, "Intersect", ""}, + {SEL_OP_SET, "SET", ICON_SELECT_SET, "Set", "Set a new selection"}, + {SEL_OP_ADD, "ADD", ICON_SELECT_EXTEND, "Extend", "Extend existing selection"}, + {SEL_OP_SUB, "SUB", ICON_SELECT_SUBTRACT, "Subtract", "Subtract existing selection"}, + {SEL_OP_XOR, "XOR", ICON_SELECT_DIFFERENCE, "Difference", "Inverts existing selection"}, + {SEL_OP_AND, "AND", ICON_SELECT_INTERSECT, "Intersect", "Intersect existing selection"}, {0, NULL, 0, NULL, NULL}, }; PropertyRNA *prop = RNA_def_enum(ot->srna, "mode", select_mode_items, SEL_OP_SET, "Mode", ""); @@ -359,9 +361,9 @@ void WM_operator_properties_select_operation(wmOperatorType *ot) void WM_operator_properties_select_operation_simple(wmOperatorType *ot) { static const EnumPropertyItem select_mode_items[] = { - {SEL_OP_SET, "SET", 0, "New", ""}, - {SEL_OP_ADD, "ADD", 0, "Add", ""}, - {SEL_OP_SUB, "SUB", 0, "Subtract", ""}, + {SEL_OP_SET, "SET", ICON_SELECT_SET, "Set", "Set a new selection"}, + {SEL_OP_ADD, "ADD", ICON_SELECT_EXTEND, "Extend", "Extend existing selection"}, + {SEL_OP_SUB, "SUB", ICON_SELECT_SUBTRACT, "Subtract", "Subtract existing selection"}, {0, NULL, 0, NULL, NULL}, }; PropertyRNA *prop = RNA_def_enum(ot->srna, "mode", select_mode_items, SEL_OP_SET, "Mode", ""); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index ec803c9bba7..8445f27ceba 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -870,7 +870,7 @@ int WM_enum_search_invoke_previews(bContext *C, wmOperator *op, short prv_cols, search_menu.prv_cols = prv_cols; search_menu.prv_rows = prv_rows; - UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu); + UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu, NULL); return OPERATOR_INTERFACE; } @@ -879,13 +879,17 @@ int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(eve { static struct EnumSearchMenu search_menu; search_menu.op = op; - UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu); + UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu, NULL); return OPERATOR_INTERFACE; } /* Can't be used as an invoke directly, needs message arg (can be NULL) */ -int WM_operator_confirm_message_ex( - bContext *C, wmOperator *op, const char *title, const int icon, const char *message) +int WM_operator_confirm_message_ex(bContext *C, + wmOperator *op, + const char *title, + const int icon, + const char *message, + const short opcontext) { uiPopupMenu *pup; uiLayout *layout; @@ -900,8 +904,7 @@ int WM_operator_confirm_message_ex( pup = UI_popup_menu_begin(C, title, icon); layout = UI_popup_menu_layout(pup); - uiItemFullO_ptr( - layout, op->type, message, ICON_NONE, properties, WM_OP_EXEC_REGION_WIN, 0, NULL); + uiItemFullO_ptr(layout, op->type, message, ICON_NONE, properties, opcontext, 0, NULL); UI_popup_menu_end(C, pup); return OPERATOR_INTERFACE; @@ -909,7 +912,8 @@ int WM_operator_confirm_message_ex( int WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message) { - return WM_operator_confirm_message_ex(C, op, IFACE_("OK?"), ICON_QUESTION, message); + return WM_operator_confirm_message_ex( + C, op, IFACE_("OK?"), ICON_QUESTION, message, WM_OP_EXEC_REGION_WIN); } int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) @@ -1398,7 +1402,7 @@ int WM_operator_redo_popup(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - UI_popup_block_invoke(C, wm_block_create_redo, op); + UI_popup_block_invoke(C, wm_block_create_redo, op, NULL); return OPERATOR_CANCELLED; } @@ -1710,7 +1714,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar static int wm_splash_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { - UI_popup_block_invoke(C, wm_block_create_splash, NULL); + UI_popup_block_invoke(C, wm_block_create_splash, NULL, NULL); return OPERATOR_FINISHED; } @@ -1816,7 +1820,7 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEv data.size[0] = UI_searchbox_size_x() * 2; data.size[1] = UI_searchbox_size_y(); - UI_popup_block_invoke(C, wm_block_search_menu, &data); + UI_popup_block_invoke(C, wm_block_search_menu, &data, NULL); return OPERATOR_INTERFACE; } @@ -3504,6 +3508,8 @@ void wm_operatortypes_register(void) WM_operatortype_append(WM_OT_read_factory_settings); WM_operatortype_append(WM_OT_save_homefile); WM_operatortype_append(WM_OT_save_userpref); + WM_operatortype_append(WM_OT_read_userpref); + WM_operatortype_append(WM_OT_read_factory_userpref); WM_operatortype_append(WM_OT_userpref_autoexec_path_add); WM_operatortype_append(WM_OT_userpref_autoexec_path_remove); WM_operatortype_append(WM_OT_window_fullscreen_toggle); diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c index f429415bee9..92ef235722b 100644 --- a/source/blender/windowmanager/intern/wm_toolsystem.c +++ b/source/blender/windowmanager/intern/wm_toolsystem.c @@ -574,6 +574,20 @@ void WM_toolsystem_refresh_active(bContext *C) } } } + + BKE_workspace_id_tag_all_visible(bmain, LIB_TAG_DOIT); + + LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) { + if (workspace->id.tag & LIB_TAG_DOIT) { + workspace->id.tag &= ~LIB_TAG_DOIT; + /* Refresh to ensure data is initialized. + * This is needed because undo can load a state which no longer has the underlying DNA data + * needed for the tool (un-initialized paint-slots for eg), see: T64339. */ + for (bToolRef *tref = workspace->tools.first; tref; tref = tref->next) { + toolsystem_refresh_ref(C, workspace, tref); + } + } + } } void WM_toolsystem_refresh_screen_area(WorkSpace *workspace, ViewLayer *view_layer, ScrArea *sa) diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index e98067d78cc..409befd8c47 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -512,7 +512,7 @@ static void wm_confirm_quit(bContext *C) if (GHOST_SupportsNativeDialogs() == 0) { if (!UI_popup_block_name_exists(C, "confirm_quit_popup")) { - UI_popup_block_invoke(C, block_create_confirm_quit, NULL); + UI_popup_block_invoke(C, block_create_confirm_quit, NULL, NULL); } } else if (GHOST_confirmQuit(win->ghostwin)) { @@ -672,6 +672,7 @@ void WM_window_set_dpi(wmWindow *win) U.dpi = dpi / pixelsize; U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE; U.dpi_fac = ((U.pixelsize * (float)U.dpi) / 72.0f); + U.inv_dpi_fac = 1.0f / U.dpi_fac; /* Set user preferences globals for drawing, and for forward compatibility. */ U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72; diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h index c60df27e24b..24209504a07 100644 --- a/source/blender/windowmanager/wm_files.h +++ b/source/blender/windowmanager/wm_files.h @@ -33,6 +33,7 @@ void wm_homefile_read(struct bContext *C, struct ReportList *reports, bool use_factory_settings, bool use_empty_data, + bool use_data, bool use_userdef, const char *filepath_startup_override, const char *app_template_override, @@ -43,6 +44,8 @@ void WM_OT_save_homefile(struct wmOperatorType *ot); void WM_OT_userpref_autoexec_path_add(struct wmOperatorType *ot); void WM_OT_userpref_autoexec_path_remove(struct wmOperatorType *ot); void WM_OT_save_userpref(struct wmOperatorType *ot); +void WM_OT_read_userpref(struct wmOperatorType *ot); +void WM_OT_read_factory_userpref(struct wmOperatorType *ot); void WM_OT_read_history(struct wmOperatorType *ot); void WM_OT_read_homefile(struct wmOperatorType *ot); void WM_OT_read_factory_settings(struct wmOperatorType *ot); |