diff options
author | YimingWu <xp8110@outlook.com> | 2019-05-28 10:39:42 +0300 |
---|---|---|
committer | YimingWu <xp8110@outlook.com> | 2019-05-28 10:39:42 +0300 |
commit | f37533fc44cfb8a7eec919df0dae38998de10e2f (patch) | |
tree | 264074656a88f96bdc3a4dbf53340277d45dc86a /source/blender | |
parent | a640228d92273154acc644d525b095b5318c248b (diff) | |
parent | 1008d9c73567780ec22bea6a0b27f57e60ea403d (diff) |
Merge branch 'master' into soc-2019-npr
Diffstat (limited to 'source/blender')
399 files changed, 8477 insertions, 5650 deletions
diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h index e956aeb769a..e55cb69a5c6 100644 --- a/source/blender/blenkernel/BKE_appdir.h +++ b/source/blender/blenkernel/BKE_appdir.h @@ -45,6 +45,9 @@ void BKE_appdir_program_path_init(const char *argv0); const char *BKE_appdir_program_path(void); const char *BKE_appdir_program_dir(void); +/* Return OS fonts directory. */ +bool BKE_appdir_font_folder_default(char *dir); + /* find python executable */ bool BKE_appdir_program_python_search(char *fullpath, const size_t fullpath_len, diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 5d659d63e27..7461a1b1051 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 69 +#define BLENDER_SUBVERSION 72 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index 0e093bb086b..502c949be9a 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -163,6 +163,9 @@ bool BKE_collection_find_cycle(struct Collection *new_ancestor, struct Collectio bool BKE_collection_has_collection(struct Collection *parent, struct Collection *collection); +void BKE_collection_parent_relations_rebuild(struct Collection *collection); +void BKE_main_collections_parent_relations_rebuild(struct Main *bmain); + /* 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 4356d39be36..df1e7a7baea 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -138,12 +138,7 @@ float *BKE_curve_surf_make_orco(struct Object *ob); void BKE_curve_bevelList_free(struct ListBase *bev); void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render); -void BKE_curve_bevel_make(struct Depsgraph *depsgraph, - struct Scene *scene, - struct Object *ob, - struct ListBase *disp, - const bool for_render, - struct LinkNode *ob_cyclic_list); +void BKE_curve_bevel_make(struct Object *ob, struct ListBase *disp); void BKE_curve_forward_diff_bezier( float q0, float q1, float q2, float q3, float *p, int it, int stride); diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index db57df42d02..c57639a8193 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -90,15 +90,13 @@ void BKE_displist_make_curveTypes(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, const bool for_render, - const bool for_orco, - struct LinkNode *ob_cyclic_list); + const bool for_orco); void BKE_displist_make_curveTypes_forRender(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ListBase *dispbase, struct Mesh **r_final, - const bool for_orco, - struct LinkNode *ob_cyclic_list); + const bool for_orco); 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_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index 91a558a9ee2..b7280c702d2 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -90,6 +90,7 @@ void BKE_editmesh_color_free(BMEditMesh *em); void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype); float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3]; void BKE_editmesh_lnorspace_update(BMEditMesh *em); +void BKE_editmesh_ensure_autosmooth(BMEditMesh *em); /* editderivedmesh.c */ /* should really be defined in editmesh.c, but they use 'EditDerivedBMesh' */ diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 387e7f2182b..9fe8fc3880f 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -107,7 +107,6 @@ typedef struct Global { /** #Global.f */ enum { G_FLAG_RENDER_VIEWPORT = (1 << 0), - G_FLAG_BACKBUFSEL = (1 << 1), G_FLAG_PICKSEL = (1 << 2), /** Support simulating events (for testing). */ G_FLAG_EVENT_SIMULATE = (1 << 3), diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 54b9fdac5b4..818fbce4f9a 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -218,6 +218,8 @@ void BKE_main_id_flag_all(struct Main *bmain, const int flag, const bool value); void BKE_main_id_clear_newpoins(struct Main *bmain); +void BLE_main_id_refcount_recompute(struct Main *bmain, const bool do_linked_only); + void BKE_main_lib_objects_recalc_all(struct Main *bmain); /* Only for repairing files via versioning, avoid for general use. */ diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 042463dc7b0..bfdeadc7f60 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -171,8 +171,6 @@ void BKE_mask_coord_to_image(struct Image *image, /* parenting */ -void BKE_mask_update_display(struct Mask *mask, float ctime); - void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const bool do_newframe); void BKE_mask_evaluate(struct Mask *mask, const float ctime, const bool do_newframe); void BKE_mask_layer_evaluate(struct MaskLayer *masklay, const float ctime, const bool do_newframe); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index c410946f438..54fbda1fa31 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -209,11 +209,22 @@ float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3]; void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals); /* Create new mesh from the given object at its current state. - * The owner of this mesh is unknown, it is up to the caller to decide. */ -struct Mesh *BKE_mesh_new_from_object(struct Object *object); + * The owner of this mesh is unknown, it is up to the caller to decide. + * + * If preserve_all_data_layers is truth then the modifier stack is re-evaluated to ensure it + * preserves all possible custom data layers. + * + * NOTE: Dependency graph argument is required when preserve_all_data_layers is truth, and is + * ignored otherwise. */ +struct Mesh *BKE_mesh_new_from_object(struct Depsgraph *depsgraph, + struct Object *object, + bool preserve_all_data_layers); /* This is a version of BKE_mesh_new_from_object() which stores mesh in the given main database. */ -struct Mesh *BKE_mesh_new_from_object_to_bmain(struct Main *bmain, struct Object *object); +struct Mesh *BKE_mesh_new_from_object_to_bmain(struct Main *bmain, + struct Depsgraph *depsgraph, + struct Object *object, + bool preserve_all_data_layers); struct Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index aa4d9696527..df1ac0e4081 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -400,8 +400,16 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const struct Object *ob, * The result is owned by the object. * * The mesh will be freed when object is re-evaluated or is destroyed. It is possible to force to - * clear memory sued by this mesh by calling BKE_object_to_mesh_clear(). */ -struct Mesh *BKE_object_to_mesh(struct Object *object); + * clear memory sued by this mesh by calling BKE_object_to_mesh_clear(). + * + * If preserve_all_data_layers is truth then the modifier stack is re-evaluated to ensure it + * preserves all possible custom data layers. + * + * NOTE: Dependency graph argument is required when preserve_all_data_layers is truth, and is + * ignored otherwise. */ +struct Mesh *BKE_object_to_mesh(struct Depsgraph *depsgraph, + struct Object *object, + bool preserve_all_data_layers); void BKE_object_to_mesh_clear(struct Object *object); diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 93c9c41e482..dcf6d6c3907 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -84,6 +84,9 @@ typedef struct SpaceType { struct wmNotifier *wmn, struct Scene *scene); + /* called when the mouse moves out of the area */ + void (*deactivate)(struct ScrArea *sa); + /* refresh context, called after filereads, ED_area_tag_refresh() */ void (*refresh)(const struct bContext *C, struct ScrArea *sa); @@ -205,6 +208,7 @@ typedef struct PanelType { short region_type; /* For popovers, 0 for default. */ int ui_units_x; + int order; int flag; diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 170ab657388..807c4a93654 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -323,7 +323,10 @@ void BKE_sequencer_cache_free_temp_cache(struct Scene *scene, short id, int cfra void BKE_sequencer_cache_destruct(struct Scene *scene); void BKE_sequencer_cache_cleanup_all(struct Main *bmain); void BKE_sequencer_cache_cleanup(struct Scene *scene); -void BKE_sequencer_cache_cleanup_sequence(struct Scene *scene, struct Sequence *seq); +void BKE_sequencer_cache_cleanup_sequence(struct Scene *scene, + struct Sequence *seq, + struct Sequence *seq_changed, + int invalidate_types); void BKE_sequencer_cache_iterate( struct Scene *scene, void *userdata, @@ -391,9 +394,10 @@ struct Sequence *BKE_sequence_dupli_recursive(const struct Scene *scene_src, int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str); bool BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur); -void BKE_sequence_invalidate_cache(struct Scene *scene, struct Sequence *seq); +void BKE_sequence_invalidate_cache_raw(struct Scene *scene, struct Sequence *seq); +void BKE_sequence_invalidate_cache_preprocessed(struct Scene *scene, struct Sequence *seq); +void BKE_sequence_invalidate_cache_composite(struct Scene *scene, struct Sequence *seq); void BKE_sequence_invalidate_dependent(struct Scene *scene, struct Sequence *seq); -void BKE_sequence_invalidate_cache_for_modifier(struct Scene *scene, struct Sequence *seq); void BKE_sequencer_update_sound_bounds_all(struct Scene *scene); void BKE_sequencer_update_sound_bounds(struct Scene *scene, struct Sequence *seq); diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h index 3586c08547c..d6fff528348 100644 --- a/source/blender/blenkernel/BKE_studiolight.h +++ b/source/blender/blenkernel/BKE_studiolight.h @@ -131,6 +131,7 @@ typedef struct StudioLight { void BKE_studiolight_init(void); void BKE_studiolight_free(void); +void BKE_studiolight_default(SolidLight lights[4], float light_ambient[4]); struct StudioLight *BKE_studiolight_find(const char *name, int flag); struct StudioLight *BKE_studiolight_findindex(int index, int flag); struct StudioLight *BKE_studiolight_find_default(int flag); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 959435ad486..615a68dc176 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2070,7 +2070,6 @@ static void object_get_datamask(const Depsgraph *depsgraph, bool *r_need_mapping) { ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); - Object *actob = view_layer->basact ? DEG_get_original_object(view_layer->basact->object) : NULL; DEG_get_customdata_mask_for_object(depsgraph, ob, r_mask); @@ -2078,6 +2077,13 @@ static void object_get_datamask(const Depsgraph *depsgraph, *r_need_mapping = false; } + /* Must never access original objects when dependency graph is not active: it might be already + * freed. */ + if (!DEG_is_active(depsgraph)) { + return; + } + + Object *actob = view_layer->basact ? DEG_get_original_object(view_layer->basact->object) : NULL; if (DEG_get_original_object(ob) == actob) { bool editing = BKE_paint_select_face_test(actob); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index ab7e59a059b..4a939180fb0 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -3618,9 +3618,9 @@ static void animsys_calculate_nla(Depsgraph *depsgraph, * Prepare data necessary to compute correct keyframe values for NLA strips * with non-Replace mode or influence different from 1. * - * \param cache List used to cache contexts for reuse when keying + * \param cache: List used to cache contexts for reuse when keying * multiple channels in one operation. - * \param ptr RNA pointer to the Object with the animation. + * \param ptr: RNA pointer to the Object with the animation. * \return Keyframing context, or NULL if not necessary. */ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *cache, @@ -3662,12 +3662,12 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *ca /** * Apply correction from the NLA context to the values about to be keyframed. * - * \param context Context to use (may be NULL). - * \param prop_ptr Property about to be keyframed. - * \param[in,out] values Array of property values to adjust. - * \param count Number of values in the array. - * \param index Index of the element about to be updated, or -1. - * \param[out] r_force_all Set to true if all channels must be inserted. May be NULL. + * \param context: Context to use (may be NULL). + * \param prop_ptr: Property about to be keyframed. + * \param[in,out] values: Array of property values to adjust. + * \param count: Number of values in the array. + * \param index: Index of the element about to be updated, or -1. + * \param[out] r_force_all: Set to true if all channels must be inserted. May be NULL. * \return False if correction fails due to a division by zero, * or null r_force_all when all channels are required. */ diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index c1ea57c5fcc..14a20689db0 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -30,6 +30,7 @@ #include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_string.h" +#include "BLI_string_utf8.h" #include "BKE_blender_version.h" #include "BKE_appdir.h" /* own include */ @@ -1024,3 +1025,17 @@ void BKE_tempdir_session_purge(void) BLI_delete(btempdir_session, true, true); } } + +/* Gets a good default directory for fonts */ +bool BKE_appdir_font_folder_default(char *dir) +{ + bool success = false; +#ifdef WIN32 + wchar_t wpath[FILE_MAXDIR]; + success = SHGetSpecialFolderPathW(0, wpath, CSIDL_FONTS, 0); + BLI_strncpy_wchar_as_utf8(dir, wpath, FILE_MAXDIR); +#endif + /* TODO: Values for other platforms. */ + UNUSED_VARS(dir); + return success; +} diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 570c1b9bd4c..c301588af0c 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -359,6 +359,16 @@ static void setup_app_data(bContext *C, /* TODO(sergey): Can this be also move above? */ RE_FreeAllPersistentData(); } + + if (mode == LOAD_UNDO) { + /* In undo/redo case, we do a whole lot of magic tricks to avoid having to re-read linked + * datablocks from libraries (since those are not supposed to change). Unfortunately, that + * means that we do not reset their user count, however we do increase that one when doing + * lib_link on local IDs using linked ones. + * There is no real way to predict amount of changes here, so we have to fully redo + * refcounting . */ + BLE_main_id_refcount_recompute(bmain, true); + } } static void setup_app_blend_file_data(bContext *C, diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index e28f1fc566f..78d965564e6 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -501,9 +501,46 @@ void BKE_brush_gpencil_presets(bContext *C) brush->gpencil_settings->gradient_s[0] = 1.0f; brush->gpencil_settings->gradient_s[1] = 1.0f; + /* Soft brush */ + brush = BKE_brush_add_gpencil(bmain, ts, "Draw Soft"); + deft = brush; /* save default brush */ + brush->size = 300.0f; + brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR); + brush->gpencil_settings->draw_sensitivity = 1.0f; + + brush->gpencil_settings->draw_strength = 0.4f; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + + brush->gpencil_settings->draw_random_press = 0.0f; + brush->gpencil_settings->draw_random_strength = 0.0f; + + brush->gpencil_settings->draw_jitter = 0.0f; + brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE; + + brush->gpencil_settings->draw_angle = 0.0f; + brush->gpencil_settings->draw_angle_factor = 0.0f; + + brush->gpencil_settings->input_samples = 10; + brush->gpencil_settings->active_smooth = 0.98f; + brush->gpencil_settings->draw_smoothfac = 0.1f; + brush->gpencil_settings->draw_smoothlvl = 1; + brush->gpencil_settings->draw_subdivide = 1; + brush->gpencil_settings->thick_smoothfac = 1.0f; + brush->gpencil_settings->thick_smoothlvl = 3; + brush->gpencil_settings->draw_random_sub = 0.0f; + brush->gpencil_settings->icon_id = GP_BRUSH_ICON_MARKER; + brush->gpencil_tool = GPAINT_TOOL_DRAW; + + brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS; + brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR; + + brush->gpencil_settings->gradient_f = 0.211f; + brush->gpencil_settings->gradient_s[0] = 1.0f; + brush->gpencil_settings->gradient_s[1] = 0.91f; + /* Fill brush */ brush = BKE_brush_add_gpencil(bmain, ts, "Fill Area"); - brush->size = 1.0f; + brush->size = 20.0f; brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR; brush->gpencil_settings->draw_sensitivity = 1.0f; brush->gpencil_settings->fill_leak = 3; diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index a17cbb29550..a8f38c3c4ce 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -66,7 +66,7 @@ void BKE_camera_init(Camera *cam) cam->flag |= CAM_SHOWPASSEPARTOUT; cam->passepartalpha = 0.5f; - cam->dof.aperture_fstop = 5.6f; + cam->dof.aperture_fstop = 2.8f; cam->dof.aperture_ratio = 1.0f; cam->dof.focus_distance = 10.0f; diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 87f448d8d57..e8d82ade7d3 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -321,11 +321,11 @@ Collection *BKE_collection_copy(Main *bmain, Collection *parent, Collection *col * \warning If any 'deep copy' behavior is enabled, * this functions will clear all \a bmain id.idnew pointers. * - * \param do_hierarchy If true, it will recursively make shallow copies of children collections. - * \param do_objects If true, it will also make duplicates of objects. - * This one does nothing if \a do_hierarchy is not set. - * \param do_obdata If true, it will also make deep duplicates of objects, - * using behavior defined in user settings (U.dupflag). + * \param do_hierarchy: If true, it will recursively make shallow copies of children collections. + * \param do_objects: If true, it will also make duplicates of objects. + * This one does nothing if \a do_hierarchy is not set. + * \param do_obdata: If true, it will also make deep duplicates of objects, + * using behavior defined in user settings (#U.dupflag). * This one does nothing if \a do_hierarchy and \a do_objects are not set. */ Collection *BKE_collection_duplicate(Main *bmain, @@ -705,18 +705,27 @@ bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob) } /** - * Add object to all scene collections that reference objects is in - * (used to copy objects) + * Add object to all scene collections that reference object is in + * (used to copy objects). */ void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst) { + bool is_instantiated = false; + FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) { - if (BKE_collection_has_object(collection, ob_src)) { + if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, ob_src)) { collection_object_add(bmain, collection, ob_dst, 0, true); + is_instantiated = true; } } FOREACH_SCENE_COLLECTION_END; + if (!is_instantiated) { + /* In case we could not find any non-linked collections in which instantiate our ob_dst, + * fallback to scene's master collection... */ + collection_object_add(bmain, BKE_collection_master(scene), ob_dst, 0, true); + } + BKE_main_collection_sync(bmain); } @@ -1047,6 +1056,72 @@ bool BKE_collection_child_remove(Main *bmain, Collection *parent, Collection *ch return true; } +/** + * Rebuild parent relationships from child ones, for all children of given \a collection. + * + * \note Given collection is assumed to already have valid parents. + */ +void BKE_collection_parent_relations_rebuild(Collection *collection) +{ + for (CollectionChild *child = collection->children.first, *child_next = NULL; child; + child = child_next) { + child_next = child->next; + + if (child->collection == NULL || BKE_collection_find_cycle(collection, child->collection)) { + BLI_freelinkN(&collection->children, child); + } + else { + CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), __func__); + cparent->collection = collection; + BLI_addtail(&child->collection->parents, cparent); + } + } +} + +static void collection_parents_rebuild_recursive(Collection *collection) +{ + BKE_collection_parent_relations_rebuild(collection); + collection->id.tag &= ~LIB_TAG_DOIT; + + for (CollectionChild *child = collection->children.first; child != NULL; child = child->next) { + collection_parents_rebuild_recursive(child->collection); + } +} + +/** + * Rebuild parent relationships from child ones, for all collections in given \a bmain. + * + * \note Uses LIB_TAG_DOIT internally... + */ +void BKE_main_collections_parent_relations_rebuild(Main *bmain) +{ + /* Only collections not in bmain (master ones in scenes) have no parent... */ + for (Collection *collection = bmain->collections.first; collection != NULL; + collection = collection->id.next) { + BLI_freelistN(&collection->parents); + + collection->id.tag |= LIB_TAG_DOIT; + } + + /* Scene's master collections will be 'root' parent of most of our collections, so start with + * them. */ + for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) { + collection_parents_rebuild_recursive(scene->master_collection); + } + + /* We may have parent chains outside of scene's master_collection context? At least, readfile's + * lib_link_collection_data() seems to assume that, so do the same here. */ + for (Collection *collection = bmain->collections.first; collection != NULL; + collection = collection->id.next) { + if (collection->id.tag & LIB_TAG_DOIT) { + /* Note: we do not have easy access to 'which collections is root' info in that case, which + * means test for cycles in collection relationships may fail here. I don't think that is an + * issue in practice here, but worth keeping in mind... */ + collection_parents_rebuild_recursive(collection); + } + } +} + /********************** Collection index *********************/ static Collection *collection_from_index_recursive(Collection *collection, @@ -1175,8 +1250,43 @@ bool BKE_collection_move(Main *bmain, } } + /* Make sure we store the flag of the layer collections before we remove and re-create them. + * Otherwise they will get lost and everything will be copied from the new parent collection. */ + GHash *view_layer_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); + + for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; + view_layer = view_layer->next) { + + LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection( + view_layer, collection); + + if (layer_collection == NULL) { + continue; + } + + BLI_ghash_insert(view_layer_hash, view_layer, POINTER_FROM_INT(layer_collection->flag)); + } + } + + /* Create and remove layer collections. */ BKE_main_collection_sync(bmain); + /* Restore back the original layer collection flags. */ + GHashIterator gh_iter; + GHASH_ITER (gh_iter, view_layer_hash) { + ViewLayer *view_layer = BLI_ghashIterator_getKey(&gh_iter); + + LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection( + view_layer, collection); + + if (layer_collection) { + layer_collection->flag = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter)); + } + } + + BLI_ghash_free(view_layer_hash, NULL, NULL); + return true; } diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 9509e408fba..28b0ae23ffe 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -399,6 +399,39 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa return 0; } +static int ctx_data_base_collection_get(const bContext *C, const char *member, ListBase *list) +{ + ListBase ctx_object_list; + bool ok = false; + + if ((ctx_data_collection_get(C, member, &ctx_object_list) == false) || + BLI_listbase_is_empty(&ctx_object_list)) { + BLI_listbase_clear(list); + return 0; + } + + bContextDataResult result; + memset(&result, 0, sizeof(bContextDataResult)); + + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + + CollectionPointerLink *ctx_object; + for (ctx_object = ctx_object_list.first; ctx_object; ctx_object = ctx_object->next) { + Object *ob = ctx_object->ptr.data; + Base *base = BKE_view_layer_base_find(view_layer, ob); + if (base != NULL) { + CTX_data_list_add(&result, &scene->id, &RNA_ObjectBase, base); + ok = true; + } + } + CTX_data_type_set(&result, CTX_DATA_TYPE_COLLECTION); + BLI_freelistN(&ctx_object_list); + + *list = result.list; + return ok; +} + PointerRNA CTX_data_pointer_get(const bContext *C, const char *member) { bContextDataResult result; @@ -1150,7 +1183,7 @@ int CTX_data_selected_editable_objects(const bContext *C, ListBase *list) int CTX_data_selected_editable_bases(const bContext *C, ListBase *list) { - return ctx_data_collection_get(C, "selected_editable_bases", list); + return ctx_data_base_collection_get(C, "selected_editable_objects", list); } int CTX_data_editable_objects(const bContext *C, ListBase *list) @@ -1160,7 +1193,7 @@ int CTX_data_editable_objects(const bContext *C, ListBase *list) int CTX_data_editable_bases(const bContext *C, ListBase *list) { - return ctx_data_collection_get(C, "editable_bases", list); + return ctx_data_base_collection_get(C, "editable_objects", list); } int CTX_data_selected_objects(const bContext *C, ListBase *list) @@ -1170,7 +1203,7 @@ int CTX_data_selected_objects(const bContext *C, ListBase *list) int CTX_data_selected_bases(const bContext *C, ListBase *list) { - return ctx_data_collection_get(C, "selected_bases", list); + return ctx_data_base_collection_get(C, "selected_objects", list); } int CTX_data_visible_objects(const bContext *C, ListBase *list) @@ -1180,7 +1213,7 @@ int CTX_data_visible_objects(const bContext *C, ListBase *list) int CTX_data_visible_bases(const bContext *C, ListBase *list) { - return ctx_data_collection_get(C, "visible_bases", list); + return ctx_data_base_collection_get(C, "visible_objects", list); } int CTX_data_selectable_objects(const bContext *C, ListBase *list) @@ -1190,7 +1223,7 @@ int CTX_data_selectable_objects(const bContext *C, ListBase *list) int CTX_data_selectable_bases(const bContext *C, ListBase *list) { - return ctx_data_collection_get(C, "selectable_bases", list); + return ctx_data_base_collection_get(C, "selectable_objects", list); } struct Object *CTX_data_active_object(const bContext *C) @@ -1200,7 +1233,14 @@ struct Object *CTX_data_active_object(const bContext *C) struct Base *CTX_data_active_base(const bContext *C) { - return ctx_data_pointer_get(C, "active_base"); + Object *ob = ctx_data_pointer_get(C, "active_object"); + + if (ob == NULL) { + return NULL; + } + + ViewLayer *view_layer = CTX_data_view_layer(C); + return BKE_view_layer_base_find(view_layer, ob); } struct Object *CTX_data_edit_object(const bContext *C) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 2775cf9691f..5945fa4bf33 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1739,12 +1739,7 @@ static void forward_diff_bezier_cotangent(const float p0[3], /* ***************** BEVEL ****************** */ -void BKE_curve_bevel_make(Depsgraph *depsgraph, - Scene *scene, - Object *ob, - ListBase *disp, - const bool for_render, - LinkNode *ob_cyclic_list) +void BKE_curve_bevel_make(Object *ob, ListBase *disp) { DispList *dl, *dlnew; Curve *bevcu, *cu; @@ -1768,25 +1763,7 @@ void BKE_curve_bevel_make(Depsgraph *depsgraph, facx = cu->bevobj->scale[0]; facy = cu->bevobj->scale[1]; - if (for_render) { - if (BLI_linklist_index(ob_cyclic_list, cu->bevobj) == -1) { - BKE_displist_make_curveTypes_forRender(depsgraph, - scene, - cu->bevobj, - &bevdisp, - NULL, - false, - &(LinkNode){ - .link = ob, - .next = ob_cyclic_list, - }); - dl = bevdisp.first; - } - else { - dl = NULL; - } - } - else if (cu->bevobj->runtime.curve_cache) { + if (cu->bevobj->runtime.curve_cache) { dl = cu->bevobj->runtime.curve_cache->disp.first; } else { diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index cc1c73b1e68..c8d6f7ae313 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -723,7 +723,7 @@ static float displist_calc_taper(Depsgraph *depsgraph, Scene *scene, Object *tap dl = taperobj->runtime.curve_cache ? taperobj->runtime.curve_cache->disp.first : NULL; if (dl == NULL) { - BKE_displist_make_curveTypes(depsgraph, scene, taperobj, false, false, NULL); + BKE_displist_make_curveTypes(depsgraph, scene, taperobj, false, false); dl = taperobj->runtime.curve_cache->disp.first; } if (dl) { @@ -1527,7 +1527,6 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph, ListBase *dispbase, const bool for_render, const bool for_orco, - LinkNode *ob_cyclic_list, Mesh **r_final) { Curve *cu = ob->data; @@ -1571,7 +1570,7 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph, 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, ob_cyclic_list); + BKE_curve_bevel_make(ob, &dlbev); /* no bevel or extrude, and no width correction? */ if (!dlbev.first && cu->width == 1.0f) { @@ -1786,12 +1785,8 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph, } } -void BKE_displist_make_curveTypes(Depsgraph *depsgraph, - Scene *scene, - Object *ob, - const bool for_render, - const bool for_orco, - LinkNode *ob_cyclic_list) +void BKE_displist_make_curveTypes( + Depsgraph *depsgraph, Scene *scene, Object *ob, const bool for_render, const bool for_orco) { ListBase *dispbase; @@ -1810,14 +1805,8 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph, dispbase = &(ob->runtime.curve_cache->disp); - do_makeDispListCurveTypes(depsgraph, - scene, - ob, - dispbase, - for_render, - for_orco, - ob_cyclic_list, - &ob->runtime.mesh_eval); + do_makeDispListCurveTypes( + depsgraph, scene, ob, dispbase, for_render, for_orco, &ob->runtime.mesh_eval); boundbox_displist_object(ob); } @@ -1827,15 +1816,13 @@ void BKE_displist_make_curveTypes_forRender(Depsgraph *depsgraph, Object *ob, ListBase *dispbase, Mesh **r_final, - const bool for_orco, - LinkNode *ob_cyclic_list) + const bool for_orco) { 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, ob_cyclic_list, r_final); + do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, true, for_orco, r_final); } void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3]) diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c index 130f4ae88f1..b8234ccc5bb 100644 --- a/source/blender/blenkernel/intern/editmesh.c +++ b/source/blender/blenkernel/intern/editmesh.c @@ -248,3 +248,13 @@ void BKE_editmesh_lnorspace_update(BMEditMesh *em) BM_lnorspace_update(bm); } + +/* If autosmooth not already set, set it */ +void BKE_editmesh_ensure_autosmooth(BMEditMesh *em) +{ + Mesh *me = em->ob->data; + if (!(me->flag & ME_AUTOSMOOTH)) { + me->flag |= ME_AUTOSMOOTH; + BKE_editmesh_lnorspace_update(em); + } +} diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 51715c3a223..7cbd5b6b050 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -172,7 +172,7 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef if (cu->flag & CU_PATH) { if (eff->ob->runtime.curve_cache == NULL || eff->ob->runtime.curve_cache->path == NULL || eff->ob->runtime.curve_cache->path->data == NULL) { - BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, false, false, NULL); + BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, false, false); } if (eff->ob->runtime.curve_cache->path && eff->ob->runtime.curve_cache->path->data) { diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index d59ead25396..9960994400f 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -502,6 +502,12 @@ static void image_init_color_management(Image *ima) if (ibuf->flags & IB_alphamode_premul) { ima->alpha_mode = IMA_ALPHA_PREMUL; } + else if (ibuf->flags & IB_alphamode_channel_packed) { + ima->alpha_mode = IMA_ALPHA_CHANNEL_PACKED; + } + else if (ibuf->flags & IB_alphamode_ignore) { + ima->alpha_mode = IMA_ALPHA_IGNORE; + } else { ima->alpha_mode = IMA_ALPHA_STRAIGHT; } @@ -3592,16 +3598,18 @@ static void image_initialize_after_load(Image *ima, ImBuf *UNUSED(ibuf)) static int imbuf_alpha_flags_for_image(Image *ima) { - int flag = 0; - - if (ima->flag & IMA_IGNORE_ALPHA) { - flag |= IB_ignore_alpha; - } - else if (ima->alpha_mode == IMA_ALPHA_PREMUL) { - flag |= IB_alphamode_premul; + switch (ima->alpha_mode) { + case IMA_ALPHA_STRAIGHT: + return 0; + case IMA_ALPHA_PREMUL: + return IB_alphamode_premul; + case IMA_ALPHA_CHANNEL_PACKED: + return IB_alphamode_channel_packed; + case IMA_ALPHA_IGNORE: + return IB_alphamode_ignore; } - return flag; + return 0; } /* the number of files will vary according to the stereo format */ diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 7fb6f78def1..27203158a4f 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -873,7 +873,7 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) /* assign copy */ RNA_id_pointer_create(newid, &idptr); - RNA_property_pointer_set(NULL, ptr, prop, idptr); + RNA_property_pointer_set(ptr, prop, idptr, NULL); RNA_property_update(C, ptr, prop); /* tag grease pencil datablock and disable onion */ @@ -1788,6 +1788,59 @@ void BKE_main_id_clear_newpoins(Main *bmain) FOREACH_MAIN_ID_END; } +static int id_refcount_recompute_callback(void *user_data, + struct ID *UNUSED(id_self), + struct ID **id_pointer, + int cb_flag) +{ + const bool do_linked_only = (bool)POINTER_AS_INT(user_data); + + if (*id_pointer == NULL) { + return IDWALK_RET_NOP; + } + if (do_linked_only && !ID_IS_LINKED(*id_pointer)) { + return IDWALK_RET_NOP; + } + + if (cb_flag & IDWALK_CB_USER) { + /* Do not touch to direct/indirect linked status here... */ + id_us_plus_no_lib(*id_pointer); + } + if (cb_flag & IDWALK_CB_USER_ONE) { + id_us_ensure_real(*id_pointer); + } + + return IDWALK_RET_NOP; +} + +void BLE_main_id_refcount_recompute(struct Main *bmain, const bool do_linked_only) +{ + ID *id; + + FOREACH_MAIN_ID_BEGIN (bmain, id) { + if (!ID_IS_LINKED(id) && do_linked_only) { + continue; + } + id->us = ID_FAKE_USERS(id); + /* Note that we keep EXTRAUSER tag here, since some UI users may define it too... */ + if (id->tag & LIB_TAG_EXTRAUSER) { + id->tag &= ~(LIB_TAG_EXTRAUSER | LIB_TAG_EXTRAUSER_SET); + id_us_ensure_real(id); + } + } + FOREACH_MAIN_ID_END; + + /* Go over whole Main database to re-generate proper usercounts... */ + FOREACH_MAIN_ID_BEGIN (bmain, id) { + BKE_library_foreach_ID_link(bmain, + id, + id_refcount_recompute_callback, + POINTER_FROM_INT((int)do_linked_only), + IDWALK_READONLY); + } + FOREACH_MAIN_ID_END; +} + static void library_make_local_copying_check(ID *id, GSet *loop_tags, MainIDRelations *id_relations, @@ -1813,7 +1866,8 @@ static void library_make_local_copying_check(ID *id, } /* Shapekeys are considered 'private' to their owner ID here, and never tagged - * (since they cannot be linked), * so we have to switch effective parent to their owner. */ + * (since they cannot be linked), * so we have to switch effective parent to their owner. + */ if (GS(par_id->name) == ID_KE) { par_id = ((Key *)par_id)->from; } @@ -1855,17 +1909,17 @@ static void library_make_local_copying_check(ID *id, * * \param bmain: Almost certainly global main. * \param lib: If not NULL, only make local datablocks from this library. - * \param untagged_only: If true, only make local datablocks not tagged with LIB_TAG_PRE_EXISTING. - * \param set_fake: If true, set fake user on all localized data-blocks + * \param untagged_only: If true, only make local datablocks not tagged with + * LIB_TAG_PRE_EXISTING. \param set_fake: If true, set fake user on all localized data-blocks * (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... * - * 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 - * function is finished. This allows to avoid any unneeded duplication of IDs, and hence all time - * lost afterwards to remove orphaned linked data-blocks... + * 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 function is finished. This allows to avoid any unneeded duplication of IDs, and + * hence all time lost afterwards to remove orphaned linked data-blocks... */ void BKE_library_make_local(Main *bmain, const Library *lib, @@ -1976,16 +2030,17 @@ void BKE_library_make_local(Main *bmain, ID *id = it->link; if (id->tag & LIB_TAG_DOIT) { - /* We know all users of this object are local or will be made fully local, even if currently - * there are some indirect usages. So instead of making a copy that we'll likely get rid of - * later, directly make that data block local. + /* We know all users of this object are local or will be made fully local, even if + * currently there are some indirect usages. So instead of making a copy that we'll likely + * get rid of later, directly make that data block local. * Saves a tremendous amount of time with complex scenes... */ id_clear_lib_data_ex(bmain, id, true); BKE_id_expand_local(bmain, id); id->tag &= ~LIB_TAG_DOIT; } else { - /* In this specific case, we do want to make ID local even if it has no local usage yet... */ + /* In this specific case, we do want to make ID local even if it has no local usage yet... + */ if (GS(id->name) == ID_OB) { /* Special case for objects because we don't want proxy pointers to be * cleared yet. This will happen down the road in this function. @@ -2039,8 +2094,9 @@ void BKE_library_make_local(Main *bmain, BLI_ghash_insert(old_to_new_ids, id, id->newid); } - /* Special hack for groups... Thing is, since we can't instantiate them here, we need to ensure - * they remain 'alive' (only instantiation is a real group 'user'... *sigh* See T49722. */ + /* Special hack for groups... Thing is, since we can't instantiate them here, we need to + * ensure they remain 'alive' (only instantiation is a real group 'user'... *sigh* See + * T49722. */ if (GS(id->name) == ID_GR && (id->tag & LIB_TAG_INDIRECT) != 0) { id_us_ensure_real(id->newid); } @@ -2108,11 +2164,11 @@ void BKE_library_make_local(Main *bmain, #endif /* This is probably more of a hack than something we should do here, but... - * Issue is, the whole copying + remapping done in complex cases above may leave pose-channels of - * armatures in complete invalid state (more precisely, the bone pointers of the pose-channels - - * very crappy cross-data-blocks relationship), se we tag it to be fully recomputed, - * but this does not seems to be enough in some cases, and evaluation code ends up trying to - * evaluate a not-yet-updated armature object's deformations. + * Issue is, the whole copying + remapping done in complex cases above may leave pose-channels + * of armatures in complete invalid state (more precisely, the bone pointers of the + * pose-channels - very crappy cross-data-blocks relationship), se we tag it to be fully + * recomputed, but this does not seems to be enough in some cases, and evaluation code ends up + * trying to evaluate a not-yet-updated armature object's deformations. * Try "make all local" in 04_01_H.lighting.blend from Agent327 without this, e.g. */ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { if (ob->data != NULL && ob->type == OB_ARMATURE && ob->pose != NULL && @@ -2289,7 +2345,8 @@ void BKE_id_tag_clear_atomic(ID *id, int tag) * Main intended use is for debug asserts in places we cannot easily get rid of G_Main... */ bool BKE_id_is_in_global_main(ID *id) { - /* We do not want to fail when id is NULL here, even though this is a bit strange behavior... */ + /* We do not want to fail when id is NULL here, even though this is a bit strange behavior... + */ return (id == NULL || BLI_findindex(which_libbase(G_MAIN, GS(id->name)), id) != -1); } diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index a95069a2af9..085051f633c 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -591,7 +591,7 @@ static void library_foreach_ID_link(Main *bmain, CALLBACK_INVOKE(object->parent, IDWALK_CB_NEVER_SELF); CALLBACK_INVOKE(object->track, IDWALK_CB_NEVER_SELF); /* object->proxy is refcounted, but not object->proxy_group... *sigh* */ - CALLBACK_INVOKE(object->proxy, IDWALK_CB_NEVER_SELF); + CALLBACK_INVOKE(object->proxy, IDWALK_CB_USER | IDWALK_CB_NEVER_SELF); CALLBACK_INVOKE(object->proxy_group, IDWALK_CB_NOP); /* Special case! diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index 4e5eac7924b..802f13ea69f 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -287,6 +287,13 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id if (!is_indirect || is_obj_proxy) { id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT; } + /* We need to remap proxy_from pointer of remapped proxy... sigh. */ + if (is_obj_proxy && new_id != NULL) { + Object *ob = (Object *)id; + if (ob->proxy == (Object *)new_id) { + ob->proxy->proxy_from = ob; + } + } } } @@ -368,6 +375,11 @@ static void libblock_remap_data_postprocess_collection_update(Main *bmain, * I'd consider optimizing that whole collection remapping process a TODO for later. */ BKE_collections_child_remove_nulls(bmain, NULL /*old_collection*/); } + else { + /* Temp safe fix, but a "tad" brute force... We should probably be able to use parents from + * old_collection instead? */ + BKE_main_collections_parent_relations_rebuild(bmain); + } BKE_main_collection_sync_remap(bmain); } diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 9a9b3757ef2..bb93d068bef 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -225,6 +225,16 @@ MaskLayer *BKE_mask_layer_copy(const MaskLayer *masklay) MaskSpline *spline_new = BKE_mask_spline_copy(spline); BLI_addtail(&masklay_new->splines, spline_new); + + if (spline == masklay->act_spline) { + masklay_new->act_spline = spline_new; + } + + if (masklay->act_point >= spline->points && + masklay->act_point < spline->points + spline->tot_point) { + const size_t point_index = masklay->act_point - spline->points; + masklay_new->act_point = spline_new->points + point_index; + } } /* correct animation */ @@ -1459,13 +1469,6 @@ void BKE_mask_evaluate(Mask *mask, const float ctime, const bool do_newframe) } } -/* the purpose of this function is to ensure spline->points_deform is never out of date. - * for now re-evaluate all. eventually this might work differently */ -void BKE_mask_update_display(Mask *mask, float ctime) -{ - BKE_mask_evaluate(mask, ctime, false); -} - void BKE_mask_evaluate_all_masks(Main *bmain, float ctime, const bool do_newframe) { Mask *mask; diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index 4e6ca878b7a..f4f93fcb698 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -954,10 +954,30 @@ void BKE_mask_eval_animation(struct Depsgraph *depsgraph, Mask *mask) void BKE_mask_eval_update(struct Depsgraph *depsgraph, Mask *mask) { + const bool is_depsgraph_active = DEG_is_active(depsgraph); float ctime = DEG_get_ctime(depsgraph); DEG_debug_print_eval(depsgraph, __func__, mask->id.name, mask); for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) { BKE_mask_layer_evaluate_deform(mask_layer, ctime); } + + if (is_depsgraph_active) { + Mask *mask_orig = (Mask *)DEG_get_original_id(&mask->id); + for (MaskLayer *masklay_orig = mask_orig->masklayers.first, + *masklay_eval = mask->masklayers.first; + masklay_orig != NULL; + masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next) { + for (MaskSpline *spline_orig = masklay_orig->splines.first, + *spline_eval = masklay_eval->splines.first; + spline_orig != NULL; + spline_orig = spline_orig->next, spline_eval = spline_eval->next) { + for (int i = 0; i < spline_eval->tot_point; i++) { + MaskSplinePoint *point_eval = &spline_eval->points[i]; + MaskSplinePoint *point_orig = &spline_orig->points[i]; + point_orig->bezt = point_eval->bezt; + } + } + } + } } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 75b9e355df9..1e5a2d53bfa 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -133,7 +133,7 @@ void BKE_material_init(Material *ma) ma->a = 1.0f; ma->spec = 0.5; - ma->roughness = 0.25f; + ma->roughness = 0.4f; ma->pr_type = MA_SPHERE; diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index dca5248c0fa..fce80272738 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -1005,8 +1005,7 @@ static void curve_to_mesh_eval_ensure(Object *object) &remapped_object, &remapped_object.runtime.curve_cache->disp, &remapped_object.runtime.mesh_eval, - false, - NULL); + false); BKE_object_free_curve_cache(&bevel_object); BKE_object_free_curve_cache(&taper_object); @@ -1083,17 +1082,11 @@ static Mesh *mesh_new_from_mball_object(Object *object) return mesh_result; } -static Mesh *mesh_new_from_mesh_object(Object *object) +static Mesh *mesh_new_from_mesh(Object *object, Mesh *mesh) { - Mesh *mesh_input = object->data; - /* If we are in edit mode, use evaluated mesh from edit structure, matching to what - * viewport is using for visualization. */ - if (mesh_input->edit_mesh != NULL && mesh_input->edit_mesh->mesh_eval_final) { - mesh_input = mesh_input->edit_mesh->mesh_eval_final; - } Mesh *mesh_result = NULL; BKE_id_copy_ex(NULL, - &mesh_input->id, + &mesh->id, (ID **)&mesh_result, LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT); /* NOTE: Materials should already be copied. */ @@ -1102,7 +1095,52 @@ static Mesh *mesh_new_from_mesh_object(Object *object) return mesh_result; } -Mesh *BKE_mesh_new_from_object(Object *object) +static Mesh *mesh_new_from_mesh_object_with_layers(Depsgraph *depsgraph, Object *object) +{ + if (DEG_is_original_id(&object->id)) { + return mesh_new_from_mesh(object, (Mesh *)object->data); + } + + if (depsgraph == NULL) { + return NULL; + } + + Object object_for_eval = *object; + if (object_for_eval.runtime.mesh_orig != NULL) { + object_for_eval.data = object_for_eval.runtime.mesh_orig; + } + + Scene *scene = DEG_get_evaluated_scene(depsgraph); + CustomData_MeshMasks mask = CD_MASK_MESH; + Mesh *result; + + if (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER) { + result = mesh_create_eval_final_render(depsgraph, scene, &object_for_eval, &mask); + } + else { + result = mesh_create_eval_final_view(depsgraph, scene, &object_for_eval, &mask); + } + + return result; +} + +static Mesh *mesh_new_from_mesh_object(Depsgraph *depsgraph, + Object *object, + bool preserve_all_data_layers) +{ + if (preserve_all_data_layers) { + return mesh_new_from_mesh_object_with_layers(depsgraph, object); + } + Mesh *mesh_input = object->data; + /* If we are in edit mode, use evaluated mesh from edit structure, matching to what + * viewport is using for visualization. */ + if (mesh_input->edit_mesh != NULL && mesh_input->edit_mesh->mesh_eval_final) { + mesh_input = mesh_input->edit_mesh->mesh_eval_final; + } + return mesh_new_from_mesh(object, mesh_input); +} + +Mesh *BKE_mesh_new_from_object(Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers) { Mesh *new_mesh = NULL; switch (object->type) { @@ -1115,7 +1153,7 @@ Mesh *BKE_mesh_new_from_object(Object *object) new_mesh = mesh_new_from_mball_object(object); break; case OB_MESH: - new_mesh = mesh_new_from_mesh_object(object); + new_mesh = mesh_new_from_mesh_object(depsgraph, object, preserve_all_data_layers); break; default: /* Object does not have geometry data. */ @@ -1141,13 +1179,24 @@ static int foreach_libblock_make_original_and_usercount_callback(void *user_data return IDWALK_RET_NOP; } *id_p = DEG_get_original_id(*id_p); - id_us_plus(*id_p); + + if (cb_flag & IDWALK_CB_USER) { + id_us_plus(*id_p); + } + else if (cb_flag & IDWALK_CB_USER_ONE) { + /* Note: in that context, that one should not be needed (since there should be at least already + * one USER_ONE user of that ID), but better be consistent. */ + id_us_ensure_real(*id_p); + } return IDWALK_RET_NOP; } -Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain, Object *object) +Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain, + Depsgraph *depsgraph, + Object *object, + bool preserve_all_data_layers) { - Mesh *mesh = BKE_mesh_new_from_object(object); + Mesh *mesh = BKE_mesh_new_from_object(depsgraph, object, preserve_all_data_layers); /* Make sure mesh only points original datablocks, also increase users of materials and other * possibly referenced data-blocks. diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index d889fca3a3a..f0fd1203cae 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -2141,8 +2141,8 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const * Higher level functions hiding most of the code needed around call to * #BKE_mesh_normals_loop_custom_set(). * - * \param r_custom_loopnors is not const, since code will replace zero_v3 normals there - * with automatically computed vectors. + * \param r_custom_loopnors: is not const, since code will replace zero_v3 normals there + * with automatically computed vectors. */ void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loopnors)[3]) { @@ -2153,8 +2153,8 @@ void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loopnors)[3]) * Higher level functions hiding most of the code needed around call to * #BKE_mesh_normals_loop_custom_from_vertices_set(). * - * \param r_custom_loopnors is not const, since code will replace zero_v3 normals there - * with automatically computed vectors. + * \param r_custom_loopnors: is not const, since code will replace zero_v3 normals there + * with automatically computed vectors. */ void BKE_mesh_set_custom_normals_from_vertices(Mesh *mesh, float (*r_custom_vertnors)[3]) { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 9bc9865631f..43a5e1d6592 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -934,8 +934,8 @@ void modwrap_deformVertsEM(ModifierData *md, * Note that modifiers in stack always get fully evaluated COW ID pointers, * never original ones. Makes things simpler. * - * \param get_cage_mesh Return evaluated mesh with only deforming modifiers applied - * (i.e. mesh topology remains the same as original one, a.k.a. 'cage' mesh). + * \param get_cage_mesh: Return evaluated mesh with only deforming modifiers applied + * (i.e. mesh topology remains the same as original one, a.k.a. 'cage' mesh). */ Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval, const bool get_cage_mesh) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 95be7f8f51f..fcb1066b633 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1468,7 +1468,7 @@ Object *BKE_object_copy(Main *bmain, const Object *ob) /** Perform deep-copy of object and its 'children' data-blocks (obdata, materials, actions, etc.). * - * \param dupflag Controls which sub-data are also duplicated + * \param dupflag: Controls which sub-data are also duplicated * (see #eDupli_ID_Flags in DNA_userdef_types.h). * * \note This function does not do any remapping to new IDs, caller must do it @@ -4499,11 +4499,11 @@ void BKE_object_update_select_id(struct Main *bmain) } } -Mesh *BKE_object_to_mesh(Object *object) +Mesh *BKE_object_to_mesh(Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers) { BKE_object_to_mesh_clear(object); - Mesh *mesh = BKE_mesh_new_from_object(object); + Mesh *mesh = BKE_mesh_new_from_object(depsgraph, object, preserve_all_data_layers); object->runtime.object_as_temp_mesh = mesh; return mesh; } diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 77941e7d607..6dee936ca76 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -204,7 +204,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o case OB_SURF: case OB_FONT: { bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); - BKE_displist_make_curveTypes(depsgraph, scene, ob, for_render, false, NULL); + BKE_displist_make_curveTypes(depsgraph, scene, ob, for_render, false); break; } diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index bd06e2fe7e0..5849d691b03 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -102,8 +102,11 @@ void BKE_paint_invalidate_overlay_tex(Scene *scene, ViewLayer *view_layer, const void BKE_paint_invalidate_cursor_overlay(Scene *scene, ViewLayer *view_layer, CurveMapping *curve) { Paint *p = BKE_paint_get_active(scene, view_layer); - Brush *br = p->brush; + if (p == NULL) { + return; + } + Brush *br = p->brush; if (br && br->curve == curve) { overlay_flags |= PAINT_OVERLAY_INVALID_CURVE; } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index c6cc72ba989..13649eaf096 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -387,8 +387,11 @@ void psys_find_group_weights(ParticleSettings *part) /* Find object pointers based on index. If the collection is linked from * another library linking may not have the object pointers available on * file load, so we have to retrieve them later. See T49273. */ - const ListBase instance_collection_objects = BKE_collection_object_cache_get( - part->instance_collection); + ListBase instance_collection_objects = {NULL, NULL}; + + if (part->instance_collection) { + instance_collection_objects = BKE_collection_object_cache_get(part->instance_collection); + } for (ParticleDupliWeight *dw = part->instance_weights.first; dw; dw = dw->next) { if (dw->ob == NULL) { diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index cba15aed55f..27722aab2d9 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -471,14 +471,6 @@ void psys_thread_context_init(ParticleThreadContext *ctx, ParticleSimulationData ctx->ma = give_current_material(sim->ob, sim->psys->part->omat); } -#define MAX_PARTICLES_PER_TASK \ - 256 /* XXX arbitrary - maybe use at least number of points instead for better balancing? */ - -BLI_INLINE int ceil_ii(int a, int b) -{ - return (a + b - 1) / b; -} - void psys_tasks_create(ParticleThreadContext *ctx, int startpart, int endpart, @@ -486,7 +478,7 @@ void psys_tasks_create(ParticleThreadContext *ctx, int *r_numtasks) { ParticleTask *tasks; - int numtasks = ceil_ii((endpart - startpart), MAX_PARTICLES_PER_TASK); + int numtasks = min_ii(BLI_system_thread_count() * 4, endpart - startpart); float particles_per_task = (float)(endpart - startpart) / (float)numtasks, p, pnext; int i; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 3d864a9fa00..87979e5d5dd 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -916,7 +916,7 @@ void BKE_scene_init(Scene *sce) sce->eevee.gi_cubemap_draw_size = 0.3f; sce->eevee.gi_irradiance_draw_size = 0.1f; sce->eevee.gi_irradiance_smoothing = 0.1f; - sce->eevee.gi_filter_quality = 1.0f; + sce->eevee.gi_filter_quality = 3.0f; sce->eevee.taa_samples = 16; sce->eevee.taa_render_samples = 64; diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index bc9ec6b28e6..3ff8b6ff18c 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -843,7 +843,7 @@ void BKE_screen_view3d_shading_init(View3DShading *shading) shading->light = V3D_LIGHTING_STUDIO; shading->shadow_intensity = 0.5f; shading->xray_alpha = 0.5f; - shading->xray_alpha_wire = 0.5f; + shading->xray_alpha_wire = 0.0f; shading->cavity_valley_factor = 1.0f; shading->cavity_ridge_factor = 1.0f; shading->cavity_type = V3D_SHADING_CAVITY_CURVATURE; diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c index 1c0aa63f590..6f5b5f90d37 100644 --- a/source/blender/blenkernel/intern/seqcache.c +++ b/source/blender/blenkernel/intern/seqcache.c @@ -90,7 +90,6 @@ typedef struct SeqCacheKey { struct SeqCacheKey *link_next; /* Used for linking intermediate items to final frame */ struct Sequence *seq; SeqRenderData context; - float cfra; float nfra; float cost; bool is_temp_cache; @@ -232,14 +231,17 @@ static SeqCacheKey *seq_cache_choose_key(Scene *scene, SeqCacheKey *lkey, SeqCac SeqCacheKey *finalkey = NULL; if (rkey && lkey) { - if (lkey->cfra > rkey->cfra) { + int lkey_cfra = lkey->seq->start + lkey->nfra; + int rkey_cfra = rkey->seq->start + rkey->nfra; + + if (lkey_cfra > rkey_cfra) { SeqCacheKey *swapkey = lkey; lkey = rkey; rkey = swapkey; } - int l_diff = scene->r.cfra - lkey->cfra; - int r_diff = rkey->cfra - scene->r.cfra; + int l_diff = scene->r.cfra - lkey_cfra; + int r_diff = rkey_cfra - scene->r.cfra; if (l_diff > r_diff) { finalkey = lkey; @@ -319,7 +321,7 @@ static SeqCacheKey *seq_cache_get_item_for_removal(Scene *scene) if (key->cost <= scene->ed->recycle_max_cost) { cheap_count++; if (lkey) { - if (key->cfra < lkey->cfra) { + if (key->seq->start + key->nfra < lkey->seq->start + lkey->nfra) { lkey = key; } } @@ -327,7 +329,7 @@ static SeqCacheKey *seq_cache_get_item_for_removal(Scene *scene) lkey = key; } if (rkey) { - if (key->cfra > rkey->cfra) { + if (key->seq->start + key->nfra > rkey->seq->start + rkey->nfra) { rkey = key; } } @@ -425,7 +427,7 @@ void BKE_sequencer_cache_free_temp_cache(Scene *scene, short id, int cfra) SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); BLI_ghashIterator_step(&gh_iter); - if (key->is_temp_cache && key->creator_id == id && key->cfra != cfra) { + if (key->is_temp_cache && key->creator_id == id && key->seq->start + key->nfra != cfra) { BLI_ghash_remove(cache->hash, key, seq_cache_keyfree, seq_cache_valfree); } } @@ -474,7 +476,10 @@ void BKE_sequencer_cache_cleanup(Scene *scene) seq_cache_unlock(scene); } -void BKE_sequencer_cache_cleanup_sequence(Scene *scene, Sequence *seq) +void BKE_sequencer_cache_cleanup_sequence(Scene *scene, + Sequence *seq, + Sequence *seq_changed, + int invalidate_types) { SeqCache *cache = seq_cache_get_from_scene(scene); if (!cache) { @@ -483,14 +488,40 @@ void BKE_sequencer_cache_cleanup_sequence(Scene *scene, Sequence *seq) seq_cache_lock(scene); + int range_start = seq_changed->startdisp; + int range_end = seq_changed->enddisp; + + if (seq->startdisp > range_start) { + range_start = seq->startdisp; + } + + if (seq->enddisp < range_end) { + range_end = seq->enddisp; + } + + int invalidate_composite = invalidate_types & SEQ_CACHE_STORE_FINAL_OUT; + int invalidate_source = invalidate_types & (SEQ_CACHE_STORE_RAW | SEQ_CACHE_STORE_PREPROCESSED | + SEQ_CACHE_STORE_COMPOSITE); + GHashIterator gh_iter; BLI_ghashIterator_init(&gh_iter, cache->hash); while (!BLI_ghashIterator_done(&gh_iter)) { SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); BLI_ghashIterator_step(&gh_iter); - if (key->seq == seq) { - /* Relink keys, so we don't end up with orphaned keys */ + int key_cfra = key->seq->start + key->nfra; + + /* clean all final and composite in intersection of seq and seq_changed */ + if (key->type & invalidate_composite && key_cfra >= range_start && key_cfra <= range_end) { + if (key->link_next || key->link_prev) { + seq_cache_relink_keys(key->link_next, key->link_prev); + } + + BLI_ghash_remove(cache->hash, key, seq_cache_keyfree, seq_cache_valfree); + } + + if (key->type & invalidate_source && key->seq == seq && key_cfra >= seq_changed->startdisp && + key_cfra <= seq_changed->enddisp) { if (key->link_next || key->link_prev) { seq_cache_relink_keys(key->link_next, key->link_prev); } @@ -592,7 +623,6 @@ void BKE_sequencer_cache_put( key->cache_owner = cache; key->seq = seq; key->context = *context; - key->cfra = cfra; key->nfra = cfra - seq->start; key->type = type; key->cost = cost; @@ -634,7 +664,7 @@ void BKE_sequencer_cache_put( void BKE_sequencer_cache_iterate( struct Scene *scene, void *userdata, - bool callback(void *userdata, struct Sequence *seq, int cfra, int cache_type, float cost)) + bool callback(void *userdata, struct Sequence *seq, int nfra, int cache_type, float cost)) { SeqCache *cache = seq_cache_get_from_scene(scene); if (!cache) { @@ -650,7 +680,7 @@ void BKE_sequencer_cache_iterate( SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); BLI_ghashIterator_step(&gh_iter); - interrupt = callback(userdata, key->seq, key->cfra, key->type, key->cost); + interrupt = callback(userdata, key->seq, key->nfra, key->type, key->cost); } cache->last_key = NULL; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 99536b979b6..827d7343aad 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -279,7 +279,7 @@ static void BKE_sequence_free_ex(Scene *scene, */ if (do_cache) { if (scene) { - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_raw(scene, seq); } } @@ -3546,7 +3546,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, IB_rect, draw_flags, scene->r.alphamode, - 0, /* no aa samples */ + U.ogl_multisamples, viewname, context->gpu_offscreen, err_out); @@ -4307,7 +4307,8 @@ static void sequence_do_invalidate_dependent(Scene *scene, Sequence *seq, ListBa } if (BKE_sequence_check_depend(seq, cur)) { - BKE_sequencer_cache_cleanup_sequence(scene, cur); + BKE_sequencer_cache_cleanup_sequence( + scene, cur, seq, SEQ_CACHE_STORE_COMPOSITE | SEQ_CACHE_STORE_FINAL_OUT); } if (cur->seqbase.first) { @@ -4319,46 +4320,46 @@ static void sequence_do_invalidate_dependent(Scene *scene, Sequence *seq, ListBa static void sequence_invalidate_cache(Scene *scene, Sequence *seq, bool invalidate_self, - bool UNUSED(invalidate_preprocess)) + int invalidate_types) { Editing *ed = scene->ed; - /* invalidate cache for current sequence */ if (invalidate_self) { - /* Animation structure holds some buffers inside, - * so for proper cache invalidation we need to - * re-open the animation. - */ BKE_sequence_free_anim(seq); - BKE_sequencer_cache_cleanup_sequence(scene, seq); + BKE_sequencer_cache_cleanup_sequence(scene, seq, seq, invalidate_types); } - /* if invalidation is invoked from sequence free routine, effectdata would be NULL here */ if (seq->effectdata && seq->type == SEQ_TYPE_SPEED) { BKE_sequence_effect_speed_rebuild_map(scene, seq, true); } - /* invalidate cache for all dependent sequences */ - - /* NOTE: can not use SEQ_BEGIN/SEQ_END here because that macro will change sequence's depth, - * which makes transformation routines work incorrect - */ sequence_do_invalidate_dependent(scene, seq, &ed->seqbase); } -void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq) +void BKE_sequence_invalidate_cache_raw(Scene *scene, Sequence *seq) { - sequence_invalidate_cache(scene, seq, true, true); + sequence_invalidate_cache(scene, seq, true, SEQ_CACHE_ALL_TYPES); } -void BKE_sequence_invalidate_dependent(Scene *scene, Sequence *seq) +void BKE_sequence_invalidate_cache_preprocessed(Scene *scene, Sequence *seq) { - sequence_invalidate_cache(scene, seq, false, true); + sequence_invalidate_cache(scene, + seq, + true, + SEQ_CACHE_STORE_PREPROCESSED | SEQ_CACHE_STORE_COMPOSITE | + SEQ_CACHE_STORE_FINAL_OUT); } -void BKE_sequence_invalidate_cache_for_modifier(Scene *scene, Sequence *seq) +void BKE_sequence_invalidate_cache_composite(Scene *scene, Sequence *seq) { - sequence_invalidate_cache(scene, seq, true, false); + sequence_invalidate_cache( + scene, seq, true, SEQ_CACHE_STORE_COMPOSITE | SEQ_CACHE_STORE_FINAL_OUT); +} + +void BKE_sequence_invalidate_dependent(Scene *scene, Sequence *seq) +{ + sequence_invalidate_cache( + scene, seq, false, SEQ_CACHE_STORE_COMPOSITE | SEQ_CACHE_STORE_FINAL_OUT); } void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render) @@ -4932,7 +4933,7 @@ void BKE_sequencer_update_sound_bounds_all(Scene *scene) void BKE_sequencer_update_sound_bounds(Scene *scene, Sequence *seq) { if (seq->type == SEQ_TYPE_SCENE) { - if (seq->scene_sound) { + if (seq->scene && seq->scene_sound) { /* We have to take into account start frame of the sequence's scene! */ int startofs = seq->startofs + seq->anim_startofs + seq->scene->r.sfra; @@ -5352,6 +5353,15 @@ static void seq_load_apply(Main *bmain, Scene *scene, Sequence *seq, SeqLoadInfo } } +static Strip *seq_strip_alloc(void) +{ + Strip *strip = MEM_callocN(sizeof(Strip), "strip"); + strip->transform = MEM_callocN(sizeof(struct StripTransform), "StripTransform"); + strip->crop = MEM_callocN(sizeof(struct StripCrop), "StripCrop"); + + return strip; +} + Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine) { Sequence *seq; @@ -5460,7 +5470,7 @@ Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoad seq->blend_mode = SEQ_TYPE_ALPHAOVER; /* basic defaults */ - seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); + seq->strip = strip = seq_strip_alloc(); seq->len = seq_load->len ? seq_load->len : 1; strip->us = 1; @@ -5515,7 +5525,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq); /* basic defaults */ - seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); + seq->strip = strip = seq_strip_alloc(); /* We add a very small negative offset here, because * ceil(132.0) == 133.0, not nice with videos, see T47135. */ seq->len = (int)ceil((double)info.length * FPS - 1e-4); @@ -5647,7 +5657,7 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad } /* basic defaults */ - seq->strip = strip = MEM_callocN(sizeof(Strip), "strip"); + seq->strip = strip = seq_strip_alloc(); seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN); strip->us = 1; @@ -5668,12 +5678,12 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) { int start_frame_back = seq_load->start_frame; - seq_load->channel++; + seq_load->channel--; seq_load->seq_sound = BKE_sequencer_add_sound_strip(C, seqbasep, seq_load); seq_load->start_frame = start_frame_back; - seq_load->channel--; + seq_load->channel++; } /* can be NULL */ diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c index e0ff5fcccca..20f2a9be53b 100644 --- a/source/blender/blenkernel/intern/studiolight.c +++ b/source/blender/blenkernel/intern/studiolight.c @@ -1246,6 +1246,59 @@ static void studiolight_irradiance_preview(uint *icon_buffer, StudioLight *sl) ITER_PIXELS_END; } +void BKE_studiolight_default(SolidLight lights[4], float light_ambient[4]) +{ + copy_v3_fl3(light_ambient, 0.0, 0.0, 0.0); + + lights[0].flag = 1; + lights[0].smooth = 0.526620f; + lights[0].col[0] = 0.033103f; + lights[0].col[1] = 0.033103f; + lights[0].col[2] = 0.033103f; + lights[0].spec[0] = 0.266761f; + lights[0].spec[1] = 0.266761f; + lights[0].spec[2] = 0.266761f; + lights[0].vec[0] = -0.352546f; + lights[0].vec[1] = 0.170931f; + lights[0].vec[2] = -0.920051f; + + lights[1].flag = 1; + lights[1].smooth = 0.000000f; + lights[1].col[0] = 0.521083f; + lights[1].col[1] = 0.538226f; + lights[1].col[2] = 0.538226f; + lights[1].spec[0] = 0.599030f; + lights[1].spec[1] = 0.599030f; + lights[1].spec[2] = 0.599030f; + lights[1].vec[0] = -0.408163f; + lights[1].vec[1] = 0.346939f; + lights[1].vec[2] = 0.844415f; + + lights[2].flag = 1; + lights[2].smooth = 0.478261f; + lights[2].col[0] = 0.038403f; + lights[2].col[1] = 0.034357f; + lights[2].col[2] = 0.049530f; + lights[2].spec[0] = 0.106102f; + lights[2].spec[1] = 0.125981f; + lights[2].spec[2] = 0.158523f; + lights[2].vec[0] = 0.521739f; + lights[2].vec[1] = 0.826087f; + lights[2].vec[2] = 0.212999f; + + lights[3].flag = 1; + lights[3].smooth = 0.200000f; + lights[3].col[0] = 0.090838f; + lights[3].col[1] = 0.082080f; + lights[3].col[2] = 0.072255f; + lights[3].spec[0] = 0.106535f; + lights[3].spec[1] = 0.084771f; + lights[3].spec[2] = 0.066080f; + lights[3].vec[0] = 0.624519f; + lights[3].vec[1] = -0.562067f; + lights[3].vec[2] = -0.542269f; +} + /* API */ void BKE_studiolight_init(void) { @@ -1255,32 +1308,6 @@ void BKE_studiolight_init(void) STUDIOLIGHT_TYPE_STUDIO); BLI_strncpy(sl->name, "Default", FILE_MAXFILE); - copy_v3_fl3(sl->light_ambient, 0.025000, 0.025000, 0.025000); - - copy_v4_fl4(sl->light[0].vec, -0.580952, 0.228571, 0.781185, 0.0); - copy_v4_fl4(sl->light[0].col, 0.900000, 0.900000, 0.900000, 1.000000); - copy_v4_fl4(sl->light[0].spec, 0.318547, 0.318547, 0.318547, 1.000000); - sl->light[0].flag = 1; - sl->light[0].smooth = 0.1; - - copy_v4_fl4(sl->light[1].vec, 0.788218, 0.593482, -0.162765, 0.0); - copy_v4_fl4(sl->light[1].col, 0.267115, 0.269928, 0.358840, 1.000000); - copy_v4_fl4(sl->light[1].spec, 0.090838, 0.090838, 0.090838, 1.000000); - sl->light[1].flag = 1; - sl->light[1].smooth = 0.25; - - copy_v4_fl4(sl->light[2].vec, 0.696472, -0.696472, -0.172785, 0.0); - copy_v4_fl4(sl->light[2].col, 0.293216, 0.304662, 0.401968, 1.000000); - copy_v4_fl4(sl->light[2].spec, 0.069399, 0.020331, 0.020331, 1.000000); - sl->light[2].flag = 1; - sl->light[2].smooth = 0.5; - - copy_v4_fl4(sl->light[3].vec, 0.021053, -0.989474, 0.143173, 0.0); - copy_v4_fl4(sl->light[3].col, 0.0, 0.0, 0.0, 1.0); - copy_v4_fl4(sl->light[3].spec, 0.072234, 0.082253, 0.162642, 1.000000); - sl->light[3].flag = 1; - sl->light[3].smooth = 0.7; - BLI_addtail(&studiolights, sl); /* go over the preset folder and add a studiolight for every image with its path */ @@ -1307,6 +1334,8 @@ void BKE_studiolight_init(void) /* sort studio lights on filename. */ BLI_listbase_sort(&studiolights, studiolight_cmp); + + BKE_studiolight_default(sl->light, sl->light_ambient); } void BKE_studiolight_free(void) diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index d3e0ff56977..caf88eb0fff 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -29,6 +29,8 @@ #include "BLI_listbase.h" #include "BLI_string.h" +#include "BLT_translation.h" + #include "DNA_listBase.h" #include "DNA_windowmanager_types.h" @@ -337,7 +339,7 @@ static bool undosys_stack_push_main(UndoStack *ustack, const char *name, struct void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain) { UNDO_NESTED_ASSERT(false); - undosys_stack_push_main(ustack, "original", bmain); + undosys_stack_push_main(ustack, IFACE_("Original"), bmain); } /* called after 'BKE_undosys_stack_init_from_main' */ @@ -345,7 +347,7 @@ void BKE_undosys_stack_init_from_context(UndoStack *ustack, bContext *C) { const UndoType *ut = BKE_undosys_type_from_context(C); if ((ut != NULL) && (ut != BKE_UNDOSYS_TYPE_MEMFILE)) { - BKE_undosys_step_push_with_type(ustack, C, "original mode", ut); + BKE_undosys_step_push_with_type(ustack, C, IFACE_("Original Mode"), ut); } } diff --git a/source/blender/blenlib/BLI_buffer.h b/source/blender/blenlib/BLI_buffer.h index 9f3644ed45a..6fe1e9bb693 100644 --- a/source/blender/blenlib/BLI_buffer.h +++ b/source/blender/blenlib/BLI_buffer.h @@ -21,7 +21,7 @@ * \ingroup bli */ -typedef struct { +typedef struct BLI_Buffer { void *data; const size_t elem_size; size_t count, alloc_count; diff --git a/source/blender/blenlib/BLI_callbacks.h b/source/blender/blenlib/BLI_callbacks.h index ed8af49d640..4d9fc66a806 100644 --- a/source/blender/blenlib/BLI_callbacks.h +++ b/source/blender/blenlib/BLI_callbacks.h @@ -52,6 +52,7 @@ typedef enum { BLI_CB_EVT_DEPSGRAPH_UPDATE_PRE, BLI_CB_EVT_DEPSGRAPH_UPDATE_POST, BLI_CB_EVT_VERSION_UPDATE, + BLI_CB_EVT_LOAD_FACTORY_USERDEF_POST, BLI_CB_EVT_LOAD_FACTORY_STARTUP_POST, BLI_CB_EVT_TOT, } eCbEvent; diff --git a/source/blender/blenlib/BLI_memblock.h b/source/blender/blenlib/BLI_memblock.h index 81dd2100362..c5ef26ffb91 100644 --- a/source/blender/blenlib/BLI_memblock.h +++ b/source/blender/blenlib/BLI_memblock.h @@ -35,16 +35,19 @@ 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; +BLI_memblock *BLI_memblock_create(uint elem_size) 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; + void **chunk_list; + int cur_index; + int end_index; + int chunk_max_ofs; + int chunk_idx; + int elem_size; + int elem_ofs; } BLI_memblock_iter; void BLI_memblock_iternew(BLI_memblock *pool, BLI_memblock_iter *iter) ATTR_NONNULL(); diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h index f23580916b1..e3cd70f7413 100644 --- a/source/blender/blenlib/BLI_rect.h +++ b/source/blender/blenlib/BLI_rect.h @@ -62,6 +62,10 @@ void BLI_rcti_resize(struct rcti *rect, int x, int y); void BLI_rctf_resize(struct rctf *rect, float x, float y); void BLI_rcti_scale(rcti *rect, const float scale); void BLI_rctf_scale(rctf *rect, const float scale); +void BLI_rctf_pad_y(struct rctf *rect, + const float boundary_size, + const float pad_min, + const float pad_max); void BLI_rctf_interp(struct rctf *rect, const struct rctf *rect_a, const struct rctf *rect_b, diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c index 0f7ac92a348..b20a0eafd74 100644 --- a/source/blender/blenlib/intern/BLI_memarena.c +++ b/source/blender/blenlib/intern/BLI_memarena.c @@ -53,8 +53,9 @@ #if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer) # include "sanitizer/asan_interface.h" #else -# define ASAN_POISON_MEMORY_REGION(addr, size) UNUSED_VARS(addr, size) -# define ASAN_UNPOISON_MEMORY_REGION(addr, size) UNUSED_VARS(addr, size) +/* Ensure return value is used. */ +# define ASAN_POISON_MEMORY_REGION(addr, size) (void)(0 && ((size) != 0 && (addr) != NULL)) +# define ASAN_UNPOISON_MEMORY_REGION(addr, size) (void)(0 && ((size) != 0 && (addr) != NULL)) #endif struct MemBuf { diff --git a/source/blender/blenlib/intern/BLI_memblock.c b/source/blender/blenlib/intern/BLI_memblock.c index 50b1e14757c..ec9b74f2b50 100644 --- a/source/blender/blenlib/intern/BLI_memblock.c +++ b/source/blender/blenlib/intern/BLI_memblock.c @@ -49,18 +49,19 @@ struct BLI_memblock { int elem_next; /** Last "touched" element. */ int elem_last; + /** Offset in a chunk of the next elem. */ + int elem_next_ofs; + /** Max offset in a chunk. */ + int chunk_max_ofs; + /** Id of the chunk used for the next allocation. */ + int chunk_next; /** 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_memblock *BLI_memblock_create(uint elem_size) { BLI_assert(elem_size < BLI_MEM_BLOCK_CHUNK_SIZE); @@ -71,22 +72,16 @@ BLI_memblock *BLI_memblock_create(uint elem_size, const bool clear_alloc) 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; + mblk->chunk_list[0] = MEM_callocN((uint)mblk->chunk_size, "BLI_memblock chunk"); + mblk->chunk_max_ofs = (mblk->chunk_size / mblk->elem_size) * mblk->elem_size; + mblk->elem_next_ofs = 0; + mblk->chunk_next = 0; 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); - } - } + BLI_memblock_clear(mblk, free_callback); for (int i = 0; i < mblk->chunk_len; i++) { MEM_SAFE_FREE(mblk->chunk_list[i]); @@ -100,7 +95,7 @@ void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback) 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; + int last_used_chunk = mblk->elem_next / elem_per_chunk; if (free_callback) { for (int i = mblk->elem_last; i >= mblk->elem_next; i--) { @@ -122,53 +117,66 @@ void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP free_callback) mblk->elem_last = mblk->elem_next - 1; mblk->elem_next = 0; + mblk->elem_next_ofs = 0; + mblk->chunk_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; - + /* Bookeeping. */ 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); - } + void *ptr = (char *)(mblk->chunk_list[mblk->chunk_next]) + mblk->elem_next_ofs; + + mblk->elem_next_ofs += mblk->elem_size; + + if (mblk->elem_next_ofs == mblk->chunk_max_ofs) { + mblk->elem_next_ofs = 0; + mblk->chunk_next++; - 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"); + if (UNLIKELY(mblk->chunk_next >= mblk->chunk_len)) { + mblk->chunk_len += CHUNK_LIST_SIZE; + mblk->chunk_list = MEM_recallocN(mblk->chunk_list, sizeof(void *) * (uint)mblk->chunk_len); } - else { - mblk->chunk_list[chunk_idx] = MEM_mallocN((uint)mblk->chunk_size, "BLI_memblock chunk"); + + if (UNLIKELY(mblk->chunk_list[mblk->chunk_next] == NULL)) { + mblk->chunk_list[mblk->chunk_next] = MEM_callocN((uint)mblk->chunk_size, + "BLI_memblock chunk"); } } - - return (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx; + return ptr; } 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; + /* Small copy of the memblock used for better cache coherence. */ + iter->chunk_list = mblk->chunk_list; + iter->end_index = mblk->elem_next; + iter->cur_index = 0; + iter->chunk_idx = 0; + iter->elem_ofs = 0; + iter->elem_size = mblk->elem_size; + iter->chunk_max_ofs = mblk->chunk_max_ofs; } void *BLI_memblock_iterstep(BLI_memblock_iter *iter) { - if (iter->current_index >= iter->mblk->elem_next) { + if (iter->cur_index == iter->end_index) { 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++; + iter->cur_index++; + + void *ptr = (char *)(iter->chunk_list[iter->chunk_idx]) + iter->elem_ofs; - return (char *)(iter->mblk->chunk_list[chunk_idx]) + iter->mblk->elem_size * elem_idx; + iter->elem_ofs += iter->elem_size; + + if (iter->elem_ofs == iter->chunk_max_ofs) { + iter->elem_ofs = 0; + iter->chunk_idx++; + } + return ptr; } diff --git a/source/blender/blenlib/intern/BLI_memiter.c b/source/blender/blenlib/intern/BLI_memiter.c index c7df7d5fdd4..4027a62bbcc 100644 --- a/source/blender/blenlib/intern/BLI_memiter.c +++ b/source/blender/blenlib/intern/BLI_memiter.c @@ -57,8 +57,9 @@ #if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer) # include "sanitizer/asan_interface.h" #else -# define ASAN_POISON_MEMORY_REGION(addr, size) UNUSED_VARS(addr, size) -# define ASAN_UNPOISON_MEMORY_REGION(addr, size) UNUSED_VARS(addr, size) +/* Ensure return value is used. */ +# define ASAN_POISON_MEMORY_REGION(addr, size) (void)(0 && ((size) != 0 && (addr) != NULL)) +# define ASAN_UNPOISON_MEMORY_REGION(addr, size) (void)(0 && ((size) != 0 && (addr) != NULL)) #endif typedef uintptr_t data_t; @@ -239,6 +240,10 @@ static void memiter_free_data(BLI_memiter *mi) BLI_memiter_chunk *chunk = mi->head; while (chunk) { BLI_memiter_chunk *chunk_next = chunk->next; + + /* Unpoison memory because MEM_freeN might overwrite it. */ + ASAN_UNPOISON_MEMORY_REGION(chunk, MEM_allocN_len(chunk)); + MEM_freeN(chunk); chunk = chunk_next; } diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 3bb60a20fc8..61b773f6016 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1855,7 +1855,10 @@ const char *BLI_path_basename(const char *path) * * Ignores multiple slashes at any point in the path (including start/end). */ -bool BLI_path_name_at_index(const char *path, const int index, int *r_offset, int *r_len) +bool BLI_path_name_at_index(const char *__restrict path, + const int index, + int *__restrict r_offset, + int *__restrict r_len) { if (index >= 0) { int index_step = 0; diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c index 5000b3df92b..99288abb38c 100644 --- a/source/blender/blenlib/intern/rct.c +++ b/source/blender/blenlib/intern/rct.c @@ -643,6 +643,25 @@ void BLI_rctf_scale(rctf *rect, const float scale) rect->ymax = cent_y + size_y_half; } +void BLI_rctf_pad_y(rctf *rect, + const float boundary_size, + const float pad_min, + const float pad_max) +{ + BLI_assert(pad_max >= 0.0f); + BLI_assert(pad_min >= 0.0f); + BLI_assert(boundary_size > 0.0f); + + float total_pad = pad_max + pad_min; + if (total_pad == 0.0f) { + return; + } + + float total_extend = BLI_rctf_size_y(rect) * total_pad / (boundary_size - total_pad); + rect->ymax += total_extend * (pad_max / total_pad); + rect->ymin -= total_extend * (pad_min / total_pad); +} + void BLI_rctf_interp(rctf *rect, const rctf *rect_a, const rctf *rect_b, const float fac) { const float ifac = 1.0f - fac; diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index 3348912f02a..88f2e2625e8 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -33,7 +33,10 @@ #if defined(WIN32) # include <intrin.h> # include <windows.h> +# pragma warning(push) +# pragma warning(disable : 4091) # include <dbghelp.h> +# pragma warning(pop) #else # include <execinfo.h> # include <unistd.h> @@ -122,7 +125,7 @@ void BLI_system_backtrace(FILE *fp) for (i = 0; i < nframes; i++) { SymFromAddr(process, (DWORD64)(stack[i]), 0, symbolinfo); - fprintf(fp, "%u: %s - 0x%0X\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address); + fprintf(fp, "%u: %s - 0x%0llX\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address); } MEM_freeN(symbolinfo); diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c index 6f9ff02ce17..85d39f2f98e 100644 --- a/source/blender/blenlib/intern/task.c +++ b/source/blender/blenlib/intern/task.c @@ -211,6 +211,10 @@ struct TaskScheduler { ThreadMutex queue_mutex; ThreadCondition queue_cond; + ThreadMutex startup_mutex; + ThreadCondition startup_cond; + volatile int num_thread_started; + volatile bool do_exit; /* NOTE: In pthread's TLS we store the whole TaskThread structure. */ @@ -429,6 +433,14 @@ static void *task_scheduler_thread_run(void *thread_p) pthread_setspecific(scheduler->tls_id_key, thread); + /* signal the main thread when all threads have started */ + BLI_mutex_lock(&scheduler->startup_mutex); + scheduler->num_thread_started++; + if (scheduler->num_thread_started == scheduler->num_threads) { + BLI_condition_notify_one(&scheduler->startup_cond); + } + BLI_mutex_unlock(&scheduler->startup_mutex); + /* keep popping off tasks */ while (task_scheduler_thread_wait_pop(scheduler, &task)) { TaskPool *pool = task->pool; @@ -463,6 +475,10 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads) BLI_mutex_init(&scheduler->queue_mutex); BLI_condition_init(&scheduler->queue_cond); + BLI_mutex_init(&scheduler->startup_mutex); + BLI_condition_init(&scheduler->startup_cond); + scheduler->num_thread_started = 0; + if (num_threads == 0) { /* automatic number of threads will be main thread + num cores */ num_threads = BLI_system_thread_count(); @@ -504,6 +520,17 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads) } } + /* Wait for all worker threads to start before returning to caller to prevent the case where + * threads are still starting and pthread_join is called, which causes a deadlock on pthreads4w. + */ + BLI_mutex_lock(&scheduler->startup_mutex); + /* NOTE: Use loop here to avoid false-positive everything-is-ready caused by spontaneous thread + * wake up. */ + while (scheduler->num_thread_started != num_threads) { + BLI_condition_wait(&scheduler->startup_cond, &scheduler->startup_mutex); + } + BLI_mutex_unlock(&scheduler->startup_mutex); + return scheduler; } @@ -551,6 +578,8 @@ void BLI_task_scheduler_free(TaskScheduler *scheduler) /* delete mutex/condition */ BLI_mutex_end(&scheduler->queue_mutex); BLI_condition_end(&scheduler->queue_cond); + BLI_mutex_end(&scheduler->startup_mutex); + BLI_condition_end(&scheduler->startup_cond); MEM_freeN(scheduler); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 0d81c55b0f2..b32745e41ee 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -325,8 +325,8 @@ typedef struct OldNewMap { int capacity_exp; } OldNewMap; -#define ENTRIES_CAPACITY(onm) (1 << (onm)->capacity_exp) -#define MAP_CAPACITY(onm) (1 << ((onm)->capacity_exp + 1)) +#define ENTRIES_CAPACITY(onm) (1ll << (onm)->capacity_exp) +#define MAP_CAPACITY(onm) (1ll << ((onm)->capacity_exp + 1)) #define SLOT_MASK(onm) (MAP_CAPACITY(onm) - 1) #define DEFAULT_SIZE_EXP 6 #define PERTURB_SHIFT 5 @@ -4119,8 +4119,6 @@ static void direct_link_world(FileData *fd, World *wrld) BLI_listbase_clear(&wrld->gpumaterial); } -/* ************ READ VFONT ***************** */ - /** \} */ /* -------------------------------------------------------------------- */ @@ -6229,20 +6227,11 @@ static void lib_link_collection_data(FileData *fd, Library *lib, Collection *col } } - for (CollectionChild *child = collection->children.first, *child_next = NULL; child; - child = child_next) { - child_next = child->next; + for (CollectionChild *child = collection->children.first; child != NULL; child = child->next) { child->collection = newlibadr_us(fd, lib, child->collection); - - if (child->collection == NULL || BKE_collection_find_cycle(collection, child->collection)) { - BLI_freelinkN(&collection->children, child); - } - else { - CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), "CollectionParent"); - cparent->collection = collection; - BLI_addtail(&child->collection->parents, cparent); - } } + + BKE_collection_parent_relations_rebuild(collection); } static void lib_link_collection(FileData *fd, Main *main) @@ -8697,8 +8686,6 @@ static void lib_link_mask(FileData *fd, Main *main) } } -/* ************ READ LINE STYLE ***************** */ - /** \} */ /* -------------------------------------------------------------------- */ @@ -8957,8 +8944,6 @@ static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle) } } -/* ************** GENERAL & MAIN ******************** */ - /** \} */ /* -------------------------------------------------------------------- */ @@ -9540,6 +9525,19 @@ static void lib_link_all(FileData *fd, Main *main) /* We could integrate that to mesh/curve/lattice lib_link, but this is really cheap process, * so simpler to just use it directly in this single call. */ BLO_main_validate_shapekeys(main, NULL); + + if (fd->memfile != NULL) { + /* When doing redo, we perform a tremendous amount of esoterics magic tricks to avoid having to + * re-read all library datablocks. + * Unfortunately, that means that we do not clear Collections' parents lists, which then get + * improperly extended in some cases by lib_link_scene() and lib_link_collection() calls above + * (when ome local collection is parent of linked ones). + * I do not really see a way to address that issue, besides brute force call below which + * invalidates and re-creates all parenting relationships between collections. Yet another + * example of why it is such a bad idea to keep that kind of double-linked relationships info + * 'permanently' in our data structures... */ + BKE_main_collections_parent_relations_rebuild(main); + } } /** \} */ @@ -10812,6 +10810,15 @@ static void expand_camera(FileData *fd, Main *mainvar, Camera *ca) { expand_doit(fd, mainvar, ca->ipo); // XXX deprecated - old animation system + for (CameraBGImage *bgpic = ca->bg_images.first; bgpic; bgpic = bgpic->next) { + if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) { + expand_doit(fd, mainvar, bgpic->ima); + } + else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) { + expand_doit(fd, mainvar, bgpic->ima); + } + } + if (ca->adt) { expand_animdata(fd, mainvar, ca->adt); } diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index 77ef27182f2..7b0aab99aea 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -1808,6 +1808,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain) Image *image = blo_do_versions_newlibadr(fd, tex->id.lib, tex->ima); if (image && (image->flag & IMA_DO_PREMUL) == 0) { + const int IMA_IGNORE_ALPHA = (1 << 12); image->flag |= IMA_IGNORE_ALPHA; } } diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 6d5508fd7bd..71f67092fa7 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -715,6 +715,23 @@ static void do_version_constraints_copy_scale_power(ListBase *lb) } } +static void do_versions_seq_alloc_transform_and_crop(ListBase *seqbase) +{ + for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) { + if (seq->strip->transform == NULL) { + seq->strip->transform = MEM_callocN(sizeof(struct StripTransform), "StripTransform"); + } + + if (seq->strip->crop == NULL) { + seq->strip->crop = MEM_callocN(sizeof(struct StripCrop), "StripCrop"); + } + + if (seq->seqbase.first != NULL) { + do_versions_seq_alloc_transform_and_crop(&seq->seqbase); + } + } +} + void do_versions_after_linking_280(Main *bmain) { bool use_collection_compat_28 = true; @@ -2361,17 +2378,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { if (sl->spacetype == SPACE_VIEW3D) { View3D *v3d = (View3D *)sl; - v3d->shading.xray_alpha_wire = 0.5f; - } - } - } - } - - 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 (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *)sl; v3d->shading.flag |= V3D_SHADING_XRAY_BONE; } } @@ -3476,6 +3482,51 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 280, 70)) { + /* New image alpha modes. */ + LISTBASE_FOREACH (Image *, image, &bmain->images) { + const int IMA_IGNORE_ALPHA = (1 << 12); + if (image->flag & IMA_IGNORE_ALPHA) { + image->alpha_mode = IMA_ALPHA_IGNORE; + image->flag &= ~IMA_IGNORE_ALPHA; + } + } + } + + if (!MAIN_VERSION_ATLEAST(bmain, 280, 71)) { + /* This assumes the Blender builtin config. Depending on the OCIO + * environment variable for versioning is weak, and these deprecated view + * transforms and look names don't seem to exist in other commonly used + * OCIO configs so .blend files created for those would be unaffected. */ + for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + ColorManagedViewSettings *view_settings; + view_settings = &scene->view_settings; + + if (STREQ(view_settings->view_transform, "Default")) { + STRNCPY(view_settings->view_transform, "Standard"); + } + else if (STREQ(view_settings->view_transform, "RRT") || + STREQ(view_settings->view_transform, "Film")) { + STRNCPY(view_settings->view_transform, "Filmic"); + } + else if (STREQ(view_settings->view_transform, "Log")) { + STRNCPY(view_settings->view_transform, "Filmic Log"); + } + + if (STREQ(view_settings->look, "Filmic - Base Contrast")) { + STRNCPY(view_settings->look, "None"); + } + } + } + + if (!MAIN_VERSION_ATLEAST(bmain, 280, 72)) { + for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + if (scene->ed != NULL) { + do_versions_seq_alloc_transform_and_crop(&scene->ed->seqbase); + } + } + } + { /* Versioning code until next subversion bump goes here. */ } diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c index 93813df3c13..9bfbf4477ab 100644 --- a/source/blender/blenloader/intern/versioning_cycles.c +++ b/source/blender/blenloader/intern/versioning_cycles.c @@ -523,7 +523,7 @@ void do_versions_after_linking_cycles(Main *bmain) } /* No depth of field, set default settings. */ - camera->dof.aperture_fstop = 5.6f; + camera->dof.aperture_fstop = 2.8f; camera->dof.aperture_blades = 0; camera->dof.aperture_rotation = 0.0f; camera->dof.aperture_ratio = 1.0f; diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index d13f976a759..d22620f9224 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -26,6 +26,7 @@ #include "BLI_string.h" #include "BLI_system.h" +#include "DNA_camera_types.h" #include "DNA_gpencil_types.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" @@ -48,6 +49,7 @@ #include "BKE_node.h" #include "BKE_paint.h" #include "BKE_screen.h" +#include "BKE_studiolight.h" #include "BKE_workspace.h" #include "BLO_readfile.h" @@ -94,6 +96,9 @@ void BLO_update_defaults_userpref_blend(void) /* Leave temp directory empty, will then get appropriate value per OS. */ U.tempdir[0] = '\0'; + /* System-specific fonts directory. */ + BKE_appdir_font_folder_default(U.fontdir); + /* Only enable tooltips translation by default, * without actually enabling translation itself, for now. */ U.transopts = USER_TR_TOOLTIPS; @@ -110,6 +115,12 @@ void BLO_update_defaults_userpref_blend(void) /* Default to left click select. */ BKE_keyconfig_pref_set_select_mouse(&U, 0, true); + + /* Increase a little for new scrubbing area. */ + U.v2d_min_gridsize = 45; + + /* Default studio light. */ + BKE_studiolight_default(U.light_param, U.light_ambient); } /** @@ -155,9 +166,16 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { - /* Remove all stored panels, we want to use defaults - * (order, open/closed) as defined by UI code here! */ - BKE_area_region_panels_free(&ar->panels); + if (builtin_template) { + /* Remove all stored panels, we want to use defaults + * (order, open/closed) as defined by UI code here! */ + BKE_area_region_panels_free(&ar->panels); + BLI_freelistN(&ar->panels_category_active); + + /* Reset size so it uses consistent defaults from the region types. */ + ar->sizex = 0; + ar->sizey = 0; + } /* some toolbars have been saved as initialized, * we don't want them to have odd zoom-level or scrolling set, see: T47047 */ @@ -173,9 +191,13 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) v3d->overlay.texture_paint_mode_opacity = 1.0f; v3d->overlay.weight_paint_mode_opacity = 1.0f; v3d->overlay.vertex_paint_mode_opacity = 1.0f; + /* Use dimmed selected edges. */ + v3d->overlay.edit_flag &= ~V3D_OVERLAY_EDIT_EDGES; /* grease pencil settings */ v3d->vertex_opacity = 1.0f; v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES; + /* Remove dither pattern in wireframe mode. */ + v3d->shading.xray_alpha_wire = 0.0f; /* Skip startups that use the viewport color by default. */ if (v3d->shading.background_type != V3D_SHADING_BACKGROUND_VIEWPORT) { copy_v3_fl(v3d->shading.background_color, 0.05f); @@ -363,8 +385,8 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) scene->r.displaymode = R_OUTPUT_WINDOW; if (app_template && STREQ(app_template, "Video_Editing")) { - /* Filmic is too slow, use default until it is optimized. */ - STRNCPY(scene->view_settings.view_transform, "Default"); + /* Filmic is too slow, use standard until it is optimized. */ + STRNCPY(scene->view_settings.view_transform, "Standard"); STRNCPY(scene->view_settings.look, "None"); } else { @@ -398,6 +420,27 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) /* Match default for new meshes. */ mesh->smoothresh = DEG2RADF(30); } + + for (Camera *camera = bmain->cameras.first; camera; camera = camera->id.next) { + /* Initialize to a useful value. */ + camera->dof.focus_distance = 10.0f; + camera->dof.aperture_fstop = 2.8f; + } + + for (Material *ma = bmain->materials.first; ma; ma = ma->id.next) { + /* Update default material to be a bit more rough. */ + ma->roughness = 0.4f; + + if (ma->nodetree) { + for (bNode *node = ma->nodetree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_BSDF_PRINCIPLED) { + bNodeSocket *roughness_socket = nodeFindSocket(node, SOCK_IN, "Roughness"); + bNodeSocketValueFloat *roughness_data = roughness_socket->default_value; + roughness_data->value = 0.4f; + } + } + } + } } for (bScreen *sc = bmain->screens.first; sc; sc = sc->id.next) { @@ -415,6 +458,9 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) copy_v3_v3(scene->display.light_direction, (float[3]){M_SQRT1_3, M_SQRT1_3, M_SQRT1_3}); copy_v2_fl2(scene->safe_areas.title, 0.1f, 0.05f); copy_v2_fl2(scene->safe_areas.action, 0.035f, 0.035f); + + /* Change default cubemap quality. */ + scene->eevee.gi_filter_quality = 3.0f; } if (app_template == NULL) { diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index d1cb9d32212..89f4d86b1b8 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -127,11 +127,11 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme) 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); + FROM_DEFAULT_V4_UCHAR(space_graph.time_scrub_background); + FROM_DEFAULT_V4_UCHAR(space_action.time_scrub_background); + FROM_DEFAULT_V4_UCHAR(space_nla.time_scrub_background); + FROM_DEFAULT_V4_UCHAR(space_sequencer.time_scrub_background); + FROM_DEFAULT_V4_UCHAR(space_clip.time_scrub_background); } if (!USER_VERSION_ATLEAST(280, 67)) { diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 0279e4dd23e..78e8ce04115 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -126,6 +126,13 @@ enum { BEVEL_MITER_ARC, }; +/* Normal Face Strength values */ +enum { + FACE_STRENGTH_WEAK = -16384, + FACE_STRENGTH_MEDIUM = 0, + FACE_STRENGTH_STRONG = 16384, +}; + extern const BMOpDefine *bmo_opdefines[]; extern const int bmo_opdefines_total; diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index a559d13fc70..f0ffea0fbc8 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -1256,6 +1256,8 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv) pro->super_r = bp->pro_super_r; /* projection direction is direction of the edge */ sub_v3_v3v3(pro->proj_dir, e->e->v1->co, e->e->v2->co); + if (e->is_rev) + negate_v3(pro->proj_dir); normalize_v3(pro->proj_dir); project_to_edge(e->e, co1, co2, pro->midco); if (DEBUG_OLD_PROJ_TO_PERP_PLANE) { @@ -1378,19 +1380,28 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv) /* Move the profile plane for bndv to the plane containing e1 and e2, which share a vert */ static void move_profile_plane(BoundVert *bndv, EdgeHalf *e1, EdgeHalf *e2) { - float d1[3], d2[3], no[3], no2[3], dot; + float d1[3], d2[3], no[3], no2[3], no3[3], dot2, dot3; /* only do this if projecting, and e1, e2, and proj_dir are not coplanar */ if (is_zero_v3(bndv->profile.proj_dir)) { return; } sub_v3_v3v3(d1, e1->e->v1->co, e1->e->v2->co); + if (e1->is_rev) + negate_v3(d1); + normalize_v3(d1); sub_v3_v3v3(d2, e2->e->v1->co, e2->e->v2->co); + if (e2->is_rev) + negate_v3(d2); + normalize_v3(d2); cross_v3_v3v3(no, d1, d2); cross_v3_v3v3(no2, d1, bndv->profile.proj_dir); - if (normalize_v3(no) > BEVEL_EPSILON_BIG && normalize_v3(no2) > BEVEL_EPSILON_BIG) { - dot = fabsf(dot_v3v3(no, no2)); - if (fabsf(dot - 1.0f) > BEVEL_EPSILON_BIG) { + cross_v3_v3v3(no3, d2, bndv->profile.proj_dir); + if (normalize_v3(no) > BEVEL_EPSILON_BIG && normalize_v3(no2) > BEVEL_EPSILON_BIG && + normalize_v3(no3) > BEVEL_EPSILON_BIG) { + dot2 = dot_v3v3(no, no2); + dot3 = dot_v3v3(no, no3); + if (fabsf(dot2) < 0.95f && fabsf(dot3) < 0.95f) { copy_v3_v3(bndv->profile.plane_no, no); } } @@ -1821,6 +1832,9 @@ static void bevel_extend_edge_data(BevVert *bv) { VMesh *vm = bv->vmesh; + if (vm->mesh_kind == M_TRI_FAN) + return; + BoundVert *bcur = bv->vmesh->boundstart, *start = bcur; do { @@ -2340,7 +2354,7 @@ static void build_boundary_terminal_edge(BevelParams *bp, /* special case: snap profile to plane of adjacent two edges */ v = vm->boundstart; BLI_assert(v->ebev != NULL); - move_profile_plane(v, v->efirst, v->next->elast); + move_profile_plane(v, v->next->elast, v->efirst); calculate_profile(bp, v); } diff --git a/source/blender/collada/AnimationClipExporter.h b/source/blender/collada/AnimationClipExporter.h index 6d67ab7c406..ead894dc941 100644 --- a/source/blender/collada/AnimationClipExporter.h +++ b/source/blender/collada/AnimationClipExporter.h @@ -25,13 +25,13 @@ class AnimationClipExporter : COLLADASW::LibraryAnimationClips { Depsgraph *depsgraph; Scene *scene; COLLADASW::StreamWriter *sw; - const ExportSettings *export_settings; + BCExportSettings &export_settings; std::vector<std::vector<std::string>> anim_meta; public: AnimationClipExporter(Depsgraph *depsgraph, COLLADASW::StreamWriter *sw, - const ExportSettings *export_settings, + BCExportSettings &export_settings, std::vector<std::vector<std::string>> anim_meta) : COLLADASW::LibraryAnimationClips(sw), depsgraph(depsgraph), diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index a34f92f66d6..2c6ae8a52f5 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -77,24 +77,20 @@ void AnimationExporter::close_animation_container(bool has_container) bool AnimationExporter::exportAnimations() { - Scene *sce = blender_context.get_scene(); + Scene *sce = export_settings.get_scene(); - LinkNode &export_set = *this->export_settings->export_set; + LinkNode *export_set = this->export_settings.get_export_set(); bool has_anim_data = bc_has_animations(sce, export_set); int animation_count = 0; if (has_anim_data) { BCObjectSet animated_subset; - BCAnimationSampler::get_animated_from_export_set(animated_subset, export_set); + BCAnimationSampler::get_animated_from_export_set(animated_subset, *export_set); animation_count = animated_subset.size(); - BCAnimationSampler animation_sampler(blender_context, animated_subset); + BCAnimationSampler animation_sampler(export_settings, animated_subset); try { - animation_sampler.sample_scene(export_settings->sampling_rate, - /*keyframe_at_end = */ true, - export_settings->open_sim, - export_settings->keep_keyframes, - export_settings->export_animation_type); + animation_sampler.sample_scene(export_settings, /*keyframe_at_end = */ true); openLibrary(); @@ -137,7 +133,7 @@ void AnimationExporter::exportAnimation(Object *ob, BCAnimationSampler &sampler) * Note: For Armatures the skeletal animation has already been exported (see above) * However Armatures also can have Object animation. */ - bool export_as_matrix = this->export_settings->export_transformation_type == + bool export_as_matrix = this->export_settings.get_animation_transformation_type() == BC_TRANSFORMATION_TYPE_MATRIX; if (export_as_matrix) { @@ -178,7 +174,7 @@ void AnimationExporter::export_curve_animation_set(Object *ob, bool export_as_matrix) { BCAnimationCurveMap *curves = sampler.get_curves(ob); - bool keep_flat_curves = this->export_settings->keep_flat_curves; + bool keep_flat_curves = this->export_settings.get_keep_flat_curves(); BCAnimationCurveMap::iterator it; for (it = curves->begin(); it != curves->end(); ++it) { @@ -215,7 +211,7 @@ void AnimationExporter::export_curve_animation_set(Object *ob, void AnimationExporter::export_matrix_animation(Object *ob, BCAnimationSampler &sampler) { - bool keep_flat_curves = this->export_settings->keep_flat_curves; + bool keep_flat_curves = this->export_settings.get_keep_flat_curves(); std::vector<float> frames; sampler.get_object_frames(frames, ob); @@ -232,17 +228,31 @@ void AnimationExporter::export_matrix_animation(Object *ob, BCAnimationSampler & std::string target = translate_id(name) + '/' + channel_type; - export_collada_matrix_animation(id, name, target, frames, samples); + BC_global_rotation_type global_rotation_type = get_global_rotation_type(ob); + export_collada_matrix_animation( + id, name, target, frames, samples, global_rotation_type, ob->parentinv); } } } +BC_global_rotation_type AnimationExporter::get_global_rotation_type(Object *ob) +{ + bool is_export_root = this->export_settings.is_export_root(ob); + if (!is_export_root) { + return BC_NO_ROTATION; + } + + bool apply_global_rotation = this->export_settings.get_apply_global_orientation(); + + return (apply_global_rotation) ? BC_DATA_ROTATION : BC_OBJECT_ROTATION; +} + /* Write bone animations in transform matrix sources. */ void AnimationExporter::export_bone_animations_recursive(Object *ob, Bone *bone, BCAnimationSampler &sampler) { - bool keep_flat_curves = this->export_settings->keep_flat_curves; + bool keep_flat_curves = this->export_settings.get_keep_flat_curves(); std::vector<float> frames; sampler.get_bone_frames(frames, ob, bone); @@ -347,7 +357,9 @@ void AnimationExporter::export_curve_animation(Object *ob, BCAnimationCurve &cur collada_target += "/" + get_collada_sid(curve, axis); } - export_collada_curve_animation(id, curve_name, collada_target, axis, curve); + BC_global_rotation_type global_rotation_type = get_global_rotation_type(ob); + export_collada_curve_animation( + id, curve_name, collada_target, axis, curve, global_rotation_type); } void AnimationExporter::export_bone_animation(Object *ob, @@ -361,7 +373,9 @@ void AnimationExporter::export_bone_animation(Object *ob, std::string id = bc_get_action_id(id_name(action), name, bone_name, "pose_matrix"); std::string target = translate_id(id_name(ob) + "_" + bone_name) + "/transform"; - export_collada_matrix_animation(id, name, target, frames, samples); + BC_global_rotation_type global_rotation_type = get_global_rotation_type(ob); + export_collada_matrix_animation( + id, name, target, frames, samples, global_rotation_type, ob->parentinv); } bool AnimationExporter::is_bone_deform_group(Bone *bone) @@ -383,11 +397,13 @@ bool AnimationExporter::is_bone_deform_group(Bone *bone) return false; } -void AnimationExporter::export_collada_curve_animation(std::string id, - std::string name, - std::string collada_target, - std::string axis, - BCAnimationCurve &curve) +void AnimationExporter::export_collada_curve_animation( + std::string id, + std::string name, + std::string collada_target, + std::string axis, + BCAnimationCurve &curve, + BC_global_rotation_type global_rotation_type) { BCFrames frames; BCValues values; @@ -408,7 +424,7 @@ void AnimationExporter::export_collada_curve_animation(std::string id, bool has_tangents = false; std::string interpolation_id; - if (this->export_settings->keep_smooth_curves) + if (this->export_settings.get_keep_smooth_curves()) interpolation_id = collada_interpolation_source(curve, id, axis, &has_tangents); else interpolation_id = collada_linear_interpolation_source(frames.size(), id); @@ -444,11 +460,14 @@ void AnimationExporter::export_collada_curve_animation(std::string id, closeAnimation(); } -void AnimationExporter::export_collada_matrix_animation(std::string id, - std::string name, - std::string target, - BCFrames &frames, - BCMatrixSampleMap &samples) +void AnimationExporter::export_collada_matrix_animation( + std::string id, + std::string name, + std::string target, + BCFrames &frames, + BCMatrixSampleMap &samples, + BC_global_rotation_type global_rotation_type, + Matrix &parentinv) { fprintf( stdout, "Export animation matrix %s (%d control points)\n", id.c_str(), int(frames.size())); @@ -457,7 +476,7 @@ void AnimationExporter::export_collada_matrix_animation(std::string id, std::string input_id = collada_source_from_values( BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, ""); - std::string output_id = collada_source_from_values(samples, id); + std::string output_id = collada_source_from_values(samples, id, global_rotation_type, parentinv); std::string interpolation_id = collada_linear_interpolation_source(frames.size(), id); std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX; @@ -540,7 +559,8 @@ std::string AnimationExporter::collada_tangent_from_curve( const std::string &anim_id, std::string axis_name) { - Scene *scene = blender_context.get_scene(); + Scene *scene = this->export_settings.get_scene(); + std::string channel = curve.get_channel_target(); const std::string source_id = anim_id + get_semantic_suffix(semantic); @@ -585,6 +605,7 @@ std::string AnimationExporter::collada_source_from_values( const std::string &anim_id, const std::string axis_name) { + BlenderContext &blender_context = this->export_settings.get_blender_context(); Scene *scene = blender_context.get_scene(); /* T can be float, int or double */ @@ -623,11 +644,14 @@ std::string AnimationExporter::collada_source_from_values( return source_id; } -/** - * Create a collada matrix source for a set of samples. +/* + * Create a collada matrix source for a set of samples */ -std::string AnimationExporter::collada_source_from_values(BCMatrixSampleMap &samples, - const std::string &anim_id) +std::string AnimationExporter::collada_source_from_values( + BCMatrixSampleMap &samples, + const std::string &anim_id, + BC_global_rotation_type global_rotation_type, + Matrix &parentinv) { COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; std::string source_id = anim_id + get_semantic_suffix(semantic); @@ -645,11 +669,18 @@ std::string AnimationExporter::collada_source_from_values(BCMatrixSampleMap &sam BCMatrixSampleMap::iterator it; /* could be made configurable */ - int precision = (this->export_settings->limit_precision) ? 6 : -1; + int precision = (this->export_settings.get_limit_precision()) ? 6 : -1; for (it = samples.begin(); it != samples.end(); it++) { - const BCMatrix *sample = it->second; - double daemat[4][4]; - sample->get_matrix(daemat, true, precision); + BCMatrix sample = BCMatrix(*it->second); + BCMatrix global_transform = this->export_settings.get_global_transform(); + DMatrix daemat; + if (this->export_settings.get_apply_global_orientation()) { + sample.apply_transform(global_transform); + } + else { + sample.add_transform(global_transform); + } + sample.get_matrix(daemat, true, precision); source.appendValues(daemat); } diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h index 71d7d14a112..27474cc2b58 100644 --- a/source/blender/collada/AnimationExporter.h +++ b/source/blender/collada/AnimationExporter.h @@ -86,20 +86,22 @@ typedef enum BC_animation_source_type { BC_SOURCE_TYPE_TIMEFRAME, } BC_animation_source_type; +typedef enum BC_global_rotation_type { + BC_NO_ROTATION, + BC_OBJECT_ROTATION, + BC_DATA_ROTATION +} BC_global_rotation_type; + class AnimationExporter : COLLADASW::LibraryAnimations { private: - BlenderContext &blender_context; COLLADASW::StreamWriter *sw; - const ExportSettings *export_settings; + BCExportSettings &export_settings; + + BC_global_rotation_type get_global_rotation_type(Object *ob); public: - AnimationExporter(BlenderContext &blender_context, - COLLADASW::StreamWriter *sw, - const ExportSettings *export_settings) - : COLLADASW::LibraryAnimations(sw), - blender_context(blender_context), - sw(sw), - export_settings(export_settings) + AnimationExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings) + : COLLADASW::LibraryAnimations(sw), sw(sw), export_settings(export_settings) { } @@ -176,14 +178,17 @@ class AnimationExporter : COLLADASW::LibraryAnimations { std::string name, std::string target, std::string axis, - BCAnimationCurve &curve); + BCAnimationCurve &curve, + BC_global_rotation_type global_rotation_type); /* call to the low level collada exporter */ void export_collada_matrix_animation(std::string id, std::string name, std::string target, BCFrames &frames, - BCMatrixSampleMap &outmats); + BCMatrixSampleMap &outmats, + BC_global_rotation_type global_rotation_type, + Matrix &parentinv); BCAnimationCurve *get_modified_export_curve(Object *ob, BCAnimationCurve &curve, @@ -202,7 +207,10 @@ class AnimationExporter : COLLADASW::LibraryAnimations { const std::string axis_name); /* Output sources (matrix data) */ - std::string collada_source_from_values(BCMatrixSampleMap &samples, const std::string &anim_id); + std::string collada_source_from_values(BCMatrixSampleMap &samples, + const std::string &anim_id, + BC_global_rotation_type global_rotation_type, + Matrix &parentinv); /* Interpolation sources */ std::string collada_linear_interpolation_source(int tot, const std::string &anim_id); diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index be50b255f13..f974996191b 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -43,8 +43,6 @@ extern "C" { #include "ArmatureExporter.h" #include "SceneExporter.h" -#include "collada_utils.h" - // write bone nodes void ArmatureExporter::add_armature_bones(Object *ob_arm, ViewLayer *view_layer, @@ -62,10 +60,7 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, } for (Bone *bone = (Bone *)armature->bonebase.first; bone; bone = bone->next) { - // start from root bones - if (!bone->parent) { - add_bone_node(bone, ob_arm, se, child_objects); - } + add_bone_node(bone, ob_arm, se, child_objects); } if (!is_edited) { @@ -77,7 +72,7 @@ void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone) { - if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) { + if (bc_is_root_bone(bone, this->export_settings.get_deform_bones_only())) { std::string joint_id = translate_id(id_name(ob_arm) + "_" + bone->name); ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, joint_id)); } @@ -109,7 +104,7 @@ bool ArmatureExporter::add_instance_controller(Object *ob) } InstanceWriter::add_material_bindings( - ins.getBindMaterial(), ob, this->export_settings->active_uv_only); + ins.getBindMaterial(), ob, this->export_settings.get_active_uv_only()); ins.add(); return true; @@ -157,7 +152,7 @@ void ArmatureExporter::add_bone_node(Bone *bone, SceneExporter *se, std::vector<Object *> &child_objects) { - if (!(this->export_settings->deform_bones_only && bone->flag & BONE_NO_DEFORM)) { + if (can_export(bone)) { std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name); std::string node_name = std::string(bone->name); std::string node_sid = get_joint_sid(bone); @@ -169,8 +164,8 @@ void ArmatureExporter::add_bone_node(Bone *bone, node.setNodeName(node_name); node.setNodeSid(node_sid); - if (this->export_settings->use_blender_profile) { - if (bone->parent) { + if (this->export_settings.get_use_blender_profile()) { + if (!is_export_root(bone)) { if (bone->flag & BONE_CONNECTED) { node.addExtraTechniqueParameter("blender", "connect", true); } @@ -184,9 +179,19 @@ void ArmatureExporter::add_bone_node(Bone *bone, node.addExtraTechniqueParameter("blender", "roll", ebone->roll); } if (bc_is_leaf_bone(bone)) { - node.addExtraTechniqueParameter("blender", "tip_x", bone->arm_tail[0] - bone->arm_head[0]); - node.addExtraTechniqueParameter("blender", "tip_y", bone->arm_tail[1] - bone->arm_head[1]); - node.addExtraTechniqueParameter("blender", "tip_z", bone->arm_tail[2] - bone->arm_head[2]); + Vector head, tail; + const BCMatrix &global_transform = this->export_settings.get_global_transform(); + if (this->export_settings.get_apply_global_orientation()) { + bc_add_global_transform(head, bone->arm_head, global_transform); + bc_add_global_transform(tail, bone->arm_tail, global_transform); + } + else { + copy_v3_v3(head, bone->arm_head); + copy_v3_v3(tail, bone->arm_tail); + } + node.addExtraTechniqueParameter("blender", "tip_x", tail[0] - head[0]); + node.addExtraTechniqueParameter("blender", "tip_y", tail[1] - head[1]); + node.addExtraTechniqueParameter("blender", "tip_z", tail[2] - head[2]); } } @@ -195,12 +200,13 @@ void ArmatureExporter::add_bone_node(Bone *bone, add_bone_transform(ob_arm, bone, node); // Write nodes of childobjects, remove written objects from list - std::vector<Object *>::iterator i = child_objects.begin(); + std::vector<Object *>::iterator iter = child_objects.begin(); - while (i != child_objects.end()) { - if ((*i)->partype == PARBONE && STREQ((*i)->parsubstr, bone->name)) { + while (iter != child_objects.end()) { + Object *ob = *iter; + if (ob->partype == PARBONE && STREQ(ob->parsubstr, bone->name)) { float backup_parinv[4][4]; - copy_m4_m4(backup_parinv, (*i)->parentinv); + copy_m4_m4(backup_parinv, ob->parentinv); // crude, temporary change to parentinv // so transform gets exported correctly. @@ -208,28 +214,28 @@ void ArmatureExporter::add_bone_node(Bone *bone, // Add bone tail- translation... don't know why // bone parenting is against the tail of a bone // and not it's head, seems arbitrary. - (*i)->parentinv[3][1] += bone->length; + ob->parentinv[3][1] += bone->length; // OPEN_SIM_COMPATIBILITY // TODO: when such objects are animated as // single matrix the tweak must be applied // to the result. - if (export_settings->open_sim) { + if (export_settings.get_open_sim()) { // tweak objects parentinverse to match compatibility float temp[4][4]; copy_m4_m4(temp, bone->arm_mat); temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - mul_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv); + mul_m4_m4m4(ob->parentinv, temp, ob->parentinv); } - se->writeNodes(*i); - copy_m4_m4((*i)->parentinv, backup_parinv); - i = child_objects.erase(i); + se->writeNode(ob); + copy_m4_m4(ob->parentinv, backup_parinv); + iter = child_objects.erase(iter); } else - i++; + iter++; } for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { @@ -244,6 +250,18 @@ void ArmatureExporter::add_bone_node(Bone *bone, } } +bool ArmatureExporter::is_export_root(Bone *bone) +{ + Bone *entry = bone->parent; + while (entry) { + if (can_export(entry)) { + return false; + } + entry = entry->parent; + } + return can_export(bone); +} + void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node &node) { // bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name); @@ -260,49 +278,45 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW: bc_create_restpose_mat(this->export_settings, bone, bone_rest_mat, bone->arm_mat, true); - if (bone->parent) { - /* Get bone-space matrix from parent pose. */ -#if 0 - bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name); - float invpar[4][4]; - invert_m4_m4(invpar, parchan->pose_mat); - mul_m4_m4m4(mat, invpar, pchan->pose_mat); -#endif - float invpar[4][4]; + if (is_export_root(bone)) { + copy_m4_m4(mat, bone_rest_mat); + } + else { + Matrix parent_inverse; bc_create_restpose_mat( this->export_settings, bone->parent, parent_rest_mat, bone->parent->arm_mat, true); - invert_m4_m4(invpar, parent_rest_mat); - mul_m4_m4m4(mat, invpar, bone_rest_mat); - } - else { - copy_m4_m4(mat, bone_rest_mat); + invert_m4_m4(parent_inverse, parent_rest_mat); + mul_m4_m4m4(mat, parent_inverse, bone_rest_mat); } // OPEN_SIM_COMPATIBILITY - if (export_settings->open_sim) { + + if (export_settings.get_open_sim()) { // Remove rotations vs armature from transform // parent_rest_rot * mat * irest_rot - float temp[4][4]; - copy_m4_m4(temp, bone_rest_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - invert_m4(temp); + Matrix workmat; + copy_m4_m4(workmat, bone_rest_mat); - mul_m4_m4m4(mat, mat, temp); + workmat[3][0] = workmat[3][1] = workmat[3][2] = 0.0f; + invert_m4(workmat); - if (bone->parent) { - copy_m4_m4(temp, parent_rest_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + mul_m4_m4m4(mat, mat, workmat); - mul_m4_m4m4(mat, temp, mat); + if (!is_export_root(bone)) { + copy_m4_m4(workmat, parent_rest_mat); + workmat[3][0] = workmat[3][1] = workmat[3][2] = 0.0f; + + mul_m4_m4m4(mat, workmat, mat); } } } - if (this->export_settings->limit_precision) + if (this->export_settings.get_limit_precision()) { bc_sanitize_mat(mat, LIMITTED_PRECISION); + } - TransformWriter::add_node_transform(node, mat, NULL); + TransformWriter::add_joint_transform(node, mat, NULL, this->export_settings, has_restmat); } std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob) diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h index 6ef6007960e..da6d6f79ef5 100644 --- a/source/blender/collada/ArmatureExporter.h +++ b/source/blender/collada/ArmatureExporter.h @@ -56,7 +56,7 @@ class ArmatureExporter : public COLLADASW::LibraryControllers, // we make controller ids then? ArmatureExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, - const ExportSettings *export_settings) + BCExportSettings &export_settings) : COLLADASW::LibraryControllers(sw), blender_context(blender_context), export_settings(export_settings) @@ -72,7 +72,7 @@ class ArmatureExporter : public COLLADASW::LibraryControllers, private: BlenderContext &blender_context; - const ExportSettings *export_settings; + BCExportSettings &export_settings; #if 0 std::vector<Object *> written_armatures; @@ -91,6 +91,12 @@ class ArmatureExporter : public COLLADASW::LibraryControllers, SceneExporter *se, std::vector<Object *> &child_objects); + inline bool can_export(Bone *bone) + { + return !(export_settings.get_deform_bones_only() && bone->flag & BONE_NO_DEFORM); + } + + bool is_export_root(Bone *bone); void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node &node); std::string get_controller_id(Object *ob_arm, Object *ob); diff --git a/source/blender/collada/BCAnimationSampler.cpp b/source/blender/collada/BCAnimationSampler.cpp index ee574e2968b..1e6ff79f132 100644 --- a/source/blender/collada/BCAnimationSampler.cpp +++ b/source/blender/collada/BCAnimationSampler.cpp @@ -44,8 +44,8 @@ extern "C" { static std::string EMPTY_STRING; static BCAnimationCurveMap BCEmptyAnimationCurves; -BCAnimationSampler::BCAnimationSampler(BlenderContext &blender_context, BCObjectSet &object_set) - : blender_context(blender_context) +BCAnimationSampler::BCAnimationSampler(BCExportSettings &export_settings, BCObjectSet &object_set) + : export_settings(export_settings) { BCObjectSet::iterator it; for (it = object_set.begin(); it != object_set.end(); ++it) { @@ -65,6 +65,7 @@ BCAnimationSampler::~BCAnimationSampler() void BCAnimationSampler::add_object(Object *ob) { + BlenderContext blender_context = export_settings.get_blender_context(); BCAnimation *animation = new BCAnimation(blender_context.get_context(), ob); objects[ob] = animation; @@ -156,6 +157,10 @@ void BCAnimationSampler::update_animation_curves(BCAnimation &animation, BCSample &BCAnimationSampler::sample_object(Object *ob, int frame_index, bool for_opensim) { BCSample &ob_sample = sample_data.add(ob, frame_index); + // if (export_settings.get_apply_global_orientation()) { + // const BCMatrix &global_transform = export_settings.get_global_transform(); + // ob_sample.get_matrix(global_transform); + //} if (ob->type == OB_ARMATURE) { bPoseChannel *pchan; @@ -163,6 +168,7 @@ BCSample &BCAnimationSampler::sample_object(Object *ob, int frame_index, bool fo Bone *bone = pchan->bone; Matrix bmat; if (bc_bone_matrix_local_get(ob, bone, bmat, for_opensim)) { + ob_sample.add_bone_matrix(bone, bmat); } } @@ -170,12 +176,14 @@ BCSample &BCAnimationSampler::sample_object(Object *ob, int frame_index, bool fo return ob_sample; } -void BCAnimationSampler::sample_scene(int sampling_rate, - int keyframe_at_end, - bool for_opensim, - bool keep_keyframes, - BC_export_animation_type export_animation_type) +void BCAnimationSampler::sample_scene(BCExportSettings &export_settings, bool keyframe_at_end) { + BlenderContext blender_context = export_settings.get_blender_context(); + int sampling_rate = export_settings.get_sampling_rate(); + bool for_opensim = export_settings.get_open_sim(); + bool keep_keyframes = export_settings.get_keep_keyframes(); + BC_export_animation_type export_animation_type = export_settings.get_export_animation_type(); + Scene *scene = blender_context.get_scene(); BCFrameSet scene_sample_frames; get_sample_frames(scene_sample_frames, sampling_rate, keyframe_at_end, scene); diff --git a/source/blender/collada/BCAnimationSampler.h b/source/blender/collada/BCAnimationSampler.h index 9544c6be916..e8d2ab56ae7 100644 --- a/source/blender/collada/BCAnimationSampler.h +++ b/source/blender/collada/BCAnimationSampler.h @@ -147,7 +147,7 @@ class BCSampleFrameContainer { class BCAnimationSampler { private: - BlenderContext &blender_context; + BCExportSettings &export_settings; BCSampleFrameContainer sample_data; BCAnimationObjectMap objects; @@ -169,16 +169,12 @@ class BCAnimationSampler { BCAnimation &animation, float *ref, float *val, std::string data_path, int length); public: - BCAnimationSampler(BlenderContext &blender_context, BCObjectSet &animated_subset); + BCAnimationSampler(BCExportSettings &export_settings, BCObjectSet &animated_subset); ~BCAnimationSampler(); void add_object(Object *ob); - void sample_scene(int sampling_rate, - int keyframe_at_end, - bool for_opensim, - bool keep_keyframes, - BC_export_animation_type export_animation_type); + void sample_scene(BCExportSettings &export_settings, bool keyframe_at_end); BCAnimationCurveMap *get_curves(Object *ob); void get_object_frames(BCFrames &frames, Object *ob); diff --git a/source/blender/collada/BCSampleData.cpp b/source/blender/collada/BCSampleData.cpp index 868526928b0..88a7fd5993c 100644 --- a/source/blender/collada/BCSampleData.cpp +++ b/source/blender/collada/BCSampleData.cpp @@ -20,10 +20,6 @@ #include "BCSampleData.h" #include "collada_utils.h" -BCSample::BCSample(Object *ob) : obmat(ob) -{ -} - BCSample::~BCSample() { BCBoneMatrixMap::iterator it; @@ -43,6 +39,11 @@ void BCSample::add_bone_matrix(Bone *bone, Matrix &mat) bonemats[bone] = matrix; } +BCMatrix::BCMatrix(const BCMatrix &mat) +{ + set_transform(mat.matrix); +} + BCMatrix::BCMatrix(Matrix &mat) { set_transform(mat); @@ -53,11 +54,71 @@ BCMatrix::BCMatrix(Object *ob) set_transform(ob); } -void BCMatrix::set_transform(Matrix &mat) +BCMatrix::BCMatrix() { - copy_m4_m4(matrix, mat); - mat4_decompose(this->loc, this->q, this->size, mat); - quat_to_eul(this->rot, this->q); + unit(); +} + +BCMatrix::BCMatrix(BC_global_forward_axis global_forward_axis, BC_global_up_axis global_up_axis) +{ + float mrot[3][3]; + float mat[4][4]; + mat3_from_axis_conversion( + BC_DEFAULT_FORWARD, BC_DEFAULT_UP, global_forward_axis, global_up_axis, mrot); + + transpose_m3(mrot); // TODO: Verify that mat3_from_axis_conversion() returns a transposed matrix + copy_m4_m3(mat, mrot); + set_transform(mat); +} + +void BCMatrix::add_transform(const Matrix &mat, bool inverse) +{ + add_transform(this->matrix, mat, this->matrix, inverse); +} + +void BCMatrix::add_transform(const BCMatrix &mat, bool inverse) +{ + add_transform(this->matrix, mat.matrix, this->matrix, inverse); +} + +void BCMatrix::apply_transform(const BCMatrix &mat, bool inverse) +{ + apply_transform(this->matrix, mat.matrix, this->matrix, inverse); +} + +void BCMatrix::add_transform(Matrix &to, const Matrix &transform, const Matrix &from, bool inverse) +{ + if (inverse) { + Matrix globinv; + invert_m4_m4(globinv, transform); + add_transform(to, globinv, from, /*inverse=*/false); + } + else { + mul_m4_m4m4(to, transform, from); + } +} + +void BCMatrix::apply_transform(Matrix &to, + const Matrix &transform, + const Matrix &from, + bool inverse) +{ + Matrix globinv; + invert_m4_m4(globinv, transform); + if (inverse) { + add_transform(to, globinv, from, /*inverse=*/false); + } + else { + mul_m4_m4m4(to, transform, from); + mul_m4_m4m4(to, to, globinv); + } +} + +void BCMatrix::add_inverted_transform(Matrix &to, const Matrix &transform, const Matrix &from) +{ + Matrix workmat; + invert_m4_m4(workmat, transform); + mul_m4_m4m4(to, workmat, from); } void BCMatrix::set_transform(Object *ob) @@ -71,6 +132,13 @@ void BCMatrix::set_transform(Object *ob) quat_to_compatible_eul(this->rot, ob->rot, this->q); } +void BCMatrix::set_transform(Matrix &mat) +{ + copy_m4_m4(matrix, mat); + mat4_decompose(this->loc, this->q, this->size, mat); + quat_to_eul(this->rot, this->q); +} + const BCMatrix *BCSample::get_matrix(Bone *bone) const { BCBoneMatrixMap::const_iterator it = bonemats.find(bone); @@ -126,12 +194,28 @@ void BCMatrix::sanitize(Matrix &mat, int precision) void BCMatrix::unit() { - unit_m4(matrix); + unit_m4(this->matrix); + mat4_decompose(this->loc, this->q, this->size, this->matrix); + quat_to_eul(this->rot, this->q); } /* We need double here because the OpenCollada API needs it. * precision = -1 indicates to not limit the precision. */ -void BCMatrix::get_matrix(double (&mat)[4][4], const bool transposed, const int precision) const +void BCMatrix::get_matrix(DMatrix &mat, const bool transposed, const int precision) const +{ + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) { + float val = (transposed) ? matrix[j][i] : matrix[i][j]; + if (precision >= 0) + val = floor((val * pow(10, precision) + 0.5)) / pow(10, precision); + mat[i][j] = val; + } +} + +void BCMatrix::get_matrix(Matrix &mat, + const bool transposed, + const int precision, + const bool inverted) const { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) { @@ -140,6 +224,10 @@ void BCMatrix::get_matrix(double (&mat)[4][4], const bool transposed, const int val = floor((val * pow(10, precision) + 0.5)) / pow(10, precision); mat[i][j] = val; } + + if (inverted) { + invert_m4(mat); + } } const bool BCMatrix::in_range(const BCMatrix &other, float distance) const diff --git a/source/blender/collada/BCSampleData.h b/source/blender/collada/BCSampleData.h index 9cb56c95e0f..709bd3e59ef 100644 --- a/source/blender/collada/BCSampleData.h +++ b/source/blender/collada/BCSampleData.h @@ -24,6 +24,8 @@ #include <map> #include <algorithm> +#include "ExportSettings.h" + extern "C" { #include "BKE_object.h" #include "BLI_math_rotation.h" @@ -34,40 +36,6 @@ extern "C" { #include "DNA_camera_types.h" } -typedef float(Matrix)[4][4]; - -class BCMatrix { - - private: - mutable float matrix[4][4]; - mutable float size[3]; - mutable float rot[3]; - mutable float loc[3]; - mutable float q[4]; - - void unit(); - void copy(Matrix &r, Matrix &a); - void set_transform(Object *ob); - void set_transform(Matrix &mat); - - public: - float (&location() const)[3]; - float (&rotation() const)[3]; - float (&scale() const)[3]; - float (&quat() const)[4]; - - BCMatrix(Matrix &mat); - BCMatrix(Object *ob); - - void get_matrix(double (&mat)[4][4], - const bool transposed = false, - const int precision = -1) const; - - const bool in_range(const BCMatrix &other, float distance) const; - static void sanitize(Matrix &matrix, int precision); - static void transpose(Matrix &matrix); -}; - typedef std::map<Bone *, BCMatrix *> BCBoneMatrixMap; class BCSample { @@ -76,7 +44,10 @@ class BCSample { BCBoneMatrixMap bonemats; /* For Armature animation */ public: - BCSample(Object *ob); + BCSample(Object *ob) : obmat(ob) + { + } + ~BCSample(); void add_bone_matrix(Bone *bone, Matrix &mat); diff --git a/source/blender/collada/BlenderContext.cpp b/source/blender/collada/BlenderContext.cpp index 384f235e00c..709f84c3f77 100644 --- a/source/blender/collada/BlenderContext.cpp +++ b/source/blender/collada/BlenderContext.cpp @@ -18,9 +18,92 @@ * \ingroup collada */ +#include <vector> + #include "BlenderContext.h" #include "BKE_scene.h" +bool bc_is_base_node(LinkNode *export_set, Object *ob, ViewLayer *view_layer) +{ + Object *root = bc_get_highest_exported_ancestor_or_self(export_set, ob, view_layer); + return (root == ob); +} + +/** + * Returns the highest selected ancestor + * returns NULL if no ancestor is selected + * IMPORTANT: This function expects that all exported objects have set: + * ob->id.tag & LIB_TAG_DOIT + */ +Object *bc_get_highest_exported_ancestor_or_self(LinkNode *export_set, + Object *ob, + ViewLayer *view_layer) +{ + Object *ancestor = ob; + while (ob->parent) { + if (bc_is_in_Export_set(export_set, ob->parent, view_layer)) { + ancestor = ob->parent; + } + ob = ob->parent; + } + return ancestor; +} + +void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer) +{ + Base *base; + for (base = (Base *)view_layer->object_bases.first; base; base = base->next) { + Object *cob = base->object; + if (cob->parent == ob) { + switch (ob->type) { + case OB_MESH: + case OB_CAMERA: + case OB_LAMP: + case OB_EMPTY: + case OB_ARMATURE: + child_set.push_back(cob); + default: + break; + } + } + } +} + +bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer) +{ + bool to_export = (BLI_linklist_index(export_set, ob) != -1); + + if (!to_export) { + /* Mark this object as to_export even if it is not in the + export list, but it contains children to export */ + + std::vector<Object *> children; + bc_get_children(children, ob, view_layer); + for (int i = 0; i < children.size(); i++) { + if (bc_is_in_Export_set(export_set, children[i], view_layer)) { + to_export = true; + break; + } + } + } + return to_export; +} + +int bc_is_marked(Object *ob) +{ + return ob && (ob->id.tag & LIB_TAG_DOIT); +} + +void bc_remove_mark(Object *ob) +{ + ob->id.tag &= ~LIB_TAG_DOIT; +} + +void bc_set_mark(Object *ob) +{ + ob->id.tag |= LIB_TAG_DOIT; +} + BlenderContext::BlenderContext(bContext *C) { context = C; diff --git a/source/blender/collada/BlenderContext.h b/source/blender/collada/BlenderContext.h index f79f3a52507..c23a1b0f312 100644 --- a/source/blender/collada/BlenderContext.h +++ b/source/blender/collada/BlenderContext.h @@ -21,14 +21,105 @@ #ifndef __BLENDERCONTEXT_H__ #define __BLENDERCONTEXT_H__ +#ifdef __cplusplus + extern "C" { +#endif + #include "DNA_object_types.h" +#include "BLI_linklist.h" #include "BKE_context.h" #include "BKE_main.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +#include "DNA_layer_types.h" + +typedef float(Vector)[3]; +typedef float(Matrix)[4][4]; +typedef double(DMatrix)[4][4]; + +typedef enum BC_global_forward_axis { + BC_GLOBAL_FORWARD_X = 0, + BC_GLOBAL_FORWARD_Y = 1, + BC_GLOBAL_FORWARD_Z = 2, + BC_GLOBAL_FORWARD_MINUS_X = 3, + BC_GLOBAL_FORWARD_MINUS_Y = 4, + BC_GLOBAL_FORWARD_MINUS_Z = 5 +} BC_global_forward_axis; + +typedef enum BC_global_up_axis { + BC_GLOBAL_UP_X = 0, + BC_GLOBAL_UP_Y = 1, + BC_GLOBAL_UP_Z = 2, + BC_GLOBAL_UP_MINUS_X = 3, + BC_GLOBAL_UP_MINUS_Y = 4, + BC_GLOBAL_UP_MINUS_Z = 5 +} BC_global_up_axis; + +static const BC_global_forward_axis BC_DEFAULT_FORWARD = BC_GLOBAL_FORWARD_Y; +static const BC_global_up_axis BC_DEFAULT_UP = BC_GLOBAL_UP_Z; + +bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer); +bool bc_is_base_node(LinkNode *export_set, Object *ob, ViewLayer *view_layer); +Object *bc_get_highest_exported_ancestor_or_self(LinkNode *export_set, + Object *ob, + ViewLayer *view_layer); +int bc_is_marked(Object *ob); +void bc_remove_mark(Object *ob); +void bc_set_mark(Object *ob); + +#ifdef __cplusplus } +class BCMatrix { + + private: + mutable float matrix[4][4]; + mutable float size[3]; + mutable float rot[3]; + mutable float loc[3]; + mutable float q[4]; + + void unit(); + void copy(Matrix &r, Matrix &a); + + public: + float (&location() const)[3]; + float (&rotation() const)[3]; + float (&scale() const)[3]; + float (&quat() const)[4]; + + BCMatrix(BC_global_forward_axis global_forward_axis, BC_global_up_axis global_up_axis); + BCMatrix(const BCMatrix &mat); + BCMatrix(Matrix &mat); + BCMatrix(Object *ob); + BCMatrix(); + + void get_matrix(DMatrix &matrix, const bool transposed = false, const int precision = -1) const; + void get_matrix(Matrix &matrix, + const bool transposed = false, + const int precision = -1, + const bool inverted = false) const; + void set_transform(Object *ob); + void set_transform(Matrix &mat); + void add_transform(Matrix &to, + const Matrix &transform, + const Matrix &from, + const bool inverted = false); + void apply_transform(Matrix &to, + const Matrix &transform, + const Matrix &from, + const bool inverted = false); + void add_inverted_transform(Matrix &to, const Matrix &transform, const Matrix &from); + void add_transform(const Matrix &matrix, const bool inverted = false); + void add_transform(const BCMatrix &matrix, const bool inverted = false); + void apply_transform(const BCMatrix &matrix, const bool inverted = false); + + const bool in_range(const BCMatrix &other, float distance) const; + static void sanitize(Matrix &matrix, int precision); + static void transpose(Matrix &matrix); +}; + class BlenderContext { private: bContext *context; @@ -47,5 +138,6 @@ class BlenderContext { ViewLayer *get_view_layer(); Main *get_main(); }; +#endif #endif diff --git a/source/blender/collada/CameraExporter.cpp b/source/blender/collada/CameraExporter.cpp index a46ee74be91..74862c44270 100644 --- a/source/blender/collada/CameraExporter.cpp +++ b/source/blender/collada/CameraExporter.cpp @@ -29,8 +29,7 @@ extern "C" { #include "collada_internal.h" -CamerasExporter::CamerasExporter(COLLADASW::StreamWriter *sw, - const ExportSettings *export_settings) +CamerasExporter::CamerasExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings) : COLLADASW::LibraryCameras(sw), export_settings(export_settings) { } @@ -52,7 +51,7 @@ void CamerasExporter::exportCameras(Scene *sce) { openLibrary(); - forEachCameraObjectInExportSet(sce, *this, this->export_settings->export_set); + forEachCameraObjectInExportSet(sce, *this, this->export_settings.get_export_set()); closeLibrary(); } diff --git a/source/blender/collada/CameraExporter.h b/source/blender/collada/CameraExporter.h index 0a90fc017e8..04bcc4a5dad 100644 --- a/source/blender/collada/CameraExporter.h +++ b/source/blender/collada/CameraExporter.h @@ -34,13 +34,13 @@ extern "C" { class CamerasExporter : COLLADASW::LibraryCameras { public: - CamerasExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); + CamerasExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings); void exportCameras(Scene *sce); void operator()(Object *ob, Scene *sce); private: bool exportBlenderProfile(COLLADASW::Camera &cla, Camera *cam); - const ExportSettings *export_settings; + BCExportSettings &export_settings; }; #endif diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index c79a4e1a1f7..cb15a3a7a7c 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -57,7 +57,7 @@ void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone) { - if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) { + if (bc_is_root_bone(bone, this->export_settings.get_deform_bones_only())) { std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name); ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, node_id)); } @@ -89,7 +89,7 @@ bool ControllerExporter::add_instance_controller(Object *ob) } InstanceWriter::add_material_bindings( - ins.getBindMaterial(), ob, this->export_settings->active_uv_only); + ins.getBindMaterial(), ob, this->export_settings.get_active_uv_only()); ins.add(); return true; @@ -102,7 +102,7 @@ void ControllerExporter::export_controllers() GeometryFunctor gf; gf.forEachMeshObjectInExportSet<ControllerExporter>( - sce, *this, this->export_settings->export_set); + sce, *this, this->export_settings.get_export_set()); closeLibrary(); } @@ -115,7 +115,7 @@ void ControllerExporter::operator()(Object *ob) if (ob_arm) { export_skin_controller(ob, ob_arm); } - if (key && this->export_settings->include_shapekeys) { + if (key && this->export_settings.get_include_shapekeys()) { export_morph_controller(ob, key); } } @@ -189,7 +189,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) } MDeformWeight; #endif - bool use_instantiation = this->export_settings->use_object_instantiation; + bool use_instantiation = this->export_settings.get_use_object_instantiation(); Mesh *me; if (((Mesh *)ob->data)->dvert == NULL) { @@ -198,9 +198,9 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) me = bc_get_mesh_copy(blender_context, ob, - this->export_settings->export_mesh_type, - this->export_settings->apply_modifiers, - this->export_settings->triangulate); + this->export_settings.get_export_mesh_type(), + this->export_settings.get_apply_modifiers(), + this->export_settings.get_triangulate()); std::string controller_name = id_name(ob_arm); std::string controller_id = get_controller_id(ob_arm, ob); @@ -297,14 +297,14 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) void ControllerExporter::export_morph_controller(Object *ob, Key *key) { - bool use_instantiation = this->export_settings->use_object_instantiation; + bool use_instantiation = this->export_settings.get_use_object_instantiation(); Mesh *me; me = bc_get_mesh_copy(blender_context, ob, - this->export_settings->export_mesh_type, - this->export_settings->apply_modifiers, - this->export_settings->triangulate); + this->export_settings.get_export_mesh_type(), + this->export_settings.get_apply_modifiers(), + this->export_settings.get_triangulate()); std::string controller_name = id_name(ob) + "-morph"; std::string controller_id = get_controller_id(key, ob); @@ -431,9 +431,16 @@ void ControllerExporter::add_bind_shape_mat(Object *ob) float f_obmat[4][4]; BKE_object_matrix_local_get(ob, f_obmat); + if (export_settings.get_apply_global_orientation()) { + // do nothing, rotation is going to be applied to the Data + } + else { + bc_add_global_transform(f_obmat, export_settings.get_global_transform()); + } + // UnitConverter::mat4_to_dae_double(bind_mat, ob->obmat); UnitConverter::mat4_to_dae_double(bind_mat, f_obmat); - if (this->export_settings->limit_precision) + if (this->export_settings.get_limit_precision()) bc_sanitize_mat(bind_mat, LIMITTED_PRECISION); addBindShapeTransform(bind_mat); @@ -532,8 +539,7 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, this->export_settings, pchan->bone, bind_mat, pchan->bone->arm_mat, true); /* SL/OPEN_SIM COMPATIBILITY */ - if (export_settings->open_sim) { - + if (export_settings.get_open_sim()) { float loc[3]; float rot[3] = {0, 0, 0}; float scale[3]; @@ -547,9 +553,15 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, /* make world-space matrix (bind_mat is armature-space) */ mul_m4_m4m4(world, ob_arm->obmat, bind_mat); + if (!has_bindmat) { + if (export_settings.get_apply_global_orientation()) { + bc_apply_global_transform(world, export_settings.get_global_transform()); + } + } + invert_m4_m4(mat, world); UnitConverter::mat4_to_dae(inv_bind_mat, mat); - if (this->export_settings->limit_precision) + if (this->export_settings.get_limit_precision()) bc_sanitize_mat(inv_bind_mat, LIMITTED_PRECISION); source.appendValues(inv_bind_mat); } diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h index 38d85cb7ebc..200f8431f62 100644 --- a/source/blender/collada/ControllerExporter.h +++ b/source/blender/collada/ControllerExporter.h @@ -53,13 +53,17 @@ class SceneExporter; class ControllerExporter : public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter { + private: + BlenderContext &blender_context; + BCExportSettings export_settings; + public: // XXX exporter writes wrong data for shared armatures. A separate // controller should be written for each armature-mesh binding how do // we make controller ids then? ControllerExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, - const ExportSettings *export_settings) + BCExportSettings &export_settings) : COLLADASW::LibraryControllers(sw), blender_context(blender_context), export_settings(export_settings) @@ -75,9 +79,6 @@ class ControllerExporter : public COLLADASW::LibraryControllers, void operator()(Object *ob); private: - BlenderContext &blender_context; - const ExportSettings *export_settings; - #if 0 std::vector<Object *> written_armatures; diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index c8202eb3cf6..f9232851fbb 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -146,9 +146,9 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type) return data->layers[layer_index].name; } -DocumentExporter::DocumentExporter(BlenderContext &blender_context, - const ExportSettings *export_settings) - : blender_context(blender_context), export_settings(export_settings) +DocumentExporter::DocumentExporter(BlenderContext &blender_context, ExportSettings *exportSettings) + : blender_context(blender_context), + export_settings(BCExportSettings(exportSettings, blender_context)) { } @@ -262,7 +262,7 @@ int DocumentExporter::exportCurrentScene() asset.getContributor().mAuthoringTool = version_buf; asset.add(); - LinkNode *export_set = this->export_settings->export_set; + LinkNode *export_set = this->export_settings.get_export_set(); // <library_cameras> if (bc_has_object_type(export_set, OB_CAMERA)) { CamerasExporter ce(writer, this->export_settings); @@ -296,7 +296,8 @@ int DocumentExporter::exportCurrentScene() // <library_controllers> ArmatureExporter arm_exporter(blender_context, writer, this->export_settings); ControllerExporter controller_exporter(blender_context, writer, this->export_settings); - if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings->include_shapekeys) { + if (bc_has_object_type(export_set, OB_ARMATURE) || + this->export_settings.get_include_shapekeys()) { controller_exporter.export_controllers(); } @@ -304,9 +305,9 @@ int DocumentExporter::exportCurrentScene() SceneExporter se(blender_context, writer, &arm_exporter, this->export_settings); - if (this->export_settings->include_animations) { + if (this->export_settings.get_include_animations()) { // <library_animations> - AnimationExporter ae(blender_context, writer, this->export_settings); + AnimationExporter ae(writer, this->export_settings); ae.exportAnimations(); } @@ -322,10 +323,10 @@ int DocumentExporter::exportCurrentScene() delete writer; // Finally move the created document into place - fprintf(stdout, "Collada export to: %s\n", this->export_settings->filepath); - int status = BLI_rename(native_filename.c_str(), this->export_settings->filepath); + fprintf(stdout, "Collada export to: %s\n", this->export_settings.get_filepath()); + int status = BLI_rename(native_filename.c_str(), this->export_settings.get_filepath()); if (status != 0) { - status = BLI_copy(native_filename.c_str(), this->export_settings->filepath); + status = BLI_copy(native_filename.c_str(), this->export_settings.get_filepath()); BLI_delete(native_filename.c_str(), false, false); } return status; diff --git a/source/blender/collada/DocumentExporter.h b/source/blender/collada/DocumentExporter.h index a5608d13a71..70722ae601e 100644 --- a/source/blender/collada/DocumentExporter.h +++ b/source/blender/collada/DocumentExporter.h @@ -31,13 +31,13 @@ extern "C" { class DocumentExporter { public: - DocumentExporter(BlenderContext &blender_context, const ExportSettings *export_settings); + DocumentExporter(BlenderContext &blender_context, ExportSettings *export_settings); int exportCurrentScene(); void exportScenes(const char *filename); private: BlenderContext &blender_context; - const ExportSettings *export_settings; + BCExportSettings export_settings; KeyImageMap key_image_map; }; diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 3aceebe0422..60813fb951c 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -1125,7 +1125,6 @@ bool DocumentImporter::writeAnimation(const COLLADAFW::Animation *anim) if (mImportStage == Fetching_Controller_data) return true; - /* return true; */ return anim_importer.write_animation(anim); } diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index a6e75ba41a9..61603226dfd 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -53,7 +53,7 @@ static std::string getActiveUVLayerName(Object *ob) } EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, - const ExportSettings *export_settings, + BCExportSettings &export_settings, KeyImageMap &key_image_map) : COLLADASW::LibraryEffects(sw), export_settings(export_settings), key_image_map(key_image_map) { @@ -84,7 +84,8 @@ void EffectsExporter::exportEffects(bContext *C, Scene *sce) this->scene = sce; openLibrary(); MaterialFunctor mf; - mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set); + mf.forEachMaterialInExportSet<EffectsExporter>( + sce, *this, this->export_settings.get_export_set()); closeLibrary(); } diff --git a/source/blender/collada/EffectExporter.h b/source/blender/collada/EffectExporter.h index 25df2d7eb89..75511800081 100644 --- a/source/blender/collada/EffectExporter.h +++ b/source/blender/collada/EffectExporter.h @@ -40,7 +40,7 @@ class EffectsExporter : COLLADASW::LibraryEffects { public: EffectsExporter(COLLADASW::StreamWriter *sw, - const ExportSettings *export_settings, + BCExportSettings &export_settings, KeyImageMap &key_image_map); void exportEffects(bContext *C, Scene *sce); @@ -73,7 +73,7 @@ class EffectsExporter : COLLADASW::LibraryEffects { bool hasEffects(Scene *sce); - const ExportSettings *export_settings; + BCExportSettings &export_settings; KeyImageMap &key_image_map; Scene *scene; bContext *mContext; diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index a362b72be00..36f3ea40da9 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -22,10 +22,13 @@ #define __EXPORTSETTINGS_H__ #ifdef __cplusplus +# include <vector> + extern "C" { #endif #include "BLI_linklist.h" +#include "BlenderContext.h" typedef enum BC_export_mesh_type { BC_MESH_TYPE_VIEW, @@ -34,7 +37,7 @@ typedef enum BC_export_mesh_type { typedef enum BC_export_transformation_type { BC_TRANSFORMATION_TYPE_MATRIX, - BC_TRANSFORMATION_TYPE_TRANSROTLOC, + BC_TRANSFORMATION_TYPE_DECOMPOSED, } BC_export_transformation_type; typedef enum BC_export_animation_type { @@ -52,6 +55,10 @@ typedef enum BC_ui_export_section { typedef struct ExportSettings { bool apply_modifiers; + BC_global_forward_axis global_forward; + BC_global_up_axis global_up; + bool apply_global_orientation; + BC_export_mesh_type export_mesh_type; bool selected; @@ -74,7 +81,8 @@ typedef struct ExportSettings { bool use_object_instantiation; bool use_blender_profile; bool sort_by_name; - BC_export_transformation_type export_transformation_type; + BC_export_transformation_type object_transformation_type; + BC_export_transformation_type animation_transformation_type; bool open_sim; bool limit_precision; @@ -86,6 +94,201 @@ typedef struct ExportSettings { #ifdef __cplusplus } + +void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer); + +class BCExportSettings { + + private: + const ExportSettings &export_settings; + BlenderContext &blender_context; + const BCMatrix global_transform; + + public: + BCExportSettings(ExportSettings *exportSettings, BlenderContext &blenderContext) + : export_settings(*exportSettings), + blender_context(blenderContext), + global_transform(BCMatrix(exportSettings->global_forward, exportSettings->global_up)) + + { + } + + const BCMatrix &get_global_transform() + { + return global_transform; + } + + bool get_apply_modifiers() + { + return export_settings.apply_modifiers; + } + + BC_global_forward_axis get_global_forward() + { + return export_settings.global_forward; + } + + BC_global_up_axis get_global_up() + { + return export_settings.global_up; + } + + bool get_apply_global_orientation() + { + return export_settings.apply_global_orientation; + } + + BC_export_mesh_type get_export_mesh_type() + { + return export_settings.export_mesh_type; + } + + bool get_selected() + { + return export_settings.selected; + } + + bool get_include_children() + { + return export_settings.include_children; + } + + bool get_include_armatures() + { + return export_settings.include_armatures; + } + + bool get_include_shapekeys() + { + return export_settings.include_shapekeys; + } + + bool get_deform_bones_only() + { + return export_settings.deform_bones_only; + } + + bool get_include_animations() + { + return export_settings.include_animations; + } + + bool get_include_all_actions() + { + return export_settings.include_all_actions; + } + + int get_sampling_rate() + { + return export_settings.sampling_rate; + } + + bool get_keep_smooth_curves() + { + return export_settings.keep_smooth_curves; + } + + bool get_keep_keyframes() + { + return export_settings.keep_keyframes; + } + + bool get_keep_flat_curves() + { + return export_settings.keep_flat_curves; + } + + bool get_active_uv_only() + { + return export_settings.active_uv_only; + } + + BC_export_animation_type get_export_animation_type() + { + return export_settings.export_animation_type; + } + + bool get_use_texture_copies() + { + return export_settings.use_texture_copies; + } + + bool get_triangulate() + { + return export_settings.triangulate; + } + + bool get_use_object_instantiation() + { + return export_settings.use_object_instantiation; + } + + bool get_use_blender_profile() + { + return export_settings.use_blender_profile; + } + + bool get_sort_by_name() + { + return export_settings.sort_by_name; + } + + BC_export_transformation_type get_object_transformation_type() + { + return export_settings.object_transformation_type; + } + + BC_export_transformation_type get_animation_transformation_type() + { + return export_settings.animation_transformation_type; + } + + bool get_open_sim() + { + return export_settings.open_sim; + } + + bool get_limit_precision() + { + return export_settings.limit_precision; + } + + bool get_keep_bind_info() + { + return export_settings.keep_bind_info; + } + + char *get_filepath() + { + return export_settings.filepath; + } + + LinkNode *get_export_set() + { + return export_settings.export_set; + } + + BlenderContext &get_blender_context() + { + return blender_context; + } + + Scene *get_scene() + { + return blender_context.get_scene(); + } + + ViewLayer *get_view_layer() + { + return blender_context.get_view_layer(); + } + + bool is_export_root(Object *ob) + { + return bc_is_base_node(get_export_set(), ob, get_view_layer()); + } +}; + #endif #endif diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index bda6fec70a8..5125a9a0562 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -48,19 +48,20 @@ void GeometryExporter::exportGeom() openLibrary(); GeometryFunctor gf; - gf.forEachMeshObjectInExportSet<GeometryExporter>(sce, *this, this->export_settings->export_set); + gf.forEachMeshObjectInExportSet<GeometryExporter>( + sce, *this, this->export_settings.get_export_set()); closeLibrary(); } void GeometryExporter::operator()(Object *ob) { - bool use_instantiation = this->export_settings->use_object_instantiation; + bool use_instantiation = this->export_settings.get_use_object_instantiation(); Mesh *me = bc_get_mesh_copy(blender_context, ob, - this->export_settings->export_mesh_type, - this->export_settings->apply_modifiers, - this->export_settings->triangulate); + this->export_settings.get_export_mesh_type(), + this->export_settings.get_apply_modifiers(), + this->export_settings.get_triangulate()); std::string geom_id = get_geometry_id(ob, use_instantiation); std::vector<Normal> nor; @@ -128,7 +129,7 @@ void GeometryExporter::operator()(Object *ob) closeGeometry(); - if (this->export_settings->include_shapekeys) { + if (this->export_settings.get_include_shapekeys()) { Key *key = BKE_key_from_object(ob); if (key) { KeyBlock *kb = (KeyBlock *)key->block.first; @@ -380,14 +381,14 @@ void GeometryExporter::create_mesh_primitive_list(short material_index, int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV); for (int i = 0; i < num_layers; i++) { int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, i); - if (!this->export_settings->active_uv_only || layer_index == active_uv_index) { + if (!this->export_settings.get_active_uv_only() || layer_index == active_uv_index) { // char *name = CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, i); COLLADASW::Input texcoord_input( COLLADASW::InputSemantic::TEXCOORD, - makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)), + makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings.get_active_uv_only())), 2, // this is only until we have optimized UV sets - (this->export_settings->active_uv_only) ? 0 : layer_index - 1 /* set (0,1,2,...) */ + (this->export_settings.get_active_uv_only()) ? 0 : layer_index - 1 /* set (0,1,2,...) */ ); til.push_back(texcoord_input); } @@ -466,7 +467,14 @@ void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me) /* appends data to <float_array> */ int i = 0; for (i = 0; i < totverts; i++) { - source.appendValues(verts[i].co[0], verts[i].co[1], verts[i].co[2]); + Vector co; + if (export_settings.get_apply_global_orientation()) { + bc_add_global_transform(co, verts[i].co, export_settings.get_global_transform()); + } + else { + copy_v3_v3(co, verts[i].co); + } + source.appendValues(co[0], co[1], co[2]); } source.finish(); @@ -547,12 +555,12 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me) int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV); for (int a = 0; a < num_layers; a++) { int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, a); - if (!this->export_settings->active_uv_only || layer_index == active_uv_index) { + if (!this->export_settings.get_active_uv_only() || layer_index == active_uv_index) { MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a); COLLADASW::FloatSourceF source(mSW); std::string layer_id = makeTexcoordSourceId( - geom_id, a, this->export_settings->active_uv_only); + geom_id, a, this->export_settings.get_active_uv_only()); source.setId(layer_id); source.setArrayId(layer_id + ARRAY_ID_SUFFIX); @@ -606,7 +614,12 @@ void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::v std::vector<Normal>::iterator it; for (it = nor.begin(); it != nor.end(); it++) { Normal &n = *it; - source.appendValues(n.x, n.y, n.z); + + Vector no{n.x, n.y, n.z}; + if (export_settings.get_apply_global_orientation()) { + bc_add_global_transform(no, export_settings.get_global_transform()); + } + source.appendValues(no[0], no[1], no[2]); } source.finish(); diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h index 976059b0925..7262784db82 100644 --- a/source/blender/collada/GeometryExporter.h +++ b/source/blender/collada/GeometryExporter.h @@ -41,8 +41,6 @@ struct Depsgraph; -extern Object *bc_get_highest_selected_ancestor_or_self(Object *ob); - class Normal { public: float x; @@ -66,7 +64,7 @@ class GeometryExporter : COLLADASW::LibraryGeometries { /* TODO: optimize UV sets by making indexed list with duplicates removed */ GeometryExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, - const ExportSettings *export_settings) + BCExportSettings &export_settings) : COLLADASW::LibraryGeometries(sw), blender_context(blender_context), export_settings(export_settings) @@ -122,7 +120,7 @@ class GeometryExporter : COLLADASW::LibraryGeometries { private: std::set<std::string> exportedGeometry; BlenderContext &blender_context; - const ExportSettings *export_settings; + BCExportSettings &export_settings; Mesh *get_mesh(Scene *sce, Object *ob, int apply_modifiers); }; diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index b606799efde..71201c8a55c 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -43,7 +43,7 @@ extern "C" { #include "MaterialExporter.h" ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, - const ExportSettings *export_settings, + BCExportSettings &export_settings, KeyImageMap &key_image_map) : COLLADASW::LibraryImages(sw), export_settings(export_settings), key_image_map(key_image_map) { @@ -76,7 +76,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) char export_file[FILE_MAX]; /* Destination folder for exported assets */ - BLI_split_dir_part(this->export_settings->filepath, export_dir, sizeof(export_dir)); + BLI_split_dir_part(this->export_settings.get_filepath(), export_dir, sizeof(export_dir)); if (is_generated || is_dirty || use_copies || is_packed) { @@ -152,7 +152,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) void ImagesExporter::exportImages(Scene *sce) { - bool use_texture_copies = this->export_settings->use_texture_copies; + bool use_texture_copies = this->export_settings.get_use_texture_copies(); openLibrary(); KeyImageMap::iterator iter; diff --git a/source/blender/collada/ImageExporter.h b/source/blender/collada/ImageExporter.h index ac0c1d5c976..b72d2709382 100644 --- a/source/blender/collada/ImageExporter.h +++ b/source/blender/collada/ImageExporter.h @@ -38,12 +38,12 @@ class ImagesExporter : COLLADASW::LibraryImages { public: ImagesExporter(COLLADASW::StreamWriter *sw, - const ExportSettings *export_settings, + BCExportSettings &export_settings, KeyImageMap &key_image_map); void exportImages(Scene *sce); private: - const ExportSettings *export_settings; + BCExportSettings &export_settings; KeyImageMap &key_image_map; void export_UV_Image(Image *image, bool use_texture_copies); }; diff --git a/source/blender/collada/LightExporter.cpp b/source/blender/collada/LightExporter.cpp index 39721b2eb3c..463981ceefa 100644 --- a/source/blender/collada/LightExporter.cpp +++ b/source/blender/collada/LightExporter.cpp @@ -41,7 +41,7 @@ void forEachLightObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) } } -LightsExporter::LightsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) +LightsExporter::LightsExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings) : COLLADASW::LibraryLights(sw), export_settings(export_settings) { } @@ -50,7 +50,7 @@ void LightsExporter::exportLights(Scene *sce) { openLibrary(); - forEachLightObjectInExportSet(sce, *this, this->export_settings->export_set); + forEachLightObjectInExportSet(sce, *this, this->export_settings.get_export_set()); closeLibrary(); } diff --git a/source/blender/collada/LightExporter.h b/source/blender/collada/LightExporter.h index fc468f1f4a3..045ccfe1ce8 100644 --- a/source/blender/collada/LightExporter.h +++ b/source/blender/collada/LightExporter.h @@ -32,13 +32,13 @@ class LightsExporter : COLLADASW::LibraryLights { public: - LightsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); + LightsExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings); void exportLights(Scene *sce); void operator()(Object *ob); private: bool exportBlenderProfile(COLLADASW::Light &cla, Light *la); - const ExportSettings *export_settings; + BCExportSettings &export_settings; }; #endif diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp index e071712b20d..8bf7a220c4a 100644 --- a/source/blender/collada/MaterialExporter.cpp +++ b/source/blender/collada/MaterialExporter.cpp @@ -23,7 +23,7 @@ #include "collada_internal.h" MaterialsExporter::MaterialsExporter(COLLADASW::StreamWriter *sw, - const ExportSettings *export_settings) + BCExportSettings &export_settings) : COLLADASW::LibraryMaterials(sw), export_settings(export_settings) { /* pass */ @@ -36,7 +36,7 @@ void MaterialsExporter::exportMaterials(Scene *sce) MaterialFunctor mf; mf.forEachMaterialInExportSet<MaterialsExporter>( - sce, *this, this->export_settings->export_set); + sce, *this, this->export_settings.get_export_set()); closeLibrary(); } @@ -45,7 +45,7 @@ void MaterialsExporter::exportMaterials(Scene *sce) bool MaterialsExporter::hasMaterials(Scene *sce) { LinkNode *node; - for (node = this->export_settings->export_set; node; node = node->next) { + for (node = this->export_settings.get_export_set(); node; node = node->next) { Object *ob = (Object *)node->link; int a; for (a = 0; a < ob->totcol; a++) { diff --git a/source/blender/collada/MaterialExporter.h b/source/blender/collada/MaterialExporter.h index d47a001596d..027fba1f8ef 100644 --- a/source/blender/collada/MaterialExporter.h +++ b/source/blender/collada/MaterialExporter.h @@ -41,13 +41,13 @@ extern "C" { class MaterialsExporter : COLLADASW::LibraryMaterials { public: - MaterialsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); + MaterialsExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings); void exportMaterials(Scene *sce); void operator()(Material *ma, Object *ob); private: bool hasMaterials(Scene *sce); - const ExportSettings *export_settings; + BCExportSettings &export_settings; }; // used in forEachMaterialInScene diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index 8017790572f..7bf6a145886 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -23,10 +23,12 @@ extern "C" { #include "BKE_collection.h" #include "BKE_object.h" #include "BLI_listbase.h" +#include "BKE_library.h" } #include "SceneExporter.h" #include "collada_utils.h" +#include "BCSampleData.h" void SceneExporter::exportScene() { @@ -43,18 +45,18 @@ void SceneExporter::exportScene() void SceneExporter::exportHierarchy() { LinkNode *node; - std::vector<Object *> base_objects; + ColladaBaseNodes base_objects; /* Ensure all objects in the export_set are marked */ - for (node = this->export_settings->export_set; node; node = node->next) { + for (node = this->export_settings.get_export_set(); node; node = node->next) { Object *ob = (Object *)node->link; ob->id.tag |= LIB_TAG_DOIT; } /* Now find all exportable base objects (highest in export hierarchy) */ - for (node = this->export_settings->export_set; node; node = node->next) { + for (node = this->export_settings.get_export_set(); node; node = node->next) { Object *ob = (Object *)node->link; - if (bc_is_base_node(this->export_settings->export_set, ob)) { + if (this->export_settings.is_export_root(ob)) { switch (ob->type) { case OB_MESH: case OB_CAMERA: @@ -62,7 +64,7 @@ void SceneExporter::exportHierarchy() case OB_EMPTY: case OB_GPENCIL: case OB_ARMATURE: - base_objects.push_back(ob); + base_objects.add(ob); break; } } @@ -70,10 +72,10 @@ void SceneExporter::exportHierarchy() /* And now export the base objects: */ for (int index = 0; index < base_objects.size(); index++) { - Object *ob = base_objects[index]; + Object *ob = base_objects.get(index); + writeNode(ob); if (bc_is_marked(ob)) { bc_remove_mark(ob); - writeNodes(ob); } } } @@ -88,30 +90,31 @@ void SceneExporter::writeNodeList(std::vector<Object *> &child_objects, Object * * the hidden elements are exported as well. */ for (int i = 0; i < child_objects.size(); ++i) { Object *child = child_objects[i]; + writeNode(child); if (bc_is_marked(child)) { bc_remove_mark(child); - writeNodes(child); } } } -void SceneExporter::writeNodes(Object *ob) +void SceneExporter::writeNode(Object *ob) { ViewLayer *view_layer = blender_context.get_view_layer(); std::vector<Object *> child_objects; bc_get_children(child_objects, ob, view_layer); - bool can_export = bc_is_in_Export_set(this->export_settings->export_set, ob, view_layer); + bool can_export = bc_is_in_Export_set(this->export_settings.get_export_set(), ob, view_layer); /* Add associated armature first if available */ bool armature_exported = false; Object *ob_arm = bc_get_assigned_armature(ob); if (ob_arm != NULL) { - armature_exported = bc_is_in_Export_set(this->export_settings->export_set, ob_arm, view_layer); + armature_exported = bc_is_in_Export_set( + this->export_settings.get_export_set(), ob_arm, view_layer); if (armature_exported && bc_is_marked(ob_arm)) { + writeNode(ob_arm); bc_remove_mark(ob_arm); - writeNodes(ob_arm); armature_exported = true; } } @@ -123,16 +126,12 @@ void SceneExporter::writeNodes(Object *ob) colladaNode.setType(COLLADASW::Node::NODE); colladaNode.start(); - if (ob->type == OB_MESH && armature_exported) { /* for skinned mesh we write obmat in <bind_shape_matrix> */ - TransformWriter::add_node_transform_identity(colladaNode); + TransformWriter::add_node_transform_identity(colladaNode, this->export_settings); } else { - TransformWriter::add_node_transform_ob(colladaNode, - ob, - this->export_settings->export_transformation_type, - this->export_settings->limit_precision); + TransformWriter::add_node_transform_ob(colladaNode, ob, this->export_settings); } /* <instance_geometry> */ @@ -143,12 +142,12 @@ void SceneExporter::writeNodes(Object *ob) } if (!instance_controller_created) { COLLADASW::InstanceGeometry instGeom(mSW); - instGeom.setUrl( - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, - get_geometry_id(ob, this->export_settings->use_object_instantiation))); + instGeom.setUrl(COLLADASW::URI( + COLLADABU::Utils::EMPTY_STRING, + get_geometry_id(ob, this->export_settings.get_use_object_instantiation()))); instGeom.setName(encode_xml(id_name(ob))); InstanceWriter::add_material_bindings( - instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only); + instGeom.getBindMaterial(), ob, this->export_settings.get_active_uv_only()); instGeom.add(); } } @@ -232,7 +231,11 @@ void SceneExporter::writeNodes(Object *ob) } } } + bc_remove_mark(ob); writeNodeList(child_objects, ob); colladaNode.end(); } + else { + writeNodeList(child_objects, ob); + } } diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h index dc0a0c3e2ad..a61d045ad5d 100644 --- a/source/blender/collada/SceneExporter.h +++ b/source/blender/collada/SceneExporter.h @@ -82,9 +82,10 @@ extern "C" { #include "COLLADASWBaseInputElement.h" #include "ArmatureExporter.h" - #include "ExportSettings.h" +extern void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer); + class SceneExporter : COLLADASW::LibraryVisualScenes, protected TransformWriter, protected InstanceWriter { @@ -92,7 +93,7 @@ class SceneExporter : COLLADASW::LibraryVisualScenes, SceneExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, ArmatureExporter *arm, - const ExportSettings *export_settings) + BCExportSettings &export_settings) : COLLADASW::LibraryVisualScenes(sw), blender_context(blender_context), arm_exporter(arm), @@ -106,11 +107,11 @@ class SceneExporter : COLLADASW::LibraryVisualScenes, BlenderContext &blender_context; friend class ArmatureExporter; ArmatureExporter *arm_exporter; - const ExportSettings *export_settings; + BCExportSettings &export_settings; void exportHierarchy(); void writeNodeList(std::vector<Object *> &child_objects, Object *parent); - void writeNodes(Object *ob); + void writeNode(Object *ob); }; #endif diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp index 2ab9105976e..560ce8a359f 100644 --- a/source/blender/collada/TransformWriter.cpp +++ b/source/blender/collada/TransformWriter.cpp @@ -25,12 +25,12 @@ #include "TransformWriter.h" -void TransformWriter::add_node_transform(COLLADASW::Node &node, - float mat[4][4], - float parent_mat[4][4], - bool limit_precision) +void TransformWriter::add_joint_transform(COLLADASW::Node &node, + float mat[4][4], + float parent_mat[4][4], + BCExportSettings &export_settings, + bool has_restmat) { - float loc[3], rot[3], scale[3]; float local[4][4]; if (parent_mat) { @@ -42,67 +42,45 @@ void TransformWriter::add_node_transform(COLLADASW::Node &node, copy_m4_m4(local, mat); } + if (!has_restmat && export_settings.get_apply_global_orientation()) { + bc_apply_global_transform(local, export_settings.get_global_transform()); + } + double dmat[4][4]; UnitConverter *converter = new UnitConverter(); converter->mat4_to_dae_double(dmat, local); delete converter; - bc_decompose(local, loc, rot, NULL, scale); - - if (node.getType() == COLLADASW::Node::JOINT) { - // XXX Why are joints handled differently ? + if (export_settings.get_object_transformation_type() == BC_TRANSFORMATION_TYPE_MATRIX) { node.addMatrix("transform", dmat); } else { + float loc[3], rot[3], scale[3]; + bc_decompose(local, loc, rot, NULL, scale); add_transform(node, loc, rot, scale); } } void TransformWriter::add_node_transform_ob(COLLADASW::Node &node, Object *ob, - BC_export_transformation_type transformation_type, - bool limit_precision) + BCExportSettings &export_settings) { -#if 0 - float rot[3], loc[3], scale[3]; - - if (ob->parent) { - float C[4][4], tmat[4][4], imat[4][4], mat[4][4]; - - // factor out scale from obmat - - copy_v3_v3(scale, ob->scale); - - ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f; - BKE_object_to_mat4(ob, C); - copy_v3_v3(ob->scale, scale); + BC_export_transformation_type transformation_type = + export_settings.get_object_transformation_type(); + bool limit_precision = export_settings.get_limit_precision(); - mul_m4_series(tmat, ob->parent->obmat, ob->parentinv, C); - - // calculate local mat - - invert_m4_m4(imat, ob->parent->obmat); - mul_m4_m4m4(mat, imat, tmat); - - // done + /* Export the local Matrix (relative to the object parent, + * be it an object, bone or vertex(-tices)). */ + Matrix f_obmat; + BKE_object_matrix_local_get(ob, f_obmat); - mat4_to_eul(rot, mat); - copy_v3_v3(loc, mat[3]); + if (export_settings.get_apply_global_orientation()) { + bc_apply_global_transform(f_obmat, export_settings.get_global_transform()); } else { - copy_v3_v3(loc, ob->loc); - copy_v3_v3(rot, ob->rot); - copy_v3_v3(scale, ob->scale); + bc_add_global_transform(f_obmat, export_settings.get_global_transform()); } - add_transform(node, loc, rot, scale); -#endif - - /* Export the local Matrix (relative to the object parent, - * be it an object, bone or vertex(-tices)). */ - float f_obmat[4][4]; - BKE_object_matrix_local_get(ob, f_obmat); - switch (transformation_type) { case BC_TRANSFORMATION_TYPE_MATRIX: { UnitConverter converter; @@ -113,7 +91,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node &node, node.addMatrix("transform", d_obmat); break; } - case BC_TRANSFORMATION_TYPE_TRANSROTLOC: { + case BC_TRANSFORMATION_TYPE_DECOMPOSED: { float loc[3], rot[3], scale[3]; bc_decompose(f_obmat, loc, rot, NULL, scale); if (limit_precision) { @@ -127,10 +105,27 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node &node, } } -void TransformWriter::add_node_transform_identity(COLLADASW::Node &node) +void TransformWriter::add_node_transform_identity(COLLADASW::Node &node, + BCExportSettings &export_settings) { - float loc[3] = {0.0f, 0.0f, 0.0f}, scale[3] = {1.0f, 1.0f, 1.0f}, rot[3] = {0.0f, 0.0f, 0.0f}; - add_transform(node, loc, rot, scale); + BC_export_transformation_type transformation_type = + export_settings.get_object_transformation_type(); + switch (transformation_type) { + case BC_TRANSFORMATION_TYPE_MATRIX: { + BCMatrix mat; + DMatrix d_obmat; + mat.get_matrix(d_obmat); + node.addMatrix("transform", d_obmat); + break; + } + default: { + float loc[3] = {0.0f, 0.0f, 0.0f}; + float scale[3] = {1.0f, 1.0f, 1.0f}; + float rot[3] = {0.0f, 0.0f, 0.0f}; + add_transform(node, loc, rot, scale); + break; + } + } } void TransformWriter::add_transform(COLLADASW::Node &node, diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h index 22ba0716cfe..d2e4b369cdc 100644 --- a/source/blender/collada/TransformWriter.h +++ b/source/blender/collada/TransformWriter.h @@ -31,17 +31,15 @@ class TransformWriter { protected: - void add_node_transform(COLLADASW::Node &node, - float mat[4][4], - float parent_mat[4][4], - bool limit_precision = false); + void add_joint_transform(COLLADASW::Node &node, + float mat[4][4], + float parent_mat[4][4], + BCExportSettings &export_settings, + bool has_restmat); - void add_node_transform_ob(COLLADASW::Node &node, - Object *ob, - BC_export_transformation_type transformation_type, - bool limit_precision = false); + void add_node_transform_ob(COLLADASW::Node &node, Object *ob, BCExportSettings &export_settings); - void add_node_transform_identity(COLLADASW::Node &node); + void add_node_transform_identity(COLLADASW::Node &node, BCExportSettings &export_settings); private: void add_transform(COLLADASW::Node &node, float loc[3], float rot[3], float scale[3]); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 9f2d3f951ec..9e8896c2b9f 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -60,6 +60,7 @@ extern "C" { #include "ED_armature.h" #include "ED_screen.h" #include "ED_node.h" +#include "ED_object.h" #include "MEM_guardedalloc.h" @@ -104,26 +105,6 @@ int bc_test_parent_loop(Object *par, Object *ob) return bc_test_parent_loop(par->parent, ob); } -void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer) -{ - Base *base; - for (base = (Base *)view_layer->object_bases.first; base; base = base->next) { - Object *cob = base->object; - if (cob->parent == ob) { - switch (ob->type) { - case OB_MESH: - case OB_CAMERA: - case OB_LAMP: - case OB_EMPTY: - case OB_ARMATURE: - child_set.push_back(cob); - default: - break; - } - } - } -} - bool bc_validateConstraints(bConstraint *con) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); @@ -146,43 +127,19 @@ bool bc_validateConstraints(bConstraint *con) return true; } -/* a shortened version of parent_set_exec() - * if is_parent_space is true then ob->obmat will be multiplied by par->obmat before parenting */ -int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space) +bool bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space) { - Object workob; - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *sce = CTX_data_scene(C); - - if (!par || bc_test_parent_loop(par, ob)) - return false; - - ob->parent = par; - ob->partype = PAROBJECT; - - ob->parsubstr[0] = 0; + Scene *scene = CTX_data_scene(C); + int partype = PAR_OBJECT; + const bool xmirror = false; + const bool keep_transform = false; - if (is_parent_space) { - float mat[4][4]; - /* calc par->obmat */ - BKE_object_where_is_calc(depsgraph, sce, par); - - /* move child obmat into world space */ - mul_m4_m4m4(mat, par->obmat, ob->obmat); - copy_m4_m4(ob->obmat, mat); + if (par && is_parent_space) { + mul_m4_m4m4(ob->obmat, par->obmat, ob->obmat); } - /* apply child obmat (i.e. decompose it into rot/loc/size) */ - BKE_object_apply_mat4(ob, ob->obmat, 0, 0); - - /* compute parentinv */ - BKE_object_workob_calc_parent(depsgraph, sce, ob, &workob); - invert_m4_m4(ob->parentinv, workob.obmat); - - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM); - - return true; + bool ok = ED_object_parent_set(NULL, C, scene, ob, par, partype, xmirror, keep_transform, NULL); + return ok; } std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool all_actions) @@ -309,49 +266,6 @@ Object *bc_get_assigned_armature(Object *ob) return ob_arm; } -/** - * Returns the highest selected ancestor - * returns NULL if no ancestor is selected - * IMPORTANT: This function expects that all exported objects have set: - * ob->id.tag & LIB_TAG_DOIT - */ -Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob) - -{ - Object *ancestor = ob; - while (ob->parent && bc_is_marked(ob->parent)) { - ob = ob->parent; - ancestor = ob; - } - return ancestor; -} - -bool bc_is_base_node(LinkNode *export_set, Object *ob) -{ - Object *root = bc_get_highest_selected_ancestor_or_self(export_set, ob); - return (root == ob); -} - -bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer) -{ - bool to_export = (BLI_linklist_index(export_set, ob) != -1); - - if (!to_export) { - /* Mark this object as to_export even if it is not in the - * export list, but it contains children to export. */ - - std::vector<Object *> children; - bc_get_children(children, ob, view_layer); - for (int i = 0; i < children.size(); i++) { - if (bc_is_in_Export_set(export_set, children[i], view_layer)) { - to_export = true; - break; - } - } - } - return to_export; -} - bool bc_has_object_type(LinkNode *export_set, short obtype) { LinkNode *node; @@ -366,21 +280,6 @@ bool bc_has_object_type(LinkNode *export_set, short obtype) return false; } -int bc_is_marked(Object *ob) -{ - return ob && (ob->id.tag & LIB_TAG_DOIT); -} - -void bc_remove_mark(Object *ob) -{ - ob->id.tag &= ~LIB_TAG_DOIT; -} - -void bc_set_mark(Object *ob) -{ - ob->id.tag |= LIB_TAG_DOIT; -} - /* Use bubble sort algorithm for sorting the export set */ void bc_bubble_sort_by_Object_name(LinkNode *export_set) { @@ -1026,26 +925,75 @@ bool bc_has_animations(Object *ob) return false; } -bool bc_has_animations(Scene *sce, LinkNode &export_set) +bool bc_has_animations(Scene *sce, LinkNode *export_set) { LinkNode *node; + if (export_set) { + for (node = export_set; node; node = node->next) { + Object *ob = (Object *)node->link; - for (node = &export_set; node; node = node->next) { - Object *ob = (Object *)node->link; - - if (bc_has_animations(ob)) - return true; + if (bc_has_animations(ob)) + return true; + } } return false; } +void bc_add_global_transform(Matrix &to_mat, + const Matrix &from_mat, + const BCMatrix &global_transform, + const bool invert) +{ + copy_m4_m4(to_mat, from_mat); + bc_add_global_transform(to_mat, global_transform, invert); +} + +void bc_add_global_transform(Vector &to_vec, + const Vector &from_vec, + const BCMatrix &global_transform, + const bool invert) +{ + copy_v3_v3(to_vec, from_vec); + bc_add_global_transform(to_vec, global_transform, invert); +} + +void bc_add_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert) +{ + BCMatrix mat(to_mat); + mat.add_transform(global_transform, invert); + mat.get_matrix(to_mat); +} + +void bc_add_global_transform(Vector &to_vec, const BCMatrix &global_transform, const bool invert) +{ + Matrix mat; + Vector from_vec; + copy_v3_v3(from_vec, to_vec); + global_transform.get_matrix(mat, false, 6, invert); + mul_v3_m4v3(to_vec, mat, from_vec); +} + +void bc_apply_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert) +{ + BCMatrix mat(to_mat); + mat.apply_transform(global_transform, invert); + mat.get_matrix(to_mat); +} + +void bc_apply_global_transform(Vector &to_vec, const BCMatrix &global_transform, const bool invert) +{ + Matrix transform; + global_transform.get_matrix(transform); + mul_v3_m4v3(to_vec, transform, to_vec); +} + /** * Check if custom information about bind matrix exists and modify the from_mat * accordingly. * * Note: This is old style for Blender <= 2.78 only kept for compatibility */ -void bc_create_restpose_mat(const ExportSettings *export_settings, +void bc_create_restpose_mat(BCExportSettings &export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], @@ -1056,9 +1004,9 @@ void bc_create_restpose_mat(const ExportSettings *export_settings, float scale[3]; static const float V0[3] = {0, 0, 0}; - if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") && - !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") && - !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale")) { + if (!has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_loc") && + !has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_rot") && + !has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_scale")) { /* No need */ copy_m4_m4(to_mat, from_mat); return; @@ -1067,7 +1015,7 @@ void bc_create_restpose_mat(const ExportSettings *export_settings, bc_decompose(from_mat, loc, rot, NULL, scale); loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6); - if (export_settings->keep_bind_info) { + if (export_settings.get_keep_bind_info()) { bc_get_property_vector(bone, "restpose_loc", loc, loc); if (use_local_space && bone->parent) { @@ -1083,7 +1031,7 @@ void bc_create_restpose_mat(const ExportSettings *export_settings, } } - if (export_settings->keep_bind_info) { + if (export_settings.get_keep_bind_info()) { if (bc_get_IDProperty(bone, "restpose_rot_x")) rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0)); if (bc_get_IDProperty(bone, "restpose_rot_y")) @@ -1092,7 +1040,7 @@ void bc_create_restpose_mat(const ExportSettings *export_settings, rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0)); } - if (export_settings->keep_bind_info) { + if (export_settings.get_keep_bind_info()) { bc_get_property_vector(bone, "restpose_scale", scale, scale); } diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index dfd5519be31..ca40de6fc1d 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -133,10 +133,9 @@ std::string bc_get_action_id(std::string action_name, extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray &array, unsigned int index); extern int bc_test_parent_loop(Object *par, Object *ob); -extern void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer); extern bool bc_validateConstraints(bConstraint *con); -extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true); +bool bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true); extern Object *bc_add_object( Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name); extern Mesh *bc_get_mesh_copy(BlenderContext &blender_context, @@ -146,15 +145,8 @@ extern Mesh *bc_get_mesh_copy(BlenderContext &blender_context, bool triangulate); extern Object *bc_get_assigned_armature(Object *ob); -extern Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob); -extern bool bc_is_base_node(LinkNode *export_set, Object *ob); -extern bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer); extern bool bc_has_object_type(LinkNode *export_set, short obtype); -extern int bc_is_marked(Object *ob); -extern void bc_remove_mark(Object *ob); -extern void bc_set_mark(Object *ob); - extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n); extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type); @@ -235,15 +227,62 @@ extern bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]) extern void bc_enable_fcurves(bAction *act, char *bone_name); extern bool bc_bone_matrix_local_get(Object *ob, Bone *bone, Matrix &mat, bool for_opensim); extern bool bc_is_animated(BCMatrixSampleMap &values); -extern bool bc_has_animations(Scene *sce, LinkNode &node); +extern bool bc_has_animations(Scene *sce, LinkNode *node); extern bool bc_has_animations(Object *ob); -extern void bc_create_restpose_mat(const ExportSettings *export_settings, +extern void bc_add_global_transform(Matrix &to_mat, + const Matrix &from_mat, + const BCMatrix &global_transform, + const bool invert = false); +extern void bc_add_global_transform(Vector &to_vec, + const Vector &from_vec, + const BCMatrix &global_transform, + const bool invert = false); +extern void bc_add_global_transform(Vector &to_vec, + const BCMatrix &global_transform, + const bool invert = false); +extern void bc_add_global_transform(Matrix &to_mat, + const BCMatrix &global_transform, + const bool invert = false); +extern void bc_apply_global_transform(Matrix &to_mat, + const BCMatrix &global_transform, + const bool invert = false); +extern void bc_apply_global_transform(Vector &to_vec, + const BCMatrix &global_transform, + const bool invert = false); +extern void bc_create_restpose_mat(BCExportSettings &export_settings, Bone *bone, float to_mat[4][4], - float world[4][4], + float from_mat[4][4], bool use_local_space); +class ColladaBaseNodes { + private: + std::vector<Object *> base_objects; + + public: + void add(Object *ob) + { + base_objects.push_back(ob); + } + + bool contains(Object *ob) + { + std::vector<Object *>::iterator it = std::find(base_objects.begin(), base_objects.end(), ob); + return (it != base_objects.end()); + } + + int size() + { + return base_objects.size(); + } + + Object *get(int index) + { + return base_objects[index]; + } +}; + class BCPolygonNormalsIndices { std::vector<unsigned int> normal_indices; @@ -293,7 +332,7 @@ class BoneExtended { bool has_roll(); float get_roll(); - void set_tail(float *vec); + void set_tail(float vec[]); float *get_tail(); bool has_tail(); diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cpp b/source/blender/compositor/operations/COM_ScaleOperation.cpp index 1c5b2a71859..37ce832209c 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.cpp +++ b/source/blender/compositor/operations/COM_ScaleOperation.cpp @@ -95,10 +95,10 @@ bool ScaleOperation::determineDependingAreaOfInterest(rcti *input, const float scx = scaleX[0]; const float scy = scaleY[0]; - newInput.xmax = this->m_centerX + (input->xmax - this->m_centerX) / scx; - newInput.xmin = this->m_centerX + (input->xmin - this->m_centerX) / scx; - newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / scy; - newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / scy; + newInput.xmax = this->m_centerX + (input->xmax - this->m_centerX) / scx + 1; + newInput.xmin = this->m_centerX + (input->xmin - this->m_centerX) / scx - 1; + newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / scy + 1; + newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / scy - 1; } else { newInput.xmax = this->getWidth(); diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index ba6b3b32d60..c3099c9486d 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -42,11 +42,13 @@ set(SRC intern/builder/deg_builder_map.cc intern/builder/deg_builder_nodes.cc intern/builder/deg_builder_nodes_rig.cc + intern/builder/deg_builder_nodes_scene.cc intern/builder/deg_builder_nodes_view_layer.cc intern/builder/deg_builder_pchanmap.cc intern/builder/deg_builder_relations.cc intern/builder/deg_builder_relations_keys.cc intern/builder/deg_builder_relations_rig.cc + intern/builder/deg_builder_relations_scene.cc intern/builder/deg_builder_relations_view_layer.cc intern/builder/deg_builder_rna.cc intern/builder/deg_builder_transitive.cc diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index 2d0bc6ff15b..15abc0c0a64 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -52,14 +52,19 @@ extern "C" { /* Graph Building -------------------------------- */ -/* Build depsgraph for the given scene, and dump results in given - * graph container. - */ +/* Build depsgraph for the given scene, and dump results in given graph container. */ void DEG_graph_build_from_view_layer(struct Depsgraph *graph, struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer); +/* Special version of builder which produces dependency graph suitable for the render pipeline. + * It will contain sequencer and compositor (if needed) and all their dependencies. */ +void DEG_graph_build_for_render_pipeline(struct Depsgraph *graph, + struct Main *bmain, + struct Scene *scene, + struct ViewLayer *view_layer); + /* Tag relations from the given graph for update. */ void DEG_graph_tag_relations_update(struct Depsgraph *graph); diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h index a7b5535d11a..9b7e5b95fdc 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.h +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -29,6 +29,9 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" +/* Needed for the instance iterator. */ +#include "DNA_object_types.h" + struct ID; struct BLI_Iterator; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.cc b/source/blender/depsgraph/intern/builder/deg_builder_map.cc index a519f3e60b5..4bca4f037b0 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_map.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_map.cc @@ -23,41 +23,52 @@ #include "intern/builder/deg_builder_map.h" -#include "BLI_utildefines.h" -#include "BLI_ghash.h" - #include "DNA_ID.h" namespace DEG { BuilderMap::BuilderMap() { - set = BLI_gset_ptr_new("deg builder gset"); } BuilderMap::~BuilderMap() { - BLI_gset_free(set, NULL); } -bool BuilderMap::checkIsBuilt(ID *id) +bool BuilderMap::checkIsBuilt(ID *id, int tag) const { - return BLI_gset_haskey(set, id); + return (getIDTag(id) & tag) == tag; } -void BuilderMap::tagBuild(ID *id) +void BuilderMap::tagBuild(ID *id, int tag) { - BLI_gset_insert(set, id); + IDTagMap::iterator it = id_tags_.find(id); + if (it == id_tags_.end()) { + id_tags_.insert(make_pair(id, tag)); + return; + } + it->second |= tag; } -bool BuilderMap::checkIsBuiltAndTag(ID *id) +bool BuilderMap::checkIsBuiltAndTag(ID *id, int tag) { - void **key_p; - if (!BLI_gset_ensure_p_ex(set, id, &key_p)) { - *key_p = id; + IDTagMap::iterator it = id_tags_.find(id); + if (it == id_tags_.end()) { + id_tags_.insert(make_pair(id, tag)); return false; } - return true; + const bool result = (it->second & tag) == tag; + it->second |= tag; + return result; +} + +int BuilderMap::getIDTag(ID *id) const +{ + IDTagMap::const_iterator it = id_tags_.find(id); + if (it == id_tags_.end()) { + return 0; + } + return it->second; } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.h b/source/blender/depsgraph/intern/builder/deg_builder_map.h index c1db1d9d2bb..dd124e07a00 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_map.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_map.h @@ -23,6 +23,8 @@ #pragma once +#include "intern/depsgraph_type.h" + struct GSet; struct ID; @@ -30,34 +32,51 @@ namespace DEG { class BuilderMap { public: + enum { + TAG_ANIMATION = (1 << 0), + TAG_PARAMETERS = (1 << 1), + TAG_TRANSFORM = (1 << 2), + TAG_GEOMETRY = (1 << 3), + + TAG_SCENE_COMPOSITOR = (1 << 4), + TAG_SCENE_SEQUENCER = (1 << 5), + + /* All ID components has been built. */ + TAG_COMPLETE = (TAG_ANIMATION | TAG_PARAMETERS | TAG_TRANSFORM | TAG_GEOMETRY | + TAG_SCENE_COMPOSITOR | TAG_SCENE_SEQUENCER), + }; + BuilderMap(); ~BuilderMap(); - /* Check whether given ID is already handled by builder (or if it's being - * handled). */ - bool checkIsBuilt(ID *id); + /* Check whether given ID is already handled by builder (or if it's being handled). */ + bool checkIsBuilt(ID *id, int tag = TAG_COMPLETE) const; /* Tag given ID as handled/built. */ - void tagBuild(ID *id); + void tagBuild(ID *id, int tag = TAG_COMPLETE); - /* Combination of previous two functions, returns truth if ID was already - * handled, or tags is handled otherwise and return false. */ - bool checkIsBuiltAndTag(ID *id); + /* Combination of previous two functions, returns truth if ID was already handled, or tags is + * handled otherwise and return false. */ + bool checkIsBuiltAndTag(ID *id, int tag = TAG_COMPLETE); - template<typename T> bool checkIsBuilt(T *datablock) + template<typename T> bool checkIsBuilt(T *datablock, int tag = TAG_COMPLETE) const { - return checkIsBuilt(&datablock->id); + return checkIsBuilt(&datablock->id, tag); } - template<typename T> void tagBuild(T *datablock) + template<typename T> void tagBuild(T *datablock, int tag = TAG_COMPLETE) { - tagBuild(&datablock->id); + tagBuild(&datablock->id, tag); } - template<typename T> bool checkIsBuiltAndTag(T *datablock) + template<typename T> bool checkIsBuiltAndTag(T *datablock, int tag = TAG_COMPLETE) { - return checkIsBuiltAndTag(&datablock->id); + return checkIsBuiltAndTag(&datablock->id, tag); } - GSet *set; + protected: + int getIDTag(ID *id) const; + + typedef map<ID *, int> IDTagMap; + IDTagMap id_tags_; }; } // 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 0d10bd1d3dc..93e5dd14ae0 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -453,6 +453,9 @@ void DepsgraphNodeBuilder::build_id(ID *id) case ID_CF: build_cachefile((CacheFile *)id); break; + case ID_SCE: + build_scene_parameters((Scene *)id); + break; default: fprintf(stderr, "Unhandled ID %s\n", id->name); BLI_assert(!"Should never happen"); @@ -540,7 +543,10 @@ void DepsgraphNodeBuilder::build_object(int base_index, IDNode *id_node = add_id_node(&object->id); Object *object_cow = get_cow_datablock(object); id_node->linked_state = linked_state; - if (object == scene_->camera) { + /* NOTE: Scene is NULL when building dependency graph for render pipeline. + * Probably need to assign that to something non-NULL, but then the logic here will still be + * somewhat weird. */ + if (scene_ != NULL && object == scene_->camera) { id_node->is_directly_visible = true; } else { @@ -681,7 +687,7 @@ void DepsgraphNodeBuilder::build_object_data(Object *object, bool is_object_visi break; default: { ID *obdata = (ID *)object->data; - if (built_map_.checkIsBuilt(obdata) == 0) { + if (!built_map_.checkIsBuilt(obdata)) { build_animdata(obdata); } break; @@ -1306,6 +1312,9 @@ void DepsgraphNodeBuilder::build_camera(Camera *camera) } build_animdata(&camera->id); build_parameters(&camera->id); + if (camera->dof.focus_object != NULL) { + build_object(-1, camera->dof.focus_object, DEG_ID_LINKED_INDIRECTLY, false); + } } void DepsgraphNodeBuilder::build_light(Light *lamp) @@ -1363,8 +1372,16 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY, true); } else if (id_type == ID_SCE) { - /* Scenes are used by compositor trees, and handled by render - * pipeline. No need to build dependencies for them here. */ + Scene *node_scene = (Scene *)id; + build_scene_parameters(node_scene); + /* Camera is used by defocus node. + * + * On the one hand it's annoying to always pull it in, but on another hand it's also annoying + * to have hardcoded node-type exception here. */ + if (node_scene->camera != NULL) { + /* TODO(sergey): Use visibility of owner of the node tree. */ + build_object(-1, node_scene->camera, DEG_ID_LINKED_INDIRECTLY, true); + } } else if (id_type == ID_TXT) { /* Ignore script nodes. */ @@ -1439,19 +1456,6 @@ void DepsgraphNodeBuilder::build_image(Image *image) &image->id, NodeType::GENERIC_DATABLOCK, OperationCode::GENERIC_DATABLOCK_UPDATE); } -void DepsgraphNodeBuilder::build_compositor(Scene *scene) -{ - /* For now, just a plain wrapper? */ - // TODO: create compositing component? - // XXX: component type undefined! - // graph->get_node(&scene->id, NULL, NodeType::COMPOSITING, NULL); - - /* for now, nodetrees are just parameters; compositing occurs in internals - * of renderer... */ - add_component_node(&scene->id, NodeType::PARAMETERS); - build_nodetree(scene->nodetree); -} - void DepsgraphNodeBuilder::build_gpencil(bGPdata *gpd) { if (built_map_.checkIsBuiltAndTag(gpd)) { @@ -1492,7 +1496,7 @@ void DepsgraphNodeBuilder::build_mask(Mask *mask) return; } ID *mask_id = &mask->id; - Mask *mask_cow = get_cow_datablock(mask); + Mask *mask_cow = (Mask *)ensure_cow_id(mask_id); /* F-Curve based animation. */ build_animdata(mask_id); build_parameters(mask_id); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 41314380b23..c3a04a9ad88 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -152,6 +152,11 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { ID *id, NodeType comp_type, OperationCode opcode, const char *name = "", int name_tag = -1); void build_id(ID *id); + + void build_scene_render(Scene *scene); + void build_scene_parameters(Scene *scene); + void build_scene_compositor(Scene *scene); + void build_layer_collections(ListBase *lb); void build_view_layer(Scene *scene, ViewLayer *view_layer, @@ -200,7 +205,6 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { void build_texture(Tex *tex); void build_image(Image *image); void build_world(World *world); - void build_compositor(Scene *scene); void build_gpencil(bGPdata *gpd); void build_cachefile(CacheFile *cache_file); void build_mask(Mask *mask); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc new file mode 100644 index 00000000000..b092799e692 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc @@ -0,0 +1,63 @@ +/* + * 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) 2013 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/builder/deg_builder_nodes.h" + +#include "DNA_scene_types.h" + +namespace DEG { + +void DepsgraphNodeBuilder::build_scene_render(Scene *scene) +{ + scene_ = scene; + const bool build_compositor = (scene->r.scemode & R_DOCOMP); + IDNode *id_node = add_id_node(&scene->id); + id_node->linked_state = DEG_ID_LINKED_DIRECTLY; + add_time_source(); + build_scene_parameters(scene); + if (build_compositor) { + build_scene_compositor(scene); + } +} + +void DepsgraphNodeBuilder::build_scene_parameters(Scene *scene) +{ + if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_PARAMETERS)) { + return; + } + add_operation_node(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL); + add_operation_node(&scene->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL); +} + +void DepsgraphNodeBuilder::build_scene_compositor(Scene *scene) +{ + if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_SCENE_COMPOSITOR)) { + return; + } + if (scene->nodetree == NULL) { + return; + } + build_nodetree(scene->nodetree); +} + +} // namespace DEG 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 b898b3d3519..baebd682f3f 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 @@ -125,9 +125,7 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene, build_world(scene->world); } /* Compositor nodes */ - if (scene->nodetree != NULL) { - build_compositor(scene); - } + build_scene_compositor(scene); /* Cache file. */ LISTBASE_FOREACH (CacheFile *, cachefile, &bmain_->cachefiles) { build_cachefile(cachefile); @@ -157,7 +155,7 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene, OperationCode::VIEW_LAYER_EVAL, function_bind(BKE_layer_eval_view_layer_indexed, _1, scene_cow, view_layer_index_)); /* Parameters evaluation for scene relations mainly. */ - add_operation_node(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL); + build_scene_parameters(scene); /* Build all set scenes. */ if (scene->set != NULL) { ViewLayer *set_view_layer = BKE_view_layer_default_render(scene->set); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 5686bcac5cb..54d5223497e 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -497,6 +497,9 @@ void DepsgraphRelationBuilder::build_id(ID *id) case ID_CF: build_cachefile((CacheFile *)id); break; + case ID_SCE: + build_scene_parameters((Scene *)id); + break; default: fprintf(stderr, "Unhandled ID %s\n", id->name); BLI_assert(!"Should never happen"); @@ -563,6 +566,7 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object) &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_LOCAL); OperationKey parent_transform_key( &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_PARENT); + OperationKey transform_eval_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL); OperationKey final_transform_key( &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL); OperationKey ob_eval_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL); @@ -638,16 +642,18 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object) } /* Proxy object to copy from. */ if (object->proxy_from != NULL) { + /* Object is linked here (comes from the library). */ build_object(NULL, object->proxy_from); ComponentKey ob_transform_key(&object->proxy_from->id, NodeType::TRANSFORM); ComponentKey proxy_transform_key(&object->id, NodeType::TRANSFORM); add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform"); } - if (object->proxy_group != NULL) { + if (object->proxy_group != NULL && object->proxy_group != object->proxy) { + /* Object is local here (local in .blend file, users interacts with it). */ build_object(NULL, object->proxy_group); OperationKey proxy_group_eval_key( &object->proxy_group->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL); - add_relation(proxy_group_eval_key, final_transform_key, "Proxy Group Transform"); + add_relation(proxy_group_eval_key, transform_eval_key, "Proxy Group Transform"); } /* Object dupligroup. */ if (object->instance_collection != NULL) { @@ -1852,7 +1858,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) /* Special case: modifiers evaluation queries scene for various things like * data mask to be used. We add relation here to ensure object is never * evaluated prior to Scene's CoW is ready. */ - OperationKey scene_key(&scene_->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL); + OperationKey scene_key(&scene_->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL); Relation *rel = add_relation(scene_key, obdata_ubereval_key, "CoW Relation"); rel->flag |= RELATION_FLAG_NO_FLUSH; /* Modifiers */ @@ -2070,6 +2076,7 @@ void DepsgraphRelationBuilder::build_camera(Camera *camera) build_animdata(&camera->id); build_parameters(&camera->id); if (camera->dof.focus_object != NULL) { + build_object(NULL, camera->dof.focus_object); ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS); ComponentKey dof_ob_key(&camera->dof.focus_object->id, NodeType::TRANSFORM); add_relation(dof_ob_key, camera_parameters_key, "Camera DOF"); @@ -2125,8 +2132,15 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) build_object(NULL, (Object *)id); } else if (id_type == ID_SCE) { - /* Scenes are used by compositor trees, and handled by render - * pipeline. No need to build dependencies for them here. */ + Scene *node_scene = (Scene *)id; + build_scene_parameters(node_scene); + /* Camera is used by defocus node. + * + * On the one hand it's annoying to always pull it in, but on another hand it's also annoying + * to have hardcoded node-type exception here. */ + if (node_scene->camera != NULL) { + build_object(NULL, node_scene->camera); + } } else if (id_type == ID_TXT) { /* Ignore script nodes. */ @@ -2214,12 +2228,6 @@ void DepsgraphRelationBuilder::build_image(Image *image) build_parameters(&image->id); } -void DepsgraphRelationBuilder::build_compositor(Scene *scene) -{ - /* For now, just a plain wrapper? */ - build_nodetree(scene->nodetree); -} - void DepsgraphRelationBuilder::build_gpencil(bGPdata *gpd) { if (built_map_.checkIsBuiltAndTag(gpd)) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 1cf0b48128f..7d302092119 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -194,6 +194,11 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { void add_special_eval_flag(ID *object, uint32_t flag); void build_id(ID *id); + + void build_scene_render(Scene *scene); + void build_scene_parameters(Scene *scene); + void build_scene_compositor(Scene *scene); + void build_layer_collections(ListBase *lb); void build_view_layer(Scene *scene, ViewLayer *view_layer); void build_collection(LayerCollection *from_layer_collection, @@ -258,7 +263,6 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { void build_material(Material *ma); void build_texture(Tex *tex); void build_image(Image *image); - void build_compositor(Scene *scene); void build_gpencil(bGPdata *gpd); void build_cachefile(CacheFile *cache_file); void build_mask(Mask *mask); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc new file mode 100644 index 00000000000..26bb1bd3d2a --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc @@ -0,0 +1,62 @@ +/* + * 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) 2013 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/builder/deg_builder_relations.h" + +#include "DNA_scene_types.h" + +namespace DEG { + +void DepsgraphRelationBuilder::build_scene_render(Scene *scene) +{ + scene_ = scene; + const bool build_compositor = (scene->r.scemode & R_DOCOMP); + build_scene_parameters(scene); + if (build_compositor) { + build_scene_compositor(scene); + } +} + +void DepsgraphRelationBuilder::build_scene_parameters(Scene *scene) +{ + if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_PARAMETERS)) { + return; + } + OperationKey parameters_eval_key( + &scene->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL); + OperationKey scene_eval_key(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL); + add_relation(parameters_eval_key, scene_eval_key, "Parameters -> Scene Eval"); +} + +void DepsgraphRelationBuilder::build_scene_compositor(Scene *scene) +{ + if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_SCENE_COMPOSITOR)) { + return; + } + if (scene->nodetree == NULL) { + return; + } + build_nodetree(scene->nodetree); +} + +} // namespace DEG 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 b5a926ad597..b832473bde9 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 @@ -106,10 +106,6 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la if (scene->world != NULL) { build_world(scene->world); } - /* Compositor nodes. */ - if (scene->nodetree != NULL) { - build_compositor(scene); - } /* Masks. */ LISTBASE_FOREACH (Mask *, mask, &bmain_->masks) { build_mask(mask); @@ -128,6 +124,14 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la build_collection(NULL, NULL, fls->group); } } + /* Scene parameters, compositor and such. */ + build_scene_compositor(scene); + build_scene_parameters(scene); + /* Make final scene evaluation dependent on view layer evaluation. */ + OperationKey scene_view_layer_key( + &scene->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL); + OperationKey scene_eval_key(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL); + add_relation(scene_view_layer_key, scene_eval_key, "View Layer -> Scene Eval"); /* Build all set scenes. */ if (scene->set != NULL) { ViewLayer *set_view_layer = BKE_view_layer_default_render(scene->set); diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index e2a9dde1eea..5d96bfad95e 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -73,7 +73,8 @@ Depsgraph::Depsgraph(Scene *scene, ViewLayer *view_layer, eEvaluationMode mode) ctime(BKE_scene_frame_get(scene)), scene_cow(NULL), is_active(false), - debug_is_evaluating(false) + debug_is_evaluating(false), + is_render_pipeline_depsgraph(false) { BLI_spin_init(&lock); id_hash = BLI_ghash_ptr_new("Depsgraph id hash"); diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index 2dcbb6b5574..073ec99b3aa 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -194,6 +194,12 @@ struct Depsgraph { bool debug_is_evaluating; + /* Is set to truth for dependency graph which are used for post-processing (compositor and + * sequencer). + * Such dependency graph needs all view layers (so render pipeline can access names), but it + * does not need any bases. */ + bool is_render_pipeline_depsgraph; + /* Cached list of colliders/effectors for collections and the scene * created along with relations, for fast lookup during evaluation. */ GHash *physics_relations[DEG_PHYSICS_RELATIONS_NUM]; diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index dd2979160cd..138b23888b4 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -222,9 +222,33 @@ struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle) /* ******************** */ /* Graph Building API's */ -/* Build depsgraph for the given scene layer, and dump results in given - * graph container. - */ +static void graph_build_finalize_common(DEG::Depsgraph *deg_graph, Main *bmain) +{ + /* Detect and solve cycles. */ + DEG::deg_graph_detect_cycles(deg_graph); + /* Simplify the graph by removing redundant relations (to optimize + * traversal later). */ + /* TODO: it would be useful to have an option to disable this in cases where + * it is causing trouble. */ + if (G.debug_value == 799) { + DEG::deg_graph_transitive_reduction(deg_graph); + } + /* Store pointers to commonly used valuated datablocks. */ + deg_graph->scene_cow = (Scene *)deg_graph->get_cow_id(°_graph->scene->id); + /* Flush visibility layer and re-schedule nodes for update. */ + DEG::deg_graph_build_finalize(bmain, deg_graph); + DEG_graph_on_visible_update(bmain, reinterpret_cast<::Depsgraph *>(deg_graph)); +#if 0 + if (!DEG_debug_consistency_check(deg_graph)) { + printf("Consistency validation failed, ABORTING!\n"); + abort(); + } +#endif + /* Relations are up to date. */ + deg_graph->need_update = false; +} + +/* Build depsgraph for the given scene layer, and dump results in given graph container. */ void DEG_graph_build_from_view_layer(Depsgraph *graph, Main *bmain, Scene *scene, @@ -245,34 +269,46 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph, node_builder.begin_build(); node_builder.build_view_layer(scene, view_layer, DEG::DEG_ID_LINKED_DIRECTLY); node_builder.end_build(); - /* Hook up relationships between operations - to determine evaluation - * order. */ + /* Hook up relationships between operations - to determine evaluation order. */ DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache); relation_builder.begin_build(); 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); - /* Simplify the graph by removing redundant relations (to optimize - * traversal later). */ - /* TODO: it would be useful to have an option to disable this in cases where - * it is causing trouble. */ - if (G.debug_value == 799) { - DEG::deg_graph_transitive_reduction(deg_graph); + /* Finalize building. */ + graph_build_finalize_common(deg_graph, bmain); + /* Finish statistics. */ + if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { + printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time); } - /* Store pointers to commonly used valuated datablocks. */ - deg_graph->scene_cow = (Scene *)deg_graph->get_cow_id(°_graph->scene->id); - /* Flush visibility layer and re-schedule nodes for update. */ - DEG::deg_graph_build_finalize(bmain, deg_graph); - DEG_graph_on_visible_update(bmain, graph); -#if 0 - if (!DEG_debug_consistency_check(deg_graph)) { - printf("Consistency validation failed, ABORTING!\n"); - abort(); +} + +void DEG_graph_build_for_render_pipeline(Depsgraph *graph, + Main *bmain, + Scene *scene, + ViewLayer * /*view_layer*/) +{ + double start_time = 0.0; + if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { + start_time = PIL_check_seconds_timer(); } -#endif - /* Relations are up to date. */ - deg_graph->need_update = false; + DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph); + /* Perform sanity checks. */ + BLI_assert(deg_graph->scene == scene); + deg_graph->is_render_pipeline_depsgraph = true; + DEG::DepsgraphBuilderCache builder_cache; + /* Generate all the nodes in the graph first */ + DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph, &builder_cache); + node_builder.begin_build(); + node_builder.build_scene_render(scene); + node_builder.end_build(); + /* Hook up relationships between operations - to determine evaluation + * order. */ + DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache); + relation_builder.begin_build(); + relation_builder.build_scene_render(scene); + relation_builder.build_copy_on_write_relations(); + /* Finalize building. */ + graph_build_finalize_common(deg_graph, bmain); /* Finish statistics. */ if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time); diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 7dcba8b7655..fc1c6be19af 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -249,7 +249,6 @@ void depsgraph_id_tag_copy_on_write(Depsgraph *graph, IDNode *id_node, eUpdateSo { 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, @@ -357,16 +356,16 @@ static void graph_id_tag_update_single_flag(Main *bmain, /* TODO(sergey): Shall we raise some panic here? */ return; } - /* Tag ID recalc flag. */ - DepsNodeFactory *factory = type_get_factory(component_type); - BLI_assert(factory != NULL); - id->recalc |= factory->id_recalc_tag(); /* Some sanity checks before moving forward. */ if (id_node == NULL) { /* Happens when object is tagged for update and not yet in the * dependency graph (but will be after relations update). */ return; } + /* Tag ID recalc flag. */ + DepsNodeFactory *factory = type_get_factory(component_type); + BLI_assert(factory != NULL); + id_node->id_cow->recalc |= factory->id_recalc_tag(); /* Tag corresponding dependency graph operation for update. */ if (component_type == NodeType::ID_REF) { id_node->tag_update(graph, update_source); @@ -440,7 +439,7 @@ void deg_graph_node_tag_zero(Main *bmain, } ID *id = id_node->id_orig; /* TODO(sergey): Which recalc flags to set here? */ - id->recalc |= ID_RECALC_ALL & ~(ID_RECALC_PSYS_ALL | ID_RECALC_ANIMATION); + id_node->id_cow->recalc |= ID_RECALC_ALL & ~(ID_RECALC_PSYS_ALL | ID_RECALC_ANIMATION); GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { if (comp_node->type == NodeType::ANIMATION) { continue; @@ -540,6 +539,8 @@ NodeType geometry_tag_to_component(const ID *id) return NodeType::GEOMETRY; case ID_PAL: /* Palettes */ return NodeType::PARAMETERS; + case ID_MSK: + return NodeType::PARAMETERS; default: break; } @@ -577,7 +578,6 @@ void graph_id_tag_update( if (flag == 0) { deg_graph_node_tag_zero(bmain, graph, id_node, update_source); } - id->recalc |= flag; int current_flag = flag; while (current_flag != 0) { IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_i(¤t_flag)); @@ -742,17 +742,12 @@ static void deg_graph_clear_id_node_func(void *__restrict data_v, DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(data_v); DEG::IDNode *id_node = deg_graph->id_nodes[i]; id_node->id_cow->recalc &= ~ID_RECALC_ALL; - id_node->id_orig->recalc &= ~ID_RECALC_ALL; /* Clear embedded node trees too. */ bNodeTree *ntree_cow = ntreeFromID(id_node->id_cow); if (ntree_cow) { ntree_cow->id.recalc &= ~ID_RECALC_ALL; } - bNodeTree *ntree_orig = ntreeFromID(id_node->id_orig); - if (ntree_orig) { - ntree_orig->id.recalc &= ~ID_RECALC_ALL; - } } void DEG_ids_clear_recalc(Main *UNUSED(bmain), Depsgraph *depsgraph) 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 2a76d5cd362..4bc05bc9185 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 @@ -327,7 +327,7 @@ ViewLayer *get_original_view_layer(const Depsgraph *depsgraph, const IDNode *id_ return BKE_view_layer_default_render(scene_orig); } /* Is possible to have scene linked indirectly (i.e. via the driver) which - * we need to support. Currently there aer issues somewhere else, which + * we need to support. Currently there are issues somewhere else, which * makes testing hard. This is a reported problem, so will eventually be * properly fixed. * @@ -340,7 +340,30 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph, const IDNode *id_node, Scene *scene_cow) { - const ViewLayer *view_layer_input = get_original_view_layer(depsgraph, id_node); + const ViewLayer *view_layer_input; + if (depsgraph->is_render_pipeline_depsgraph) { + /* If the dependency graph is used for post-processing (such as compositor) we do need to + * have access to its view layer names so can not remove any view layers. + * On a more positive side we can remove all the bases from all the view layers. + * + * NOTE: Need to clear pointers which might be pointing to original on freed (due to being + * unused) data. + * + * NOTE: Need to keep view layers for all scenes, even indirect ones. This is because of + * render layer node possibly pointing to another scene. */ + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) { + view_layer->basact = NULL; + } + return; + } + else if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) { + /* Indirectly linked scenes means it's not an input scene and not a set scene, and is pulled + * via some driver. Such scenes should not have view layers after copy. */ + view_layer_input = NULL; + } + else { + view_layer_input = get_original_view_layer(depsgraph, id_node); + } ViewLayer *view_layer_eval = NULL; /* Find evaluated view layer. At the same time we free memory used by * all other of the view layers. */ @@ -349,24 +372,35 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph, view_layer_cow != NULL; view_layer_cow = view_layer_next) { view_layer_next = view_layer_cow->next; - if (STREQ(view_layer_input->name, view_layer_cow->name)) { + if (view_layer_input != NULL && STREQ(view_layer_input->name, view_layer_cow->name)) { view_layer_eval = view_layer_cow; } else { BKE_view_layer_free_ex(view_layer_cow, false); } } - BLI_assert(view_layer_eval != NULL); - /* Make evaluated view layer the only one in the evaluated scene. */ - view_layer_eval->prev = view_layer_eval->next = NULL; + /* Make evaluated view layer the only one in the evaluated scene (if it exists). */ + if (view_layer_eval != NULL) { + view_layer_eval->prev = view_layer_eval->next = NULL; + } scene_cow->view_layers.first = view_layer_eval; scene_cow->view_layers.last = view_layer_eval; } +void scene_remove_all_bases(Scene *scene_cow) +{ + LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) { + BLI_freelistN(&view_layer->object_bases); + } +} + /* Makes it so given view layer only has bases corresponding to enabled * objects. */ void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *view_layer) { + if (view_layer == NULL) { + return; + } ListBase enabled_bases = {NULL, NULL}; LISTBASE_FOREACH_MUTABLE (Base *, base, &view_layer->object_bases) { /* TODO(sergey): Would be cool to optimize this somehow, or make it so @@ -397,6 +431,10 @@ void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *vie void view_layer_update_orig_base_pointers(const ViewLayer *view_layer_orig, ViewLayer *view_layer_eval) { + if (view_layer_orig == NULL || view_layer_eval == NULL) { + /* Happens when scene is only used for parameters or compositor/sequencer. */ + return; + } Base *base_orig = reinterpret_cast<Base *>(view_layer_orig->object_bases.first); LISTBASE_FOREACH (Base *, base_eval, &view_layer_eval->object_bases) { base_eval->base_orig = base_orig; @@ -409,6 +447,11 @@ void scene_setup_view_layers_before_remap(const Depsgraph *depsgraph, Scene *scene_cow) { scene_remove_unused_view_layers(depsgraph, id_node, scene_cow); + /* If dependency graph is used for post-processing we don't need any bases and can free of them. + * Do it before re-mapping to make that process faster. */ + if (depsgraph->is_render_pipeline_depsgraph) { + scene_remove_all_bases(scene_cow); + } } void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph, @@ -821,7 +864,7 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph, /* Correct or tweak some pointers which are not taken care by foreach * from above. */ update_id_after_copy(depsgraph, id_node, id_orig, id_cow); - id_cow->recalc = id_orig->recalc | id_cow_recalc; + id_cow->recalc = id_cow_recalc; return id_cow; } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index 0bd5b3b4f82..6d8dcf2778f 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -234,10 +234,6 @@ void flush_editors_id_update(Depsgraph *graph, const DEGEditorUpdateContext *upd /* TODO(sergey): Do we need to pass original or evaluated ID here? */ ID *id_orig = id_node->id_orig; ID *id_cow = id_node->id_cow; - /* Copy tag from original data to CoW storage. - * This is because DEG_id_tag_update() sets tags on original - * data. */ - id_cow->recalc |= (id_orig->recalc & ID_RECALC_ALL); /* Gather recalc flags from all changed components. */ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { if (comp_node->custom_flags != COMPONENT_STATE_DONE) { diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c index aad92c9658a..a274eda84fe 100644 --- a/source/blender/draw/engines/basic/basic_engine.c +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -94,11 +94,6 @@ static void basic_cache_init(void *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); BASIC_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - const RegionView3D *rv3d = draw_ctx->rv3d; - - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } if (!stl->g_data) { /* Alloc transient pointers */ @@ -110,7 +105,7 @@ static void basic_cache_init(void *vedata) DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); stl->g_data->depth_shgrp = DRW_shgroup_create(sh_data->depth, psl->depth_pass); if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp, rv3d); + DRW_shgroup_state_enable(stl->g_data->depth_shgrp, DRW_STATE_CLIP_PLANES); } psl->depth_pass_cull = DRW_pass_create("Depth Pass Cull", @@ -118,7 +113,7 @@ static void basic_cache_init(void *vedata) DRW_STATE_CULL_BACK); stl->g_data->depth_shgrp_cull = DRW_shgroup_create(sh_data->depth, psl->depth_pass_cull); if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp_cull, rv3d); + DRW_shgroup_state_enable(stl->g_data->depth_shgrp_cull, DRW_STATE_CLIP_PLANES); } } } diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index b7b8702b41a..0ce271275d0 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -62,7 +62,6 @@ void EEVEE_view_layer_data_free(void *storage) DRW_UBO_FREE_SAFE(sldata->grid_ubo); DRW_UBO_FREE_SAFE(sldata->planar_ubo); DRW_UBO_FREE_SAFE(sldata->common_ubo); - DRW_UBO_FREE_SAFE(sldata->clip_ubo); } EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void) 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 ae8e7614302..c14f08857c3 100644 --- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c +++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c @@ -140,14 +140,7 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), float focus_dist = BKE_camera_object_dof_distance(camera); float focal_len = cam->lens; - /* this is factor that converts to the scene scale. focal length and sensor are expressed in - * mm unit.scale_length is how many meters per blender unit we have. We want to convert to - * blender units though because the shader reads coordinates in world space, which is in - * blender units. - * Note however that focus_distance is already in blender units and shall not be scaled here - * (see T48157). */ - float scale = (scene_eval->unit.system) ? scene_eval->unit.scale_length : 1.0f; - float scale_camera = 0.001f / scale; + const float scale_camera = 0.001f; /* we want radius here for the aperture number */ float aperture = 0.5f * scale_camera * focal_len / fstop; float focal_len_scaled = scale_camera * focal_len; diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 8a85c6671fd..8b176f8e5b2 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -175,16 +175,6 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, } /** - * Ping Pong buffer - */ - if ((effects->enabled_effects & EFFECT_POST_BUFFER) != 0) { - SETUP_BUFFER(txl->color_post, fbl->effect_fb, fbl->effect_color_fb); - } - else { - CLEANUP_BUFFER(txl->color_post, fbl->effect_fb, fbl->effect_color_fb); - } - - /** * MinMax Pyramid */ const bool half_res_hiz = true; @@ -360,6 +350,13 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_vec4(grp, "color2", effects->color_checker_light, 1); DRW_shgroup_uniform_int_copy(grp, "size", 8); DRW_shgroup_call(grp, quad, NULL); + + float mat[4][4]; + unit_m4(mat); + + /* Using default view bypasses the culling. */ + const DRWView *default_view = DRW_view_default_get(); + effects->checker_view = DRW_view_create_sub(default_view, mat, mat); } } @@ -378,6 +375,16 @@ void EEVEE_effects_draw_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *ve else { CLEANUP_BUFFER(txl->color_double_buffer, fbl->double_buffer_fb, fbl->double_buffer_color_fb); } + + /** + * Ping Pong buffer + */ + if ((effects->enabled_effects & EFFECT_POST_BUFFER) != 0) { + SETUP_BUFFER(txl->color_post, fbl->effect_fb, fbl->effect_color_fb); + } + else { + CLEANUP_BUFFER(txl->color_post, fbl->effect_fb, fbl->effect_color_fb); + } } #if 0 /* Not required for now */ @@ -515,16 +522,11 @@ void EEVEE_draw_alpha_checker(EEVEE_Data *vedata) EEVEE_EffectsInfo *effects = stl->effects; if ((effects->enabled_effects & EFFECT_ALPHA_CHECKER) != 0) { - float mat[4][4]; - unit_m4(mat); - - /* Fragile, rely on the fact that GPU_SHADER_2D_CHECKER - * only use the persmat. */ - DRW_viewport_matrix_override_set(mat, DRW_MAT_PERS); + DRW_view_set_active(effects->checker_view); DRW_draw_pass(psl->alpha_checker); - DRW_viewport_matrix_override_unset(DRW_MAT_PERS); + DRW_view_set_active(NULL); } } @@ -534,16 +536,17 @@ static void EEVEE_velocity_resolve(EEVEE_Data *vedata) EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; + struct DRWView *view = effects->taa_view; if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) { DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); e_data.depth_src = dtxl->depth; - DRW_viewport_matrix_get(effects->velocity_curr_persinv, DRW_MAT_PERSINV); + DRW_view_persmat_get(view, effects->velocity_curr_persinv, true); GPU_framebuffer_bind(fbl->velocity_resolve_fb); DRW_draw_pass(psl->velocity_resolve); } - DRW_viewport_matrix_get(effects->velocity_past_persmat, DRW_MAT_PERS); + DRW_view_persmat_get(view, effects->velocity_past_persmat, false); } void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) @@ -594,7 +597,7 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) } /* Record pers matrix for the next frame. */ - DRW_viewport_matrix_get(stl->effects->prev_persmat, DRW_MAT_PERS); + DRW_view_persmat_get(effects->taa_view, effects->prev_persmat, false); /* Update double buffer status if render mode. */ if (DRW_state_is_image_render()) { diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 481b566eff0..22f7b786330 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -79,20 +79,12 @@ static void eevee_engine_init(void *ved) sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data); } - if (sldata->clip_ubo == NULL) { - sldata->clip_ubo = DRW_uniformbuffer_create(sizeof(sldata->clip_data), &sldata->clip_data); - } /* EEVEE_effects_init needs to go first for TAA */ EEVEE_effects_init(sldata, vedata, camera, false); EEVEE_materials_init(sldata, stl, fbl); EEVEE_lights_init(sldata); EEVEE_lightprobes_init(sldata, vedata); - - if ((stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render()) { - /* XXX otherwise it would break the other engines. */ - DRW_viewport_matrix_override_unset_all(); - } } static void eevee_cache_init(void *vedata) @@ -214,15 +206,22 @@ static void eevee_draw_background(void *vedata) /* Copy previous persmat to UBO data */ copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat); + /* Refresh Probes */ + DRW_stats_group_start("Probes Refresh"); + EEVEE_lightprobes_refresh(sldata, vedata); + EEVEE_lightprobes_refresh_planar(sldata, vedata); + DRW_stats_group_end(); + + /* Refresh shadows */ + DRW_stats_group_start("Shadows"); + EEVEE_draw_shadows(sldata, vedata, stl->effects->taa_view); + DRW_stats_group_end(); + if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) && (stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render() && !taa_use_reprojection) { - DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS); - DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV); - DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN); - DRW_viewport_matrix_override_set(stl->effects->overide_wininv, DRW_MAT_WININV); + DRW_view_set_active(stl->effects->taa_view); } - /* when doing viewport rendering the overrides needs to be recalculated for * every loop as this normally happens once inside * `EEVEE_temporal_sampling_init` */ @@ -231,21 +230,6 @@ static void eevee_draw_background(void *vedata) EEVEE_temporal_sampling_update_matrices(vedata); } - /* Refresh Probes */ - DRW_stats_group_start("Probes Refresh"); - EEVEE_lightprobes_refresh(sldata, vedata); - /* Probes refresh can have reset the current sample. */ - if (stl->effects->taa_current_sample == 1) { - DRW_viewport_matrix_override_unset_all(); - } - EEVEE_lightprobes_refresh_planar(sldata, vedata); - DRW_stats_group_end(); - - /* Refresh shadows */ - DRW_stats_group_start("Shadows"); - EEVEE_draw_shadows(sldata, vedata); - DRW_stats_group_end(); - /* Set ray type. */ sldata->common_data.ray_type = EEVEE_RAY_CAMERA; sldata->common_data.ray_depth = 0.0f; @@ -309,9 +293,7 @@ static void eevee_draw_background(void *vedata) EEVEE_draw_effects(sldata, vedata); DRW_stats_group_end(); - if ((stl->effects->taa_current_sample > 1)) { - DRW_viewport_matrix_override_unset_all(); - } + DRW_view_set_active(NULL); } /* Tonemapping and transfer result to default framebuffer. */ @@ -391,7 +373,7 @@ static void eevee_id_object_update(void *UNUSED(vedata), Object *object) { EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object); if (ped != NULL && ped->dd.recalc != 0) { - ped->need_update = (ped->dd.recalc & (ID_RECALC_TRANSFORM | ID_RECALC_COPY_ON_WRITE)) != 0; + ped->need_update = (ped->dd.recalc & (ID_RECALC_TRANSFORM)) != 0; ped->dd.recalc = 0; } EEVEE_LightEngineData *led = EEVEE_light_data_get(object); diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index 3e0e5f6d00f..536ecb1bc42 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -717,16 +717,20 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb stl->g_data->background_alpha = 1.0f; /* XXX TODO remove this. This is in order to make the init functions work. */ - DRWMatrixState dummy_mats = {{{{{0}}}}}; - DRW_viewport_matrix_override_set_all(&dummy_mats); + if (DRW_view_default_get() == NULL) { + float winmat[4][4], viewmat[4][4]; + unit_m4(viewmat); + unit_m4(winmat); + negate_v3(winmat[2]); + DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL); + DRW_view_default_set(view); + DRW_view_set_active(view); + } if (sldata->common_ubo == NULL) { sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data); } - if (sldata->clip_ubo == NULL) { - sldata->clip_ubo = DRW_uniformbuffer_create(sizeof(sldata->clip_data), &sldata->clip_data); - } /* HACK: set txl->color but unset it before Draw Manager frees it. */ txl->color = lbake->rt_color; @@ -743,6 +747,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb EEVEE_effects_cache_init(sldata, vedata); EEVEE_materials_cache_init(sldata, vedata); + EEVEE_subsurface_cache_init(sldata, vedata); EEVEE_lights_cache_init(sldata, vedata); EEVEE_lightprobes_cache_init(sldata, vedata); diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index 92cd465f771..78565f9c465 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -167,6 +167,11 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) e_data.hammersley = create_hammersley_sample_texture(HAMMERSLEY_SIZE); } + memset(stl->g_data->bake_views, 0, sizeof(stl->g_data->bake_views)); + memset(stl->g_data->cube_views, 0, sizeof(stl->g_data->cube_views)); + memset(stl->g_data->world_views, 0, sizeof(stl->g_data->world_views)); + memset(stl->g_data->planar_views, 0, sizeof(stl->g_data->planar_views)); + /* Use fallback if we don't have gpu texture allocated an we cannot restore them. */ bool use_fallback_lightcache = (scene_eval->eevee.light_cache == NULL) || ((scene_eval->eevee.light_cache->grid_tx.tex == NULL) && @@ -463,7 +468,8 @@ static bool eevee_lightprobes_culling_test(Object *ob) for (int v = 0; v < 8; ++v) { mul_m4_v3(tmp, bbox.vec[v]); } - return DRW_culling_box_test(&bbox); + const DRWView *default_view = DRW_view_default_get(); + return DRW_culling_box_test(default_view, &bbox); } case LIGHTPROBE_TYPE_CUBE: return true; /* TODO */ @@ -487,6 +493,8 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata } if (probe->type == LIGHTPROBE_TYPE_PLANAR) { + /* TODO(fclem): Culling should be done after cache generation. + * This is needed for future draw cache persistence. */ if (!eevee_lightprobes_culling_test(ob)) { return; /* Culled */ } @@ -673,22 +681,35 @@ void EEVEE_lightprobes_planar_data_from_object(Object *ob, eplanar->attenuation_bias = max_dist * -eplanar->attenuation_scale; } -static void lightbake_planar_compute_render_matrices(EEVEE_PlanarReflection *eplanar, - DRWMatrixState *r_matstate, - const float viewmat[4][4], - const float winmat[4][4]) +static void lightbake_planar_ensure_view(EEVEE_PlanarReflection *eplanar, + const DRWView *main_view, + DRWView **r_planar_view) { + float winmat[4][4], viewmat[4][4]; + DRW_view_viewmat_get(main_view, viewmat, false); /* Temporal sampling jitter should be already applied to the DRW_MAT_WIN. */ - copy_m4_m4(r_matstate->winmat, winmat); + DRW_view_winmat_get(main_view, winmat, false); /* Invert X to avoid flipping the triangle facing direction. */ - r_matstate->winmat[0][0] = -r_matstate->winmat[0][0]; - r_matstate->winmat[1][0] = -r_matstate->winmat[1][0]; - r_matstate->winmat[2][0] = -r_matstate->winmat[2][0]; - r_matstate->winmat[3][0] = -r_matstate->winmat[3][0]; + winmat[0][0] = -winmat[0][0]; + winmat[1][0] = -winmat[1][0]; + winmat[2][0] = -winmat[2][0]; + winmat[3][0] = -winmat[3][0]; /* Reflect Camera Matrix. */ - mul_m4_m4m4(r_matstate->viewmat, viewmat, eplanar->mtx); - /* Apply Projection Matrix. */ - mul_m4_m4m4(r_matstate->persmat, r_matstate->winmat, r_matstate->viewmat); + mul_m4_m4m4(viewmat, viewmat, eplanar->mtx); + + if (*r_planar_view == NULL) { + *r_planar_view = DRW_view_create( + viewmat, winmat, NULL, NULL, EEVEE_lightprobes_obj_visibility_cb); + /* Compute offset plane equation (fix missing texels near reflection plane). */ + float clip_plane[4]; + copy_v4_v4(clip_plane, eplanar->plane_equation); + clip_plane[3] += eplanar->clipsta; + /* Set clipping plane */ + DRW_view_clip_planes_set(*r_planar_view, &clip_plane, 1); + } + else { + DRW_view_update(*r_planar_view, viewmat, winmat, NULL, NULL); + } } static void eevee_lightprobes_extract_from_cache(EEVEE_LightProbesInfo *pinfo, LightCache *lcache) @@ -756,7 +777,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved } } - if (pinfo->num_planar) { + if (pinfo->num_planar > 0) { EEVEE_PassList *psl = vedata->psl; EEVEE_TextureList *txl = vedata->txl; DRW_PASS_CREATE(psl->probe_planar_downsample_ps, DRW_STATE_WRITE_COLOR); @@ -783,32 +804,43 @@ typedef struct EEVEE_BakeRenderData { static void render_cubemap(void (*callback)(int face, EEVEE_BakeRenderData *user_data), EEVEE_BakeRenderData *user_data, const float pos[3], - float clipsta, - float clipend) + float near, + float far, + bool do_culling) { - DRWMatrixState matstate; + EEVEE_StorageList *stl = user_data->vedata->stl; + DRWView **views = do_culling ? stl->g_data->bake_views : stl->g_data->world_views; - /* Move to capture position */ - float posmat[4][4]; - unit_m4(posmat); - negate_v3_v3(posmat[3], pos); + float winmat[4][4], viewmat[4][4]; + perspective_m4(winmat, -near, near, -near, near, near, far); - perspective_m4(matstate.winmat, -clipsta, clipsta, -clipsta, clipsta, clipsta, clipend); - invert_m4_m4(matstate.wininv, matstate.winmat); + /* Prepare views at the same time for faster culling. */ + for (int i = 0; i < 6; i++) { + unit_m4(viewmat); + negate_v3_v3(viewmat[3], pos); + mul_m4_m4m4(viewmat, cubefacemat[i], viewmat); - /* 1 - Render to each cubeface individually. - * We do this instead of using geometry shader because a) it's faster, - * b) it's easier than fixing the nodetree shaders (for view dependent effects). */ - for (int i = 0; i < 6; ++i) { - /* Setup custom matrices */ - mul_m4_m4m4(matstate.viewmat, cubefacemat[i], posmat); - mul_m4_m4m4(matstate.persmat, matstate.winmat, matstate.viewmat); - invert_m4_m4(matstate.persinv, matstate.persmat); - invert_m4_m4(matstate.viewinv, matstate.viewmat); - invert_m4_m4(matstate.wininv, matstate.winmat); - - DRW_viewport_matrix_override_set_all(&matstate); + if (do_culling) { + if (views[i] == NULL) { + views[i] = DRW_view_create(viewmat, winmat, NULL, NULL, NULL); + } + else { + DRW_view_update(views[i], viewmat, winmat, NULL, NULL); + } + } + else { + if (views[i] == NULL) { + const DRWView *default_view = DRW_view_default_get(); + views[i] = DRW_view_create_sub(default_view, viewmat, winmat); + } + else { + DRW_view_update_sub(views[i], viewmat, winmat); + } + } + } + for (int i = 0; i < 6; ++i) { + DRW_view_set_active(views[i]); callback(i, user_data); } } @@ -818,21 +850,16 @@ static void render_reflections(void (*callback)(int face, EEVEE_BakeRenderData * EEVEE_PlanarReflection *planar_data, int ref_count) { - DRWMatrixState matstate; - - float original_viewmat[4][4], original_winmat[4][4]; - DRW_viewport_matrix_get(original_viewmat, DRW_MAT_VIEW); - DRW_viewport_matrix_get(original_winmat, DRW_MAT_WIN); - + EEVEE_StorageList *stl = user_data->vedata->stl; + DRWView *main_view = stl->effects->taa_view; + DRWView **views = stl->g_data->planar_views; + /* Prepare views at the same time for faster culling. */ for (int i = 0; i < ref_count; ++i) { - /* Setup custom matrices */ - lightbake_planar_compute_render_matrices( - planar_data + i, &matstate, original_viewmat, original_winmat); - invert_m4_m4(matstate.persinv, matstate.persmat); - invert_m4_m4(matstate.viewinv, matstate.viewmat); - invert_m4_m4(matstate.wininv, matstate.winmat); - DRW_viewport_matrix_override_set_all(&matstate); + lightbake_planar_ensure_view(&planar_data[i], main_view, &views[i]); + } + for (int i = 0; i < ref_count; ++i) { + DRW_view_set_active(views[i]); callback(i, user_data); } } @@ -858,17 +885,20 @@ void EEVEE_lightbake_render_world(EEVEE_ViewLayerData *UNUSED(sldata), .face_fb = face_fb, }; - render_cubemap(lightbake_render_world_face, &brdata, (float[3]){0.0f}, 1.0f, 10.0f); + render_cubemap(lightbake_render_world_face, &brdata, (float[3]){0.0f}, 1.0f, 10.0f, false); } static void lightbake_render_scene_face(int face, EEVEE_BakeRenderData *user_data) { EEVEE_ViewLayerData *sldata = user_data->sldata; EEVEE_PassList *psl = user_data->vedata->psl; + EEVEE_PrivateData *g_data = user_data->vedata->stl->g_data; + DRWView **views = g_data->bake_views; + struct GPUFrameBuffer **face_fb = user_data->face_fb; /* Be sure that cascaded shadow maps are updated. */ - EEVEE_draw_shadows(sldata, user_data->vedata); + EEVEE_draw_shadows(sldata, user_data->vedata, views[face]); GPU_framebuffer_bind(face_fb[face]); GPU_framebuffer_clear_depth(face_fb[face], 1.0f); @@ -897,7 +927,7 @@ void EEVEE_lightbake_render_scene(EEVEE_ViewLayerData *sldata, .face_fb = face_fb, }; - render_cubemap(lightbake_render_scene_face, &brdata, pos, near_clip, far_clip); + render_cubemap(lightbake_render_scene_face, &brdata, pos, near_clip, far_clip, true); } static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *user_data) @@ -906,9 +936,9 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us EEVEE_ViewLayerData *sldata = user_data->sldata; EEVEE_PassList *psl = vedata->psl; EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_LightProbesInfo *pinfo = sldata->probes; - EEVEE_PlanarReflection *eplanar = pinfo->planar_data + layer; GPU_framebuffer_ensure_config(&fbl->planarref_fb, {GPU_ATTACHMENT_TEXTURE_LAYER(txl->planar_depth, layer), @@ -924,18 +954,10 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us txl->planar_pool = e_data.planar_pool_placeholder; txl->planar_depth = e_data.depth_array_placeholder; - /* Be sure that cascaded shadow maps are updated. */ DRW_stats_group_start("Planar Reflection"); /* Be sure that cascaded shadow maps are updated. */ - EEVEE_draw_shadows(sldata, vedata); - - /* Compute offset plane equation (fix missing texels near reflection plane). */ - copy_v4_v4(sldata->clip_data.clip_planes[0], eplanar->plane_equation); - sldata->clip_data.clip_planes[0][3] += eplanar->clipsta; - /* Set clipping plane */ - DRW_uniformbuffer_update(sldata->clip_ubo, &sldata->clip_data); - DRW_state_clip_planes_len_set(1); + EEVEE_draw_shadows(sldata, vedata, stl->g_data->planar_views[layer]); GPU_framebuffer_bind(fbl->planarref_fb); GPU_framebuffer_clear_depth(fbl->planarref_fb, 1.0); @@ -972,8 +994,6 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us } DRW_draw_pass(psl->transparent_pass); - DRW_state_clip_planes_reset(); - DRW_stats_group_end(); /* Restore */ @@ -1033,7 +1053,7 @@ void EEVEE_lightbake_filter_glossy(EEVEE_ViewLayerData *sldata, /* 3 - Render to probe array to the specified layer, do prefiltering. */ int mipsize = GPU_texture_width(light_cache->cube_tx.tex); for (int i = 0; i < maxlevel + 1; i++) { - float bias = (i == 0) ? -1.0f : 1.0f; + float bias = 0.0f; pinfo->texel_size = 1.0f / (float)mipsize; pinfo->padding_size = (i == maxlevel) ? 0 : (float)(1 << (maxlevel - i - 1)); pinfo->padding_size *= pinfo->texel_size; @@ -1043,22 +1063,27 @@ void EEVEE_lightbake_filter_glossy(EEVEE_ViewLayerData *sldata, pinfo->roughness *= pinfo->roughness; /* Distribute Roughness accros lod more evenly */ CLAMP(pinfo->roughness, 1e-8f, 0.99999f); /* Avoid artifacts */ -#if 1 /* Variable Sample count (fast) */ +#if 1 /* Variable Sample count and bias (fast) */ switch (i) { case 0: pinfo->samples_len = 1.0f; + bias = -1.0f; break; case 1: - pinfo->samples_len = 16.0f; + pinfo->samples_len = 32.0f; + bias = 1.0f; break; case 2: - pinfo->samples_len = 32.0f; + pinfo->samples_len = 40.0f; + bias = 2.0f; break; case 3: pinfo->samples_len = 64.0f; + bias = 2.0f; break; default: pinfo->samples_len = 128.0f; + bias = 2.0f; break; } #else /* Constant Sample count (slow) */ @@ -1221,7 +1246,6 @@ void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *v { EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; EEVEE_LightProbesInfo *pinfo = sldata->probes; - DRWMatrixState saved_mats; if (pinfo->num_planar == 0) { /* Disable SSR if we cannot read previous frame */ @@ -1230,9 +1254,6 @@ void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *v return; } - /* We need to save the Matrices before overidding them */ - DRW_viewport_matrix_get_all(&saved_mats); - /* Temporary Remove all planar reflections (avoid lag effect). */ common_data->prb_num_planar = 0; /* Turn off ssr to avoid black specular */ @@ -1261,8 +1282,6 @@ void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *v EEVEE_lightbake_filter_planar(vedata); } - DRW_viewport_matrix_override_set_all(&saved_mats); - if (DRW_state_is_image_render()) { /* Sort transparents because planar reflections could have re-sorted them. */ DRW_pass_sort_shgroup_z(vedata->psl->transparent_pass); @@ -1280,10 +1299,7 @@ void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) if ((light_cache->flag & LIGHTCACHE_UPDATE_WORLD) && (light_cache->flag & LIGHTCACHE_BAKED) == 0) { - DRWMatrixState saved_mats; - DRW_viewport_matrix_get_all(&saved_mats); EEVEE_lightbake_update_world_quick(sldata, vedata, scene_eval); - DRW_viewport_matrix_override_set_all(&saved_mats); } } diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 7106cf0249e..e966fadbcdb 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -970,7 +970,7 @@ static void frustum_min_bounding_sphere(const float corners[8][3], static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LightsInfo *linfo, EEVEE_LightEngineData *led, - DRWMatrixState *saved_mats, + DRWView *view, float view_near, float view_far, int sample_ofs) @@ -978,9 +978,10 @@ static void eevee_shadow_cascade_setup(Object *ob, Light *la = (Light *)ob->data; /* Camera Matrices */ - float(*persinv)[4] = saved_mats->mat[DRW_MAT_PERSINV]; - float(*vp_projmat)[4] = saved_mats->mat[DRW_MAT_WIN]; - bool is_persp = DRW_viewport_is_persp_get(); + float persinv[4][4], vp_projmat[4][4]; + DRW_view_persmat_get(view, persinv, true); + DRW_view_winmat_get(view, vp_projmat, false); + bool is_persp = DRW_view_is_persp_get(view); /* Lights Matrices */ int cascade_nbr = la->cascade_count; @@ -1286,19 +1287,52 @@ void EEVEE_lights_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } } +static void eevee_ensure_cube_views(float near, float far, const float pos[3], DRWView *view[6]) +{ + float winmat[4][4], viewmat[4][4]; + perspective_m4(winmat, -near, near, -near, near, near, far); + + for (int i = 0; i < 6; i++) { + unit_m4(viewmat); + negate_v3_v3(viewmat[3], pos); + mul_m4_m4m4(viewmat, cubefacemat[i], viewmat); + + if (view[i] == NULL) { + view[i] = DRW_view_create(viewmat, winmat, NULL, NULL, NULL); + } + else { + DRW_view_update(view[i], viewmat, winmat, NULL, NULL); + } + } +} + +static void eevee_ensure_cascade_views(EEVEE_ShadowCascadeData *cascade_data, + int cascade_count, + DRWView *view[4]) +{ + for (int i = 0; i < cascade_count; i++) { + if (view[i] == NULL) { + view[i] = DRW_view_create(cascade_data->viewmat, cascade_data->projmat[i], NULL, NULL, NULL); + } + else { + DRW_view_update(view[i], cascade_data->viewmat, cascade_data->projmat[i], NULL, NULL); + } + } +} + /* this refresh lights shadow buffers */ -void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWView *view) { EEVEE_PassList *psl = vedata->psl; EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_PrivateData *g_data = stl->g_data; EEVEE_LightsInfo *linfo = sldata->lights; const DRWContextState *draw_ctx = DRW_context_state_get(); const float light_threshold = draw_ctx->scene->eevee.light_threshold; Object *ob; int i; - DRWMatrixState saved_mats; int saved_ray_type = sldata->common_data.ray_type; /* TODO: make it optionnal if we don't draw shadows. */ @@ -1313,8 +1347,9 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) .center = {ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2]}, .radius = light_attenuation_radius_get(la, light_threshold), }; - cube_visible[i] = DRW_culling_sphere_test(&bsphere); + cube_visible[i] = DRW_culling_sphere_test(view, &bsphere); } + bool cascade_visible[MAX_SHADOW_CASCADE]; for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) { EEVEE_LightEngineData *led = EEVEE_light_data_get(ob); @@ -1325,12 +1360,9 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) plane_from_point_normal_v3(plane, sh_data->viewmat[3], sh_data->viewmat[2]); /* TODO: check against near/far instead of "local Z = 0" plane. * Or even the cascades AABB. */ - cascade_visible[i] = DRW_culling_plane_test(plane); + cascade_visible[i] = DRW_culling_plane_test(view, plane); } - /* We need to save the Matrices before overidding them */ - DRW_viewport_matrix_get_all(&saved_mats); - /* Cube Shadow Maps */ DRW_stats_group_start("Cube Shadow Maps"); /* Render each shadow to one layer of the array */ @@ -1342,11 +1374,6 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) continue; } - DRWMatrixState render_mats; - float(*winmat)[4] = render_mats.mat[DRW_MAT_WIN]; - float(*viewmat)[4] = render_mats.mat[DRW_MAT_VIEW]; - float(*persmat)[4] = render_mats.mat[DRW_MAT_PERS]; - EEVEE_ShadowRender *srd = &linfo->shadow_render_data; EEVEE_ShadowCubeData *evscd = &led->data.scd; EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + evscd->cube_id; @@ -1357,32 +1384,16 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) srd->exponent = la->bleedexp; copy_v3_v3(srd->position, cube_data->position); - perspective_m4(winmat, - -srd->clip_near, - srd->clip_near, - -srd->clip_near, - srd->clip_near, - srd->clip_near, - srd->clip_far); - DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd); + eevee_ensure_cube_views(srd->clip_near, srd->clip_far, srd->position, g_data->cube_views); + /* Render shadow cube */ /* Render 6 faces separately: seems to be faster for the general case. * The only time it's more beneficial is when the CPU culling overhead * outweigh the instancing overhead. which is rarely the case. */ for (int j = 0; j < 6; j++) { - /* TODO optimize */ - float tmp[4][4]; - unit_m4(tmp); - negate_v3_v3(tmp[3], srd->position); - mul_m4_m4m4(viewmat, cubefacemat[j], tmp); - mul_m4_m4m4(persmat, winmat, viewmat); - invert_m4_m4(render_mats.mat[DRW_MAT_WININV], winmat); - invert_m4_m4(render_mats.mat[DRW_MAT_VIEWINV], viewmat); - invert_m4_m4(render_mats.mat[DRW_MAT_PERSINV], persmat); - - DRW_viewport_matrix_override_set_all(&render_mats); + DRW_view_set_active(g_data->cube_views[j]); GPU_framebuffer_texture_cubeface_attach( sldata->shadow_cube_target_fb, sldata->shadow_cube_target, 0, j, 0); @@ -1448,9 +1459,8 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) linfo->update_flag &= ~LIGHT_UPDATE_SHADOW_CUBE; DRW_stats_group_end(); - DRW_viewport_matrix_override_set_all(&saved_mats); - float near = DRW_viewport_near_distance_get(); - float far = DRW_viewport_far_distance_get(); + float near = DRW_view_near_distance_get(view); + float far = DRW_view_far_distance_get(view); /* Cascaded Shadow Maps */ DRW_stats_group_start("Cascaded Shadow Maps"); @@ -1465,34 +1475,24 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) EEVEE_ShadowCascadeData *evscd = &led->data.scad; EEVEE_ShadowRender *srd = &linfo->shadow_render_data; - DRWMatrixState render_mats; - float(*winmat)[4] = render_mats.mat[DRW_MAT_WIN]; - float(*viewmat)[4] = render_mats.mat[DRW_MAT_VIEW]; - float(*persmat)[4] = render_mats.mat[DRW_MAT_PERS]; - - eevee_shadow_cascade_setup( - ob, linfo, led, &saved_mats, near, far, effects->taa_current_sample - 1); - srd->clip_near = la->clipsta; srd->clip_far = la->clipend; srd->stored_texel_size = 1.0 / (float)linfo->shadow_cascade_size; DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data); - copy_m4_m4(viewmat, evscd->viewmat); - invert_m4_m4(render_mats.mat[DRW_MAT_VIEWINV], viewmat); + eevee_shadow_cascade_setup(ob, linfo, led, view, near, far, effects->taa_current_sample - 1); + + /* Meh, Reusing the cube views. */ + BLI_assert(MAX_CASCADE_NUM <= 6); + eevee_ensure_cascade_views(evscd, la->cascade_count, g_data->cube_views); /* Render shadow cascades */ /* Render cascade separately: seems to be faster for the general case. * The only time it's more beneficial is when the CPU culling overhead * outweigh the instancing overhead. which is rarely the case. */ for (int j = 0; j < la->cascade_count; j++) { - copy_m4_m4(winmat, evscd->projmat[j]); - copy_m4_m4(persmat, evscd->viewprojmat[j]); - invert_m4_m4(render_mats.mat[DRW_MAT_WININV], winmat); - invert_m4_m4(render_mats.mat[DRW_MAT_PERSINV], persmat); - - DRW_viewport_matrix_override_set_all(&render_mats); + DRW_view_set_active(g_data->cube_views[j]); GPU_framebuffer_texture_layer_attach( sldata->shadow_cascade_target_fb, sldata->shadow_cascade_target, 0, j, 0); @@ -1554,7 +1554,7 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_stats_group_end(); - DRW_viewport_matrix_override_set_all(&saved_mats); + DRW_view_set_active(view); DRW_uniformbuffer_update(sldata->light_ubo, &linfo->light_data); DRW_uniformbuffer_update(sldata->shadow_ubo, &linfo->shadow_data); /* Update all data at once */ diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index bd786c06e69..a998bd3a71b 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -223,20 +223,28 @@ void EEVEE_lookdev_draw(EEVEE_Data *vedata) DRW_uniformbuffer_update(sldata->common_ubo, common); /* override matrices */ - DRWMatrixState matstate; - unit_m4(matstate.winmat); + float winmat[4][4], viewmat[4][4]; + unit_m4(winmat); + /* Look through the negative Z. */ + negate_v3(winmat[2]); - eevee_lookdev_apply_taa(effects, effects->sphere_size, matstate.winmat); + eevee_lookdev_apply_taa(effects, effects->sphere_size, winmat); /* "Remove" view matrix location. Leaving only rotation. */ - DRW_viewport_matrix_get(matstate.viewmat, DRW_MAT_VIEW); - zero_v3(matstate.viewmat[3]); - mul_m4_m4m4(matstate.persmat, matstate.winmat, matstate.viewmat); - invert_m4_m4(matstate.wininv, matstate.winmat); - invert_m4_m4(matstate.viewinv, matstate.viewmat); - invert_m4_m4(matstate.persinv, matstate.persmat); + DRW_view_viewmat_get(NULL, viewmat, false); + zero_v3(viewmat[3]); - DRW_viewport_matrix_override_set_all(&matstate); + if (effects->lookdev_view) { + /* When rendering just update the view. This avoids recomputing the culling. */ + DRW_view_update_sub(effects->lookdev_view, viewmat, winmat); + } + else { + /* Using default view bypasses the culling. */ + const DRWView *default_view = DRW_view_default_get(); + effects->lookdev_view = DRW_view_create_sub(default_view, viewmat, winmat); + } + + DRW_view_set_active(effects->lookdev_view); /* Find the right framebuffers to render to. */ GPUFrameBuffer *fb = (effects->target_buffer == fbl->effect_color_fb) ? fbl->main_fb : @@ -270,6 +278,6 @@ void EEVEE_lookdev_draw(EEVEE_Data *vedata) DRW_stats_group_end(); - DRW_viewport_matrix_override_unset_all(); + DRW_view_set_active(NULL); } } diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 44e9b98e8e2..456f312f1df 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -386,7 +386,6 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp, DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo); DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block(shgrp, "clip_block", sldata->clip_ubo); if (use_diffuse || use_glossy || use_refract) { DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); @@ -599,8 +598,11 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, 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_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl, + NULL, + datatoc_default_world_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); char *vert_str = BLI_string_joinN( datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_prepass_vert_glsl); @@ -642,8 +644,8 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, { /* Update view_vecs */ float invproj[4][4], winmat[4][4]; - DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); - DRW_viewport_matrix_get(invproj, DRW_MAT_WININV); + DRW_view_winmat_get(NULL, winmat, false); + DRW_view_winmat_get(NULL, invproj, true); EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs); } @@ -1024,14 +1026,12 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_PASS_CREATE(psl->depth_pass_clip, state); stl->g_data->depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->depth_pass_clip); - DRW_shgroup_uniform_block(stl->g_data->depth_shgrp_clip, "clip_block", sldata->clip_ubo); state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_CULL_BACK; DRW_PASS_CREATE(psl->depth_pass_clip_cull, state); stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->depth_pass_clip_cull); - DRW_shgroup_uniform_block(stl->g_data->depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo); } { @@ -1055,16 +1055,12 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_PASS_CREATE(psl->refract_depth_pass_clip, state); stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip); - DRW_shgroup_uniform_block( - stl->g_data->refract_depth_shgrp_clip, "clip_block", sldata->clip_ubo); state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | DRW_STATE_CULL_BACK; DRW_PASS_CREATE(psl->refract_depth_pass_clip_cull, state); stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create( e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull); - DRW_shgroup_uniform_block( - stl->g_data->refract_depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo); } { @@ -1130,11 +1126,10 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) #define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \ do { \ if (oedata) { \ - DRW_shgroup_call_object_with_callback( \ - shgrp, geom, ob, EEVEE_lightprobes_obj_visibility_cb, oedata); \ + DRW_shgroup_call_object_with_callback(shgrp, geom, ob, oedata); \ } \ else { \ - DRW_shgroup_call_object_ex(shgrp, geom, ob, false); \ + DRW_shgroup_call_object(shgrp, geom, ob); \ } \ } while (0) @@ -1510,7 +1505,6 @@ static void material_transparent(Material *ma, /* Depth prepass */ if (use_prepass) { *shgrp_depth = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass); - DRW_shgroup_uniform_block(*shgrp_depth, "clip_block", sldata->clip_ubo); cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; @@ -1748,7 +1742,6 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata, shgrp = DRW_shgroup_hair_create( ob, psys, md, psl->depth_pass_clip, e_data.default_hair_prepass_clip_sh); - DRW_shgroup_uniform_block(shgrp, "clip_block", sldata->clip_ubo); shgrp = NULL; if (ma->use_nodes && ma->nodetree) { diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index ad4f72d78dc..abd5bb82815 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -127,7 +127,7 @@ int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda /* Viewport Matrix */ /* Note: This does not have TAA jitter applied. */ - DRW_viewport_matrix_get(persmat, DRW_MAT_PERS); + DRW_view_persmat_get(NULL, persmat, false); bool view_is_valid = (stl->g_data->view_updated == false); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index e2130615b1d..2e652dff232 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -571,10 +571,7 @@ typedef struct EEVEE_EffectsInfo { float taa_alpha; bool prev_drw_support; float prev_drw_persmat[4][4]; - float overide_persmat[4][4]; - float overide_persinv[4][4]; - float overide_winmat[4][4]; - float overide_wininv[4][4]; + struct DRWView *taa_view; /* Ambient Occlusion */ int ao_depth_layer; struct GPUTexture *ao_src_depth; /* pointer copy */ @@ -604,11 +601,13 @@ typedef struct EEVEE_EffectsInfo { /* Alpha Checker */ float color_checker_dark[4]; float color_checker_light[4]; + struct DRWView *checker_view; /* Other */ float prev_persmat[4][4]; /* Lookdev */ int sphere_size; int anchor[2]; + struct DRWView *lookdev_view; /* Bloom */ int bloom_iteration_len; float source_texel_size[2]; @@ -694,12 +693,6 @@ typedef struct EEVEE_CommonUniformBuffer { #define EEVEE_RAY_DIFFUSE 2 #define EEVEE_RAY_GLOSSY 3 -/* ***************** CLIP PLANES DATA **************** */ - -typedef struct EEVEE_ClipPlanesUniformBuffer { - float clip_planes[1][4]; /* must be less than MAX_CLIP_PLANES */ -} EEVEE_ClipPlanesUniformBuffer; - /* ************** SCENE LAYER DATA ************** */ typedef struct EEVEE_ViewLayerData { /* Lights */ @@ -735,9 +728,6 @@ typedef struct EEVEE_ViewLayerData { struct EEVEE_CommonUniformBuffer common_data; struct GPUUniformBuffer *common_ubo; - struct EEVEE_ClipPlanesUniformBuffer clip_data; - struct GPUUniformBuffer *clip_ubo; - struct LightCache *fallback_lightcache; } EEVEE_ViewLayerData; @@ -754,7 +744,7 @@ typedef struct EEVEE_ShadowCubeData { typedef struct EEVEE_ShadowCascadeData { short light_id, shadow_id, cascade_id, layer_id; /* World->Light->NDC : used for rendering the shadow map. */ - float viewprojmat[MAX_CASCADE_NUM][4][4]; + float viewprojmat[MAX_CASCADE_NUM][4][4]; /* Could be removed. */ float projmat[MAX_CASCADE_NUM][4][4]; float viewmat[4][4], viewinv[4][4]; float radius[MAX_CASCADE_NUM]; @@ -829,9 +819,6 @@ typedef struct EEVEE_PrivateData { bool valid_double_buffer; bool valid_taa_history; /* Render Matrices */ - float persmat[4][4], persinv[4][4]; - float viewmat[4][4], viewinv[4][4]; - float winmat[4][4], wininv[4][4]; float studiolight_matrix[3][3]; float overscan, overscan_pixels; float size_orig[2]; @@ -849,6 +836,14 @@ typedef struct EEVEE_PrivateData { float studiolight_glossy_clamp; float studiolight_filter_quality; + /** For rendering shadows. */ + struct DRWView *cube_views[6]; + /** For rendering probes. */ + struct DRWView *bake_views[6]; + /** Same as bake_views but does not generate culling infos. */ + struct DRWView *world_views[6]; + /** For rendering planar reflections. */ + struct DRWView *planar_views[MAX_PLANAR]; } EEVEE_PrivateData; /* Transient data */ /* eevee_data.c */ @@ -919,7 +914,7 @@ void EEVEE_lights_cache_shcaster_material_add(EEVEE_ViewLayerData *sldata, void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, struct Object *ob); void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_lights_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); -void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct DRWView *view); void EEVEE_lights_free(void); /* eevee_shaders.c */ @@ -1055,10 +1050,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata void EEVEE_temporal_sampling_offset_calc(const double ht_point[2], const float filter_size, float r_offset[2]); -void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, - float viewmat[4][4], - float persmat[4][4], - const double ht_point[2]); +void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, const double ht_point[2]); void EEVEE_temporal_sampling_update_matrices(EEVEE_Data *vedata); void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 8e3857ae8a8..2afd0b1d313 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -53,6 +53,8 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); Scene *scene = DEG_get_evaluated_scene(depsgraph); const float *size_orig = DRW_viewport_size_get(); + float size_final[2]; + float camtexcofac[4]; /* Init default FB and render targets: * In render mode the default framebuffer is not generated @@ -73,10 +75,20 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * if (scene->eevee.flag & SCE_EEVEE_OVERSCAN) { g_data->overscan = scene->eevee.overscan / 100.0f; g_data->overscan_pixels = roundf(max_ff(size_orig[0], size_orig[1]) * g_data->overscan); + + madd_v2_v2v2fl(size_final, size_orig, (float[2]){2.0f, 2.0f}, g_data->overscan_pixels); + + camtexcofac[0] = size_final[0] / size_orig[0]; + camtexcofac[1] = size_final[1] / size_orig[1]; + + camtexcofac[2] = -camtexcofac[0] * g_data->overscan_pixels / size_final[0]; + camtexcofac[3] = -camtexcofac[1] * g_data->overscan_pixels / size_final[1]; } else { + copy_v2_v2(size_final, size_orig); g_data->overscan = 0.0f; g_data->overscan_pixels = 0.0f; + copy_v4_fl4(camtexcofac, 1.0f, 1.0f, 0.0f, 0.0f); } /* XXX overiding viewport size. Simplify things but is not really 100% safe. */ @@ -100,30 +112,23 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data); } - if (sldata->clip_ubo == NULL) { - sldata->clip_ubo = DRW_uniformbuffer_create(sizeof(sldata->clip_data), &sldata->clip_data); - } /* Set the pers & view matrix. */ + float winmat[4][4], viewmat[4][4], viewinv[4][4]; /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */ struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); float frame = BKE_scene_frame_get(scene); - RE_GetCameraWindow(engine->re, ob_camera_eval, frame, g_data->winmat); - RE_GetCameraModelMatrix(engine->re, ob_camera_eval, g_data->viewinv); - RE_GetCameraWindowWithOverscan(engine->re, g_data->winmat, g_data->overscan); + RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat); + RE_GetCameraWindowWithOverscan(engine->re, winmat, g_data->overscan); + RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv); - invert_m4_m4(g_data->viewmat, g_data->viewinv); - mul_m4_m4m4(g_data->persmat, g_data->winmat, g_data->viewmat); - invert_m4_m4(g_data->persinv, g_data->persmat); - invert_m4_m4(g_data->wininv, g_data->winmat); + invert_m4_m4(viewmat, viewinv); - DRW_viewport_matrix_override_set(g_data->persmat, DRW_MAT_PERS); - DRW_viewport_matrix_override_set(g_data->persinv, DRW_MAT_PERSINV); - DRW_viewport_matrix_override_set(g_data->winmat, DRW_MAT_WIN); - DRW_viewport_matrix_override_set(g_data->wininv, DRW_MAT_WININV); - DRW_viewport_matrix_override_set(g_data->viewmat, DRW_MAT_VIEW); - DRW_viewport_matrix_override_set(g_data->viewinv, DRW_MAT_VIEWINV); + DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL); + DRW_view_camtexco_set(view, camtexcofac); + DRW_view_default_set(view); + DRW_view_set_active(view); /* EEVEE_effects_init needs to go first for TAA */ EEVEE_effects_init(sldata, vedata, ob_camera_eval, false); @@ -304,6 +309,9 @@ static void eevee_render_result_normal(RenderLayer *rl, 1, rp->rect); + float viewinv[4][4]; + DRW_view_viewmat_get(NULL, viewinv, true); + /* Convert Eevee encoded normals to Blender normals. */ for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) { if (rp->rect[i] == 0.0f && rp->rect[i + 1] == 0.0f) { @@ -322,7 +330,7 @@ static void eevee_render_result_normal(RenderLayer *rl, rp->rect[i + 1] = fenc[1] * g; rp->rect[i + 2] = 1.0f - f / 2.0f; - mul_mat3_m4_v3(g_data->viewinv, &rp->rect[i]); + mul_mat3_m4_v3(viewinv, &rp->rect[i]); } } } @@ -355,7 +363,10 @@ static void eevee_render_result_z(RenderLayer *rl, BLI_rcti_size_y(rect), rp->rect); - bool is_persp = DRW_viewport_is_persp_get(); + bool is_persp = DRW_view_is_persp_get(NULL); + + float winmat[4][4]; + DRW_view_winmat_get(NULL, winmat, false); /* Convert ogl depth [0..1] to view Z [near..far] */ for (int i = 0; i < rp->rectx * rp->recty; ++i) { @@ -365,7 +376,7 @@ static void eevee_render_result_z(RenderLayer *rl, else { if (is_persp) { rp->rect[i] = rp->rect[i] * 2.0f - 1.0f; - rp->rect[i] = g_data->winmat[3][2] / (rp->rect[i] + g_data->winmat[2][2]); + rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]); } else { rp->rect[i] = -common_data->view_vecs[0][2] + @@ -533,25 +544,15 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl double offset[3] = {0.0, 0.0, 0.0}; double r[3]; - /* Restore winmat before jittering again. */ - copy_m4_m4(stl->effects->overide_winmat, g_data->winmat); /* Copy previous persmat to UBO data */ copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat); BLI_halton_3d(primes, offset, stl->effects->taa_current_sample, r); EEVEE_update_noise(psl, fbl, r); - EEVEE_temporal_sampling_matrices_calc(stl->effects, g_data->viewmat, g_data->persmat, r); + EEVEE_temporal_sampling_matrices_calc(stl->effects, r); EEVEE_volumes_set_jitter(sldata, stl->effects->taa_current_sample - 1); EEVEE_materials_init(sldata, stl, fbl); - /* Set matrices. */ - DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS); - DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV); - DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN); - DRW_viewport_matrix_override_set(stl->effects->overide_wininv, DRW_MAT_WININV); - DRW_viewport_matrix_override_set(g_data->viewmat, DRW_MAT_VIEW); - DRW_viewport_matrix_override_set(g_data->viewinv, DRW_MAT_VIEWINV); - /* Refresh Probes */ EEVEE_lightprobes_refresh(sldata, vedata); EEVEE_lightprobes_refresh_planar(sldata, vedata); @@ -566,7 +567,10 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl /* Refresh Shadows */ EEVEE_lights_update(sldata, vedata); - EEVEE_draw_shadows(sldata, vedata); + EEVEE_draw_shadows(sldata, vedata, stl->effects->taa_view); + + /* Set matrices. */ + DRW_view_set_active(stl->effects->taa_view); /* Set ray type. */ sldata->common_data.ray_type = EEVEE_RAY_CAMERA; diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index ca6c9cdbe94..33a8383fe90 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -127,7 +127,7 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) &fbl->refract_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->refract_color)}); } - const bool is_persp = DRW_viewport_is_persp_get(); + const bool is_persp = DRW_view_is_persp_get(NULL); if (effects->ssr_was_persp != is_persp) { effects->ssr_was_persp = is_persp; DRW_viewport_request_redraw(); diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c index dbb43e16385..34a3e723161 100644 --- a/source/blender/draw/engines/eevee/eevee_shaders.c +++ b/source/blender/draw/engines/eevee/eevee_shaders.c @@ -110,8 +110,11 @@ void EEVEE_shaders_lightprobe_shaders_init(void) e_data.probe_filter_glossy_sh = DRW_shader_create( datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, shader_str, filter_defines); - e_data.probe_default_sh = DRW_shader_create( - datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, NULL); + e_data.probe_default_sh = DRW_shader_create_with_lib(datatoc_background_vert_glsl, + NULL, + datatoc_default_world_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); MEM_freeN(shader_str); @@ -178,8 +181,12 @@ GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void) GPUShader *EEVEE_shaders_default_studiolight_sh_get(void) { if (e_data.probe_default_studiolight_sh == NULL) { - e_data.probe_default_studiolight_sh = DRW_shader_create( - datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, "#define LOOKDEV\n"); + e_data.probe_default_studiolight_sh = DRW_shader_create_with_lib( + datatoc_background_vert_glsl, + NULL, + datatoc_default_world_frag_glsl, + datatoc_common_view_lib_glsl, + "#define LOOKDEV\n"); } return e_data.probe_default_studiolight_sh; } diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index a488e16093a..099147a82dd 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -139,25 +139,27 @@ void EEVEE_temporal_sampling_offset_calc(const double ht_point[2], r_offset[1] = eval_table(e_data.inverted_cdf, (float)(ht_point[1])) * filter_size; } -void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, - float viewmat[4][4], - float persmat[4][4], - const double ht_point[2]) +void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, const double ht_point[2]) { const float *viewport_size = DRW_viewport_size_get(); const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; RenderData *rd = &scene->r; + float persmat[4][4], viewmat[4][4], winmat[4][4]; + DRW_view_persmat_get(NULL, persmat, false); + DRW_view_viewmat_get(NULL, viewmat, false); + DRW_view_winmat_get(NULL, winmat, false); + float ofs[2]; EEVEE_temporal_sampling_offset_calc(ht_point, rd->gauss, ofs); - window_translate_m4( - effects->overide_winmat, persmat, ofs[0] / viewport_size[0], ofs[1] / viewport_size[1]); + window_translate_m4(winmat, persmat, ofs[0] / viewport_size[0], ofs[1] / viewport_size[1]); + + BLI_assert(effects->taa_view != NULL); - mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat); - invert_m4_m4(effects->overide_persinv, effects->overide_persmat); - invert_m4_m4(effects->overide_wininv, effects->overide_winmat); + /* When rendering just update the view. This avoids recomputing the culling. */ + DRW_view_update_sub(effects->taa_view, viewmat, winmat); } /* Update the matrices based on the current sample. @@ -167,23 +169,15 @@ void EEVEE_temporal_sampling_update_matrices(EEVEE_Data *vedata) EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; EEVEE_EffectsInfo *effects = stl->effects; - float persmat[4][4], viewmat[4][4]; double ht_point[2]; double ht_offset[2] = {0.0, 0.0}; uint ht_primes[2] = {2, 3}; - DRW_viewport_matrix_get(persmat, DRW_MAT_PERS); - DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); - DRW_viewport_matrix_get(effects->overide_winmat, DRW_MAT_WIN); - BLI_halton_2d(ht_primes, ht_offset, effects->taa_current_sample - 1, ht_point); - EEVEE_temporal_sampling_matrices_calc(effects, viewmat, persmat, ht_point); + EEVEE_temporal_sampling_matrices_calc(effects, ht_point); - DRW_viewport_matrix_override_set(effects->overide_persmat, DRW_MAT_PERS); - DRW_viewport_matrix_override_set(effects->overide_persinv, DRW_MAT_PERSINV); - DRW_viewport_matrix_override_set(effects->overide_winmat, DRW_MAT_WIN); - DRW_viewport_matrix_override_set(effects->overide_wininv, DRW_MAT_WININV); + DRW_view_set_active(effects->taa_view); } void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata) @@ -195,8 +189,6 @@ void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata) int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) { EEVEE_StorageList *stl = vedata->stl; - // EEVEE_FramebufferList *fbl = vedata->fbl; - // EEVEE_TextureList *txl = vedata->txl; EEVEE_EffectsInfo *effects = stl->effects; int repro_flag = 0; @@ -204,17 +196,26 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data eevee_create_cdf_table_temporal_sampling(); } - /* Reset for each "redraw". When rendering using ogl render, + /** + * Reset for each "redraw". When rendering using ogl render, * we accumulate the redraw inside the drawing loop in eevee_draw_background(). - * But we do NOT accumulate between "redraw" (as in full draw manager drawloop) - * because the opengl render already does that. */ + **/ effects->taa_render_sample = 1; + effects->taa_view = NULL; + + /* Create a sub view to disable clipping planes (if any). */ + const DRWView *default_view = DRW_view_default_get(); + float viewmat[4][4], winmat[4][4]; + DRW_view_viewmat_get(default_view, viewmat, false); + DRW_view_winmat_get(default_view, winmat, false); + effects->taa_view = DRW_view_create_sub(default_view, viewmat, winmat); + DRW_view_clip_planes_set(effects->taa_view, NULL, 0); const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); if ((scene_eval->eevee.taa_samples != 1) || DRW_state_is_image_render()) { - float persmat[4][4], viewmat[4][4]; + float persmat[4][4]; if (!DRW_state_is_image_render() && (scene_eval->eevee.flag & SCE_EEVEE_TAA_REPROJECTION)) { repro_flag = EFFECT_TAA_REPROJECT | EFFECT_VELOCITY_BUFFER | EFFECT_DEPTH_DOUBLE_BUFFER | @@ -236,8 +237,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data effects->taa_total_sample = scene_eval->eevee.taa_samples; MAX2(effects->taa_total_sample, 0); - DRW_viewport_matrix_get(persmat, DRW_MAT_PERS); - DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); + DRW_view_persmat_get(NULL, persmat, false); view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN); copy_m4_m4(effects->prev_drw_persmat, persmat); diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 9a59b95b2e8..61277628859 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -221,7 +221,7 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) current_sample = effects->taa_current_sample - 1; effects->volume_current_sample = -1; } - else { + else if (DRW_state_is_image_render()) { const uint max_sample = (ht_primes[0] * ht_primes[1] * ht_primes[2]); current_sample = effects->volume_current_sample = (effects->volume_current_sample + 1) % max_sample; @@ -242,11 +242,11 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* Update view_vecs */ float invproj[4][4], winmat[4][4]; - DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); - DRW_viewport_matrix_get(invproj, DRW_MAT_WININV); + DRW_view_winmat_get(NULL, winmat, false); + DRW_view_winmat_get(NULL, invproj, true); EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs); - if (DRW_viewport_is_persp_get()) { + if (DRW_view_is_persp_get(NULL)) { float sample_distribution = scene_eval->eevee.volumetric_sample_distribution; sample_distribution = 4.0f * (1.00001f - sample_distribution); diff --git a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl index 0be2a8d6a12..70466479a29 100644 --- a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl @@ -5,9 +5,6 @@ uniform vec3 color; out vec4 FragColor; #ifdef LOOKDEV -uniform mat4 ProjectionMatrix; -uniform mat4 ProjectionMatrixInverse; -uniform mat4 ViewMatrixInverse; uniform mat3 StudioLightMatrix; uniform sampler2D image; uniform float studioLightBackground = 1.0; 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 2b9a325e313..cf20b3ff5b9 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl @@ -7,13 +7,6 @@ in vec3 nor; out vec3 worldPosition; out vec3 viewPosition; -/* Used for planar reflections */ -/* keep in sync with EEVEE_ClipPlanesUniformBuffer */ -layout(std140) uniform clip_block -{ - vec4 ClipPlanes[1]; -}; - out vec3 worldNormal; out vec3 viewNormal; @@ -61,7 +54,7 @@ void main() gl_Position = point_world_to_ndc(worldPosition); /* Used for planar reflections */ - gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), ClipPlanes[0]); + gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), clipPlanes[0]); #ifdef USE_ATTR pass_attr(pos); diff --git a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl index d133889e725..2c7e0aca3fb 100644 --- a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl @@ -1,12 +1,4 @@ -#ifdef CLIP_PLANES -/* keep in sync with DRWManager.view_data */ -layout(std140) uniform clip_block -{ - vec4 ClipPlanes[1]; -}; -#endif - #ifndef HAIR_SHADER in vec3 pos; #endif @@ -40,7 +32,7 @@ void main() gl_Position = point_world_to_ndc(worldPosition); #ifdef CLIP_PLANES - gl_ClipDistance[0] = dot(vec4(worldPosition.xyz, 1.0), ClipPlanes[0]); + gl_ClipDistance[0] = dot(vec4(worldPosition.xyz, 1.0), clipPlanes[0]); #endif /* TODO motion vectors */ } diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index 1223e31b891..d8748b05f96 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -90,8 +90,7 @@ typedef struct EXTERNAL_PrivateData { bool update_depth; bool view_updated; - float last_mat[4][4]; - float curr_mat[4][4]; + float last_persmat[4][4]; } EXTERNAL_PrivateData; /* Transient data */ /* Functions */ @@ -126,13 +125,11 @@ static void external_engine_init(void *vedata) } { - float view[4][4]; - float win[4][4]; - DRW_viewport_matrix_get(view, DRW_MAT_VIEW); - DRW_viewport_matrix_get(win, DRW_MAT_WIN); - mul_m4_m4m4(stl->g_data->curr_mat, view, win); - if (!equals_m4m4(stl->g_data->curr_mat, stl->g_data->last_mat)) { + float persmat[4][4]; + DRW_view_persmat_get(NULL, persmat, false); + if (!equals_m4m4(persmat, stl->g_data->last_persmat)) { stl->g_data->update_depth = true; + copy_m4_m4(stl->g_data->last_persmat, persmat); } } } @@ -227,12 +224,14 @@ static void external_draw_scene_do(void *vedata) /* Rendered draw. */ GPU_matrix_push_projection(); + GPU_matrix_push(); ED_region_pixelspace(ar); /* Render result draw. */ type = rv3d->render_engine->type; type->view_draw(rv3d->render_engine, draw_ctx->evil_C, draw_ctx->depsgraph); + GPU_matrix_pop(); GPU_matrix_pop_projection(); /* Set render info. */ @@ -270,8 +269,6 @@ static void external_draw_scene(void *vedata) // copy tmp buffer to default GPU_framebuffer_blit(fbl->depth_buffer_fb, 0, dfbl->depth_only_fb, 0, GPU_DEPTH_BIT); } - - copy_m4_m4(stl->g_data->last_mat, stl->g_data->curr_mat); } static void external_view_update(void *vedata) diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 9ebd168bc4c..5dab0a56b63 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -187,9 +187,7 @@ typedef struct GPENCIL_Storage { float mix_stroke_factor; /* Render Matrices and data */ - float persmat[4][4], persinv[4][4]; - float viewmat[4][4], viewinv[4][4]; - float winmat[4][4], wininv[4][4]; + DRWView *view; float view_vecs[2][4]; /* vec4[2] */ float grid_matrix[4][4]; diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c index e6a3f45d60d..301c29af335 100644 --- a/source/blender/draw/engines/gpencil/gpencil_render.c +++ b/source/blender/draw/engines/gpencil/gpencil_render.c @@ -94,26 +94,26 @@ void GPENCIL_render_init(GPENCIL_Data *ved, RenderEngine *engine, struct Depsgra } /* Set the pers & view matrix. */ + float winmat[4][4], viewmat[4][4], viewinv[4][4], persmat[4][4]; + struct Object *camera = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); float frame = BKE_scene_frame_get(scene); - RE_GetCameraWindow(engine->re, camera, frame, stl->storage->winmat); - RE_GetCameraModelMatrix(engine->re, camera, stl->storage->viewinv); + RE_GetCameraWindow(engine->re, camera, frame, winmat); + RE_GetCameraModelMatrix(engine->re, camera, viewinv); + + invert_m4_m4(viewmat, viewinv); - invert_m4_m4(stl->storage->viewmat, stl->storage->viewinv); - mul_m4_m4m4(stl->storage->persmat, stl->storage->winmat, stl->storage->viewmat); - invert_m4_m4(stl->storage->persinv, stl->storage->persmat); - invert_m4_m4(stl->storage->wininv, stl->storage->winmat); + DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL); + DRW_view_default_set(view); + DRW_view_set_active(view); - DRW_viewport_matrix_override_set(stl->storage->persmat, DRW_MAT_PERS); - DRW_viewport_matrix_override_set(stl->storage->persinv, DRW_MAT_PERSINV); - DRW_viewport_matrix_override_set(stl->storage->winmat, DRW_MAT_WIN); - DRW_viewport_matrix_override_set(stl->storage->wininv, DRW_MAT_WININV); - DRW_viewport_matrix_override_set(stl->storage->viewmat, DRW_MAT_VIEW); - DRW_viewport_matrix_override_set(stl->storage->viewinv, DRW_MAT_VIEWINV); + DRW_view_persmat_get(view, persmat, false); /* calculate pixel size for render */ - stl->storage->render_pixsize = get_render_pixelsize( - stl->storage->persmat, viewport_size[0], viewport_size[1]); + stl->storage->render_pixsize = get_render_pixelsize(persmat, viewport_size[0], viewport_size[1]); + + stl->storage->view = view; + /* INIT CACHE */ GPENCIL_cache_init(vedata); } @@ -180,8 +180,8 @@ static void GPENCIL_render_update_vecs(GPENCIL_Data *vedata) GPENCIL_StorageList *stl = vedata->stl; float invproj[4][4], winmat[4][4]; - DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); - DRW_viewport_matrix_get(invproj, DRW_MAT_WININV); + DRW_view_winmat_get(NULL, winmat, false); + DRW_view_winmat_get(NULL, invproj, true); /* this is separated to keep function equal to Eevee for future reuse of same code */ GPENCIL_render_update_viewvecs(invproj, winmat, stl->storage->view_vecs); @@ -207,10 +207,13 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl, BLI_rcti_size_y(rect), rp->rect); - bool is_persp = DRW_viewport_is_persp_get(); + bool is_persp = DRW_view_is_persp_get(NULL); GPENCIL_render_update_vecs(vedata); + float winmat[4][4]; + DRW_view_winmat_get(stl->storage->view, winmat, false); + /* Convert ogl depth [0..1] to view Z [near..far] */ for (int i = 0; i < BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); i++) { if (rp->rect[i] == 1.0f) { @@ -219,7 +222,7 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl, else { if (is_persp) { rp->rect[i] = rp->rect[i] * 2.0f - 1.0f; - rp->rect[i] = stl->storage->winmat[3][2] / (rp->rect[i] + stl->storage->winmat[2][2]); + rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]); } else { rp->rect[i] = -stl->storage->view_vecs[0][2] + diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index d46e850ba82..9eb4123e5bc 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -110,22 +110,13 @@ static void GPENCIL_dof_nearfar(Object *camera, float coc, float nearfar[2]) if (camera == NULL) { return; } - - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - Camera *cam = (Camera *)camera->data; + Camera *cam = camera->data; float fstop = cam->dof.aperture_fstop; float focus_dist = BKE_camera_object_dof_distance(camera); float focal_len = cam->lens; - /* This is factor that converts to the scene scale. focal length and sensor are expressed in mm - * unit.scale_length is how many meters per blender unit we have. We want to convert to blender - * units though because the shader reads coordinates in world space, which is in blender units. - * Note however that focus_distance is already in blender units and shall not be scaled here - * (see T48157). */ - float scale = (scene->unit.system) ? scene->unit.scale_length : 1.0f; - float scale_camera = 0.001f / scale; + const float scale_camera = 0.001f; /* we want radius here for the aperture number */ float aperture_scaled = 0.5f * scale_camera * focal_len / fstop; float focal_len_scaled = scale_camera * focal_len; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl index 46b0361245b..092878e43aa 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl @@ -8,6 +8,9 @@ uniform vec2 invertedViewportSize; void main() { + ivec2 texel = ivec2(gl_FragCoord.xy); + float alpha = texelFetch(colorBuffer, texel, 0).a; FragColor = FxaaPixelShader( uvcoordsvar.st, colorBuffer, invertedViewportSize, 1.0, 0.166, 0.0833); + FragColor.a = alpha; } 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 848cd49bf53..fd06c85747f 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl @@ -216,8 +216,8 @@ void main() vs_ray_dir /= abs(vs_ray_dir.z); /* 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_dir = mat3(ViewMatrixInverse) * vs_ray_dir * OrcoTexCoFactors[1] * 2.0; + ls_ray_dir = mat3(ModelMatrixInverse) * 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); diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index 7728b3f998b..fce1d725133 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -127,7 +127,6 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) RegionView3D *rv3d = draw_ctx->rv3d; if (rv3d->rflag & RV3D_CLIPPING) { wpd->world_clip_planes = rv3d->clip; - DRW_state_clip_planes_set_from_rv3d(rv3d); UI_GetThemeColor4fv(TH_V3D_CLIPPING_BORDER, wpd->world_clip_planes_color); if (wpd->use_color_management) { srgb_to_linearrgb_v3_v3(wpd->world_clip_planes_color, wpd->world_clip_planes_color); @@ -148,7 +147,7 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) const int ssao_samples = scene->display.matcap_ssao_samples; float invproj[4][4]; - const bool is_persp = DRW_viewport_is_persp_get(); + const bool is_persp = DRW_view_is_persp_get(NULL); /* view vectors for the corners of the view frustum. * Can be used to recreate the world space position easily */ float viewvecs[3][4] = { @@ -171,9 +170,8 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) wpd->shading.cavity_ridge_factor, scene->display.matcap_ssao_attenuation); - /* invert the view matrix */ - DRW_viewport_matrix_get(wpd->winmat, DRW_MAT_WIN); - invert_m4_m4(invproj, wpd->winmat); + DRW_view_winmat_get(NULL, wpd->winmat, false); + DRW_view_winmat_get(NULL, invproj, true); /* convert the view vectors to view space */ for (i = 0; i < 3; i++) { @@ -213,7 +211,7 @@ void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, Scene *scene = draw_ctx->scene; WORKBENCH_UBO_World *wd = &wpd->world_data; float view_matrix[4][4]; - DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW); + DRW_view_viewmat_get(NULL, view_matrix, false); copy_v3_v3(r_light_direction, scene->display.light_direction); SWAP(float, r_light_direction[2], r_light_direction[1]); diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index eacd319cc4a..28104a87b9a 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -983,6 +983,8 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat); int color_type = workbench_material_determine_color_type(wpd, image, ob, is_sculpt_mode); if (color_type == V3D_SHADING_MATERIAL_COLOR && mat && mat->a < 1.0) { + /* Hack */ + wpd->shading.xray_alpha = mat->a; material = workbench_forward_get_or_create_material_data( vedata, ob, mat, image, iuser, color_type, 0, is_sculpt_mode); has_transp_mat = true; diff --git a/source/blender/draw/engines/workbench/workbench_effect_aa.c b/source/blender/draw/engines/workbench/workbench_effect_aa.c index b4cdcfcfc99..965f5a5ca4f 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_aa.c +++ b/source/blender/draw/engines/workbench/workbench_effect_aa.c @@ -49,6 +49,7 @@ void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx) } else { psl->effect_aa_pass = NULL; + effect_info->jitter_index = 0; } } diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.c b/source/blender/draw/engines/workbench/workbench_effect_dof.c index 6886b73650c..e24536759db 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_dof.c +++ b/source/blender/draw/engines/workbench/workbench_effect_dof.c @@ -231,7 +231,6 @@ void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera) { const DRWContextState *draw_ctx = DRW_context_state_get(); - const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); RegionView3D *rv3d = draw_ctx->rv3d; /* Parameters */ @@ -242,14 +241,7 @@ void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera) float focal_len = cam->lens; /* TODO(fclem) deduplicate with eevee */ - - /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm - * unit.scale_length is how many meters per blender unit we have. We want to convert to blender - * units though because the shader reads coordinates in world space, which is in blender units. - * Note however that focus_distance is already in blender units and shall not be scaled here - * (see T48157). */ - float scale = (scene_eval->unit.system) ? scene_eval->unit.scale_length : 1.0f; - float scale_camera = 0.001f / scale; + const float scale_camera = 0.001f; /* we want radius here for the aperture number */ float aperture = 0.5f * scale_camera * focal_len / fstop; float focal_len_scaled = scale_camera * focal_len; diff --git a/source/blender/draw/engines/workbench/workbench_effect_taa.c b/source/blender/draw/engines/workbench/workbench_effect_taa.c index 7b2faf0ddcd..7fd68babc13 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_taa.c +++ b/source/blender/draw/engines/workbench/workbench_effect_taa.c @@ -135,6 +135,8 @@ void workbench_taa_engine_init(WORKBENCH_Data *vedata) workbench_taa_jitter_init(); } + effect_info->view = NULL; + /* reset complete drawing when navigating. */ if (effect_info->jitter_index != 0) { if (rv3d && rv3d->rflag & RV3D_NAVIGATING) { @@ -148,12 +150,10 @@ void workbench_taa_engine_init(WORKBENCH_Data *vedata) } { - float view[4][4]; - float win[4][4]; - DRW_viewport_matrix_get(view, DRW_MAT_VIEW); - DRW_viewport_matrix_get(win, DRW_MAT_WIN); - mul_m4_m4m4(effect_info->curr_mat, view, win); - if (!equals_m4m4(effect_info->curr_mat, effect_info->last_mat)) { + float persmat[4][4]; + DRW_view_persmat_get(NULL, persmat, false); + if (!equals_m4m4(persmat, effect_info->last_mat)) { + copy_m4_m4(effect_info->last_mat, persmat); effect_info->jitter_index = 0; } } @@ -217,9 +217,9 @@ void workbench_taa_draw_scene_start(WORKBENCH_Data *vedata) WORKBENCH_StorageList *stl = vedata->stl; WORKBENCH_EffectInfo *effect_info = stl->effects; const float *viewport_size = DRW_viewport_size_get(); + const DRWView *default_view = DRW_view_default_get(); int num_samples = 8; float(*samples)[2]; - float mix_factor; num_samples = workbench_taa_calculate_num_iterations(vedata); switch (num_samples) { @@ -241,41 +241,38 @@ void workbench_taa_draw_scene_start(WORKBENCH_Data *vedata) break; } - mix_factor = 1.0f / (effect_info->jitter_index + 1); - const int jitter_index = effect_info->jitter_index; const float *transform_offset = samples[jitter_index]; + effect_info->taa_mix_factor = 1.0f / (jitter_index + 1); effect_info->jitter_index = (jitter_index + 1) % num_samples; /* construct new matrices from transform delta */ - float viewmat[4][4]; - float persmat[4][4]; - DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); - DRW_viewport_matrix_get(persmat, DRW_MAT_PERS); - DRW_viewport_matrix_get(effect_info->override_winmat, DRW_MAT_WIN); + float winmat[4][4], viewmat[4][4], persmat[4][4]; + DRW_view_winmat_get(default_view, winmat, false); + DRW_view_viewmat_get(default_view, viewmat, false); + DRW_view_persmat_get(default_view, persmat, false); - window_translate_m4(effect_info->override_winmat, + window_translate_m4(winmat, persmat, transform_offset[0] / viewport_size[0], transform_offset[1] / viewport_size[1]); - mul_m4_m4m4(effect_info->override_persmat, effect_info->override_winmat, viewmat); - invert_m4_m4(effect_info->override_persinv, effect_info->override_persmat); - invert_m4_m4(effect_info->override_wininv, effect_info->override_winmat); - - DRW_viewport_matrix_override_set(effect_info->override_persmat, DRW_MAT_PERS); - DRW_viewport_matrix_override_set(effect_info->override_persinv, DRW_MAT_PERSINV); - DRW_viewport_matrix_override_set(effect_info->override_winmat, DRW_MAT_WIN); - DRW_viewport_matrix_override_set(effect_info->override_wininv, DRW_MAT_WININV); - - /* weight the mix factor by the jitter index */ - effect_info->taa_mix_factor = mix_factor; + if (effect_info->view) { + /* When rendering just update the view. This avoids recomputing the culling. */ + DRW_view_update_sub(effect_info->view, viewmat, winmat); + } + else { + /* TAA is not making a big change to the matrices. + * Reuse the main view culling by creating a subview. */ + effect_info->view = DRW_view_create_sub(default_view, viewmat, winmat); + } + DRW_view_set_active(effect_info->view); } void workbench_taa_draw_scene_end(WORKBENCH_Data *vedata) { /* - * If first frame than the offset is 0.0 and its depth is the depth buffer to use + * If first frame then the offset is 0.0 and its depth is the depth buffer to use * for the rest of the draw engines. We store it in a persistent buffer. * * If it is not the first frame we copy the persistent buffer back to the @@ -296,10 +293,9 @@ void workbench_taa_draw_scene_end(WORKBENCH_Data *vedata) GPU_framebuffer_blit(dfbl->color_only_fb, 0, fbl->effect_taa_fb, 0, GPU_COLOR_BIT); if (!DRW_state_is_image_render()) { - DRW_viewport_matrix_override_unset_all(); + DRW_view_set_active(NULL); } - copy_m4_m4(effect_info->last_mat, effect_info->curr_mat); if (effect_info->jitter_index != 0 && !DRW_state_is_image_render()) { DRW_viewport_request_redraw(); } diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index f12902b6801..5f15fb3f19e 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -212,7 +212,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_ material->object_id = engine_object_data->object_id; DRW_shgroup_uniform_int(material->shgrp_object_outline, "object_id", &material->object_id, 1); if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(material->shgrp_object_outline, draw_ctx->rv3d); + DRW_shgroup_state_enable(material->shgrp_object_outline, DRW_STATE_CLIP_PLANES); } BLI_ghash_insert(wpd->material_transp_hash, POINTER_FROM_UINT(hash), material); } diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index b280b6fd01a..02fbbe0b042 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -52,7 +52,7 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd, copy_v3_v3(data->base_color, data->diffuse_color); copy_v3_fl3(data->specular_color, 0.05f, 0.05f, 0.05f); /* Dielectric: 5% reflective. */ data->metallic = 0.0f; - data->roughness = 0.5f; /* sqrtf(0.25f); */ + data->roughness = 0.632455532f; /* sqrtf(0.4f); */ if (color_type == V3D_SHADING_SINGLE_COLOR) { copy_v3_v3(data->diffuse_color, wpd->shading.single_color); @@ -316,7 +316,6 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd, } if (WORLD_CLIPPING_ENABLED(wpd)) { - DRW_shgroup_uniform_vec4(grp, "WorldClipPlanes", wpd->world_clip_planes[0], 6); DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } } diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 09d9ad65717..240d06c1e79 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -273,12 +273,10 @@ typedef struct WORKBENCH_PrivateData { } WORKBENCH_PrivateData; /* Transient data */ typedef struct WORKBENCH_EffectInfo { - float override_persmat[4][4]; - float override_persinv[4][4]; - float override_winmat[4][4]; - float override_wininv[4][4]; + /** View */ + struct DRWView *view; + /** Last projection matrix to see if view is still valid. */ float last_mat[4][4]; - float curr_mat[4][4]; int jitter_index; float taa_mix_factor; bool view_updated; @@ -328,7 +326,8 @@ BLI_INLINE bool workbench_is_taa_enabled(WORKBENCH_PrivateData *wpd) } } else { - return wpd->preferences->viewport_aa > SCE_DISPLAY_AA_FXAA && !wpd->is_playback; + return !(IS_NAVIGATING(wpd) || wpd->is_playback) && + wpd->preferences->viewport_aa > SCE_DISPLAY_AA_FXAA; } } @@ -348,8 +347,9 @@ BLI_INLINE bool workbench_is_fxaa_enabled(WORKBENCH_PrivateData *wpd) return true; } - /* when navigating or animation playback use FXAA. */ - return (IS_NAVIGATING(wpd) || wpd->is_playback) && workbench_is_taa_enabled(wpd); + /* when navigating or animation playback use FXAA if scene uses TAA. */ + return (IS_NAVIGATING(wpd) || wpd->is_playback) && + wpd->preferences->viewport_aa > SCE_DISPLAY_AA_FXAA; } } diff --git a/source/blender/draw/engines/workbench/workbench_render.c b/source/blender/draw/engines/workbench/workbench_render.c index 1497ef493cf..46d78ca0e37 100644 --- a/source/blender/draw/engines/workbench/workbench_render.c +++ b/source/blender/draw/engines/workbench/workbench_render.c @@ -63,24 +63,16 @@ static void workbench_render_matrices_init(RenderEngine *engine, Depsgraph *deps float frame = BKE_scene_frame_get(scene); /* Set the persective, view and window matrix. */ - float winmat[4][4], wininv[4][4]; - float viewmat[4][4], viewinv[4][4]; - float persmat[4][4], persinv[4][4]; + float winmat[4][4], viewmat[4][4], viewinv[4][4]; RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat); RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv); invert_m4_m4(viewmat, viewinv); - mul_m4_m4m4(persmat, winmat, viewmat); - invert_m4_m4(persinv, persmat); - invert_m4_m4(wininv, winmat); - - DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS); - DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV); - DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN); - DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV); - DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW); - DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV); + + DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL); + DRW_view_default_set(view); + DRW_view_set_active(view); } static bool workbench_render_framebuffers_init(void) @@ -159,9 +151,6 @@ void workbench_render(WORKBENCH_Data *data, if (RE_engine_test_break(engine)) { break; } - /* TODO: Save matrices instead of recomputing them for each samples. */ - workbench_render_matrices_init(engine, depsgraph); - workbench_deferred_draw_background(data); workbench_deferred_draw_scene(data); } diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c index 3fc83fea7c6..944bca73993 100644 --- a/source/blender/draw/engines/workbench/workbench_studiolight.c +++ b/source/blender/draw/engines/workbench/workbench_studiolight.c @@ -32,7 +32,7 @@ void studiolight_update_world(WORKBENCH_PrivateData *wpd, WORKBENCH_UBO_World *wd) { float view_matrix[4][4], rot_matrix[4][4]; - DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW); + DRW_view_viewmat_get(NULL, view_matrix, false); if (USE_WORLD_ORIENTATION(wpd)) { axis_angle_to_mat4_single(rot_matrix, 'Z', -wpd->shading.studiolight_rot_z); @@ -165,12 +165,12 @@ void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_dire } float planes[6][4]; - DRW_culling_frustum_planes_get(planes); + DRW_culling_frustum_planes_get(NULL, planes); /* we only need the far plane. */ copy_v4_v4(wpd->shadow_far_plane, planes[2]); BoundBox frustum_corners; - DRW_culling_frustum_corners_get(&frustum_corners); + DRW_culling_frustum_corners_get(NULL, &frustum_corners); mul_v3_mat3_m4v3(wpd->shadow_near_corners[0], wpd->shadow_inv, frustum_corners.vec[0]); mul_v3_mat3_m4v3(wpd->shadow_near_corners[1], wpd->shadow_inv, frustum_corners.vec[3]); @@ -230,7 +230,8 @@ bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, WORKBENCH_ObjectData *oed) { BoundBox *shadow_bbox = studiolight_object_shadow_bbox_get(wpd, ob, oed); - return DRW_culling_box_test(shadow_bbox); + const DRWView *default_view = DRW_view_default_get(); + return DRW_culling_box_test(default_view, shadow_bbox); } float studiolight_object_shadow_distance(WORKBENCH_PrivateData *wpd, diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c index 1620584dc06..2b5fc8c0e47 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.c +++ b/source/blender/draw/engines/workbench/workbench_volume.c @@ -154,7 +154,7 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, if (use_slice) { float invviewmat[4][4]; - DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); + DRW_view_viewmat_get(NULL, invviewmat, true); const int axis = (sds->slice_axis == SLICE_AXIS_AUTO) ? axis_dominant_v3_single(invviewmat[2]) : diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 98e974a09b5..a33060bfbbe 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -81,6 +81,7 @@ struct rcti; typedef struct DRWInterface DRWInterface; typedef struct DRWPass DRWPass; +typedef struct DRWView DRWView; typedef struct DRWShadingGroup DRWShadingGroup; typedef struct DRWUniform DRWUniform; @@ -353,10 +354,6 @@ typedef enum { DRW_STATE_CLIP_PLANES = (1 << 22), DRW_STATE_WIRE_SMOOTH = (1 << 23), DRW_STATE_FIRST_VERTEX_CONVENTION = (1 << 24), - /** Polygon offset. Does not work with lines and points. */ - DRW_STATE_OFFSET_POSITIVE = (1 << 25), - /** Polygon offset. Does not work with lines and points. */ - DRW_STATE_OFFSET_NEGATIVE = (1 << 26), } DRWState; #define DRW_STATE_DEFAULT \ @@ -397,7 +394,6 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, /* return final visibility */ typedef bool(DRWCallVisibilityFn)(bool vis_in, void *user_data); -/* 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); @@ -416,10 +412,10 @@ void DRW_shgroup_call_object_ex(DRWShadingGroup *shgroup, DRW_shgroup_call_object_ex(shgroup, geom, ob, true) /* TODO(fclem) remove this when we have DRWView */ +/* user_data is used by DRWCallVisibilityFn defined in DRWView. */ void DRW_shgroup_call_object_with_callback(DRWShadingGroup *shgroup, struct GPUBatch *geom, struct Object *ob, - DRWCallVisibilityFn *callback, void *user_data); void DRW_shgroup_call_instances(DRWShadingGroup *shgroup, @@ -484,14 +480,6 @@ void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize); -void DRW_shgroup_uniform_short_to_int(DRWShadingGroup *shgroup, - const char *name, - const short *value, - int arraysize); -void DRW_shgroup_uniform_short_to_float(DRWShadingGroup *shgroup, - const char *name, - const short *value, - int arraysize); /* Boolean are expected to be 4bytes longs for opengl! */ void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, @@ -525,6 +513,7 @@ bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup); /* Passes */ DRWPass *DRW_pass_create(const char *name, DRWState state); +/* TODO Replace with passes inheritance. */ void DRW_pass_state_set(DRWPass *pass, DRWState state); void DRW_pass_state_add(DRWPass *pass, DRWState state); void DRW_pass_state_remove(DRWPass *pass, DRWState state); @@ -537,51 +526,59 @@ bool DRW_pass_is_empty(DRWPass *pass); #define DRW_PASS_CREATE(pass, state) (pass = DRW_pass_create(#pass, state)) -/* Viewport */ -typedef enum { - /* keep in sync with the union struct DRWMatrixState. */ - DRW_MAT_PERS = 0, - DRW_MAT_PERSINV, - DRW_MAT_VIEW, - DRW_MAT_VIEWINV, - DRW_MAT_WIN, - DRW_MAT_WININV, - - DRW_MAT_COUNT, // Don't use this. -} DRWViewportMatrixType; - -typedef struct DRWMatrixState { - union { - float mat[DRW_MAT_COUNT][4][4]; - struct { - /* keep in sync with the enum DRWViewportMatrixType. */ - float persmat[4][4]; - float persinv[4][4]; - float viewmat[4][4]; - float viewinv[4][4]; - float winmat[4][4]; - float wininv[4][4]; - }; - }; -} DRWMatrixState; - -void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type); -void DRW_viewport_matrix_get_all(DRWMatrixState *state); -void DRW_viewport_matrix_override_set(const float mat[4][4], DRWViewportMatrixType type); -void DRW_viewport_matrix_override_set_all(DRWMatrixState *state); -void DRW_viewport_matrix_override_unset(DRWViewportMatrixType type); -void DRW_viewport_matrix_override_unset_all(void); - -/* These are in view-space so negative if in perspective. +/* Views */ +DRWView *DRW_view_create(const float viewmat[4][4], + const float winmat[4][4], + const float (*culling_viewmat)[4], + const float (*culling_winmat)[4], + DRWCallVisibilityFn *visibility_fn); +DRWView *DRW_view_create_sub(const DRWView *parent_view, + const float viewmat[4][4], + const float winmat[4][4]); + +void DRW_view_update(DRWView *view, + const float viewmat[4][4], + const float winmat[4][4], + const float (*culling_viewmat)[4], + const float (*culling_winmat)[4]); +void DRW_view_update_sub(DRWView *view, const float viewmat[4][4], const float winmat[4][4]); + +const DRWView *DRW_view_default_get(void); +void DRW_view_default_set(DRWView *view); + +void DRW_view_set_active(DRWView *view); + +void DRW_view_clip_planes_set(DRWView *view, float (*planes)[4], int plane_len); +void DRW_view_camtexco_set(DRWView *view, float texco[4]); + +/* For all getters, if view is NULL, default view is assumed. */ +void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse); +void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse); +void DRW_view_persmat_get(const DRWView *view, float mat[4][4], bool inverse); + +void DRW_view_frustum_corners_get(const DRWView *view, BoundBox *corners); +void DRW_view_frustum_planes_get(const DRWView *view, float planes[6][4]); + +/* These are in view-space, so negative if in perspective. * Extract near and far clip distance from the projection matrix. */ -float DRW_viewport_near_distance_get(void); -float DRW_viewport_far_distance_get(void); +float DRW_view_near_distance_get(const DRWView *view); +float DRW_view_far_distance_get(const DRWView *view); +bool DRW_view_is_persp_get(const DRWView *view); + +/* Culling, return true if object is inside view frustum. */ +bool DRW_culling_sphere_test(const DRWView *view, const BoundSphere *bsphere); +bool DRW_culling_box_test(const DRWView *view, const BoundBox *bbox); +bool DRW_culling_plane_test(const DRWView *view, const float plane[4]); + +void DRW_culling_frustum_corners_get(const DRWView *view, BoundBox *corners); +void DRW_culling_frustum_planes_get(const DRWView *view, float planes[6][4]); + +/* Viewport */ const float *DRW_viewport_size_get(void); const float *DRW_viewport_invert_size_get(void); const float *DRW_viewport_screenvecs_get(void); const float *DRW_viewport_pixelsize_get(void); -bool DRW_viewport_is_persp_get(void); struct DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void); struct DefaultTextureList *DRW_viewport_texture_list_get(void); @@ -645,18 +642,6 @@ void DRW_state_reset_ex(DRWState state); void DRW_state_reset(void); void DRW_state_lock(DRWState state); -void DRW_state_clip_planes_len_set(uint plane_len); -void DRW_state_clip_planes_reset(void); -void DRW_state_clip_planes_set_from_rv3d(struct RegionView3D *rv3d); - -/* Culling, return true if object is inside view frustum. */ -bool DRW_culling_sphere_test(BoundSphere *bsphere); -bool DRW_culling_box_test(BoundBox *bbox); -bool DRW_culling_plane_test(float plane[4]); - -void DRW_culling_frustum_corners_get(BoundBox *corners); -void DRW_culling_frustum_planes_get(float planes[6][4]); - /* Selection */ void DRW_select_load_id(uint id); diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index e1c86790cdc..bcca660f861 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -31,6 +31,8 @@ #include "BKE_global.h" #include "BKE_colorband.h" +#include "BIF_glutil.h" + #include "draw_common.h" #if 0 @@ -304,13 +306,6 @@ void DRW_globals_free(void) } } -void DRW_shgroup_world_clip_planes_from_rv3d(DRWShadingGroup *shgrp, const RegionView3D *rv3d) -{ - int world_clip_planes_len = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; - DRW_shgroup_uniform_vec4(shgrp, "WorldClipPlanes", rv3d->clip[0], world_clip_planes_len); - DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); -} - 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); @@ -323,7 +318,7 @@ struct DRWCallBuffer *buffer_dynlines_flat_color(DRWPass *pass, eGPUShaderConfig 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer(grp, g_formats.pos_color, GPU_PRIM_LINES); } @@ -347,7 +342,7 @@ struct DRWCallBuffer *buffer_dynlines_dashed_uniform_color(DRWPass *pass, DRW_shgroup_uniform_float(grp, "dash_factor", &dash_factor, 1); DRW_shgroup_uniform_int_copy(grp, "colors_len", 0); /* "simple" mode */ if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_LINES); } @@ -370,7 +365,7 @@ struct DRWCallBuffer *buffer_groundlines_uniform_color(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_POINTS); } @@ -386,7 +381,7 @@ struct DRWCallBuffer *buffer_groundpoints_uniform_color(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_POINTS); } @@ -410,7 +405,7 @@ struct DRWCallBuffer *buffer_instance_screenspace(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_screenspace, geom); } @@ -465,7 +460,7 @@ struct DRWCallBuffer *buffer_instance_screen_aligned(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_screen_aligned, geom); } @@ -486,7 +481,7 @@ struct DRWCallBuffer *buffer_instance_scaled(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_scaled, geom); } @@ -508,7 +503,7 @@ struct DRWCallBuffer *buffer_instance(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom); } @@ -549,7 +544,7 @@ struct DRWCallBuffer *buffer_instance_empty_axes(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom); } @@ -589,7 +584,7 @@ struct DRWCallBuffer *buffer_camera_instance(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_camera, geom); } @@ -613,7 +608,7 @@ struct DRWCallBuffer *buffer_distance_lines_instance(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_distance_lines, geom); } @@ -638,7 +633,7 @@ struct DRWCallBuffer *buffer_spot_instance(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_spot, geom); } @@ -664,7 +659,7 @@ struct DRWCallBuffer *buffer_instance_bone_axes(DRWPass *pass, eGPUShaderConfig 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance( grp, g_formats.instance_color, DRW_cache_bone_arrows_get()); @@ -694,7 +689,7 @@ struct DRWCallBuffer *buffer_instance_bone_envelope_outline(DRWPass *pass, eGPUS 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance( grp, g_formats.instance_bone_envelope_outline, DRW_cache_bone_envelope_outline_get()); @@ -723,7 +718,7 @@ struct DRWCallBuffer *buffer_instance_bone_envelope_distance(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance( grp, g_formats.instance_bone_envelope_distance, DRW_cache_bone_envelope_solid_get()); @@ -759,7 +754,7 @@ struct DRWCallBuffer *buffer_instance_bone_envelope_solid(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance( grp, g_formats.instance_bone_envelope, DRW_cache_bone_envelope_solid_get()); @@ -787,7 +782,7 @@ struct DRWCallBuffer *buffer_instance_mball_handles(DRWPass *pass, eGPUShaderCon 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance( grp, g_formats.instance_mball_handles, DRW_cache_screenspace_circle_get()); @@ -824,7 +819,7 @@ struct DRWCallBuffer *buffer_instance_bone_shape_outline(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_bone_outline, geom); } @@ -857,7 +852,7 @@ struct DRWCallBuffer *buffer_instance_bone_shape_solid(DRWPass *pass, 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_bone, geom); } @@ -887,7 +882,7 @@ struct DRWCallBuffer *buffer_instance_bone_sphere_solid(DRWPass *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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance( grp, g_formats.instance_bone, DRW_cache_bone_point_get()); @@ -915,7 +910,7 @@ struct DRWCallBuffer *buffer_instance_bone_sphere_outline(DRWPass *pass, eGPUSha 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance( grp, g_formats.instance_bone_outline, DRW_cache_bone_point_wire_outline_get()); @@ -948,7 +943,7 @@ struct DRWCallBuffer *buffer_instance_bone_stick(DRWPass *pass, eGPUShaderConfig 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); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return DRW_shgroup_call_buffer_instance( grp, g_formats.instance_bone_stick, DRW_cache_bone_stick_get()); @@ -1035,6 +1030,26 @@ struct GPUShader *volume_velocity_shader_get(bool use_needle) } } +DRWView *DRW_view_create_with_zoffset(const RegionView3D *rv3d, float offset) +{ + /* Create view with depth offset */ + const DRWView *default_view = DRW_view_default_get(); + float viewmat[4][4], winmat[4][4]; + DRW_view_viewmat_get(default_view, viewmat, false); + DRW_view_winmat_get(default_view, winmat, false); + + float viewdist = rv3d->dist; + + /* special exception for ortho camera (viewdist isnt used for perspective cameras) */ + if (rv3d->persp == RV3D_CAMOB && rv3d->is_persp == false) { + viewdist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1])); + } + + winmat[3][2] -= bglPolygonOffsetCalc((float *)winmat, viewdist, offset); + + return DRW_view_create_sub(default_view, viewmat, winmat); +} + /* ******************************************** COLOR UTILS ************************************ */ /* TODO FINISH */ @@ -1212,7 +1227,7 @@ bool DRW_object_is_flat(Object *ob, int *axis) bool DRW_object_axis_orthogonal_to_view(Object *ob, int axis) { float ob_rot[3][3], invviewmat[4][4]; - DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); + DRW_view_viewmat_get(NULL, invviewmat, true); BKE_object_rot_to_mat3(ob, ob_rot, true); float dot = dot_v3v3(ob_rot[axis], invviewmat[2]); if (fabsf(dot) < 1e-3) { diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index df7220c0d2a..d0717888525 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -123,9 +123,6 @@ BLI_STATIC_ASSERT_ALIGN(GlobalsUboStorage, 16) void DRW_globals_update(void); void DRW_globals_free(void); -void DRW_shgroup_world_clip_planes_from_rv3d(struct DRWShadingGroup *shgrp, - const RegionView3D *rv3d); - /* 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, @@ -200,6 +197,8 @@ struct GPUShader *mpath_points_shader_get(void); struct GPUShader *volume_velocity_shader_get(bool use_needle); +struct DRWView *DRW_view_create_with_zoffset(const RegionView3D *rv3d, float offset); + int DRW_object_wire_theme_get(struct Object *ob, struct ViewLayer *view_layer, float **r_color); float *DRW_color_background_blend_get(int theme_id); diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c index b88ad936c28..e7a41ee3e43 100644 --- a/source/blender/draw/intern/draw_instance_data.c +++ b/source/blender/draw/intern/draw_instance_data.c @@ -284,9 +284,9 @@ DRWInstanceDataList *DRW_instance_data_list_create(void) { DRWInstanceDataList *idatalist = MEM_callocN(sizeof(DRWInstanceDataList), "DRWInstanceDataList"); - 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); + idatalist->pool_batching = BLI_memblock_create(sizeof(GPUBatch)); + idatalist->pool_instancing = BLI_memblock_create(sizeof(GPUBatch)); + idatalist->pool_buffers = BLI_memblock_create(sizeof(DRWTempBufferHandle)); BLI_addtail(&g_idatalists, idatalist); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 677e117c602..c0a695adbc2 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -366,7 +366,8 @@ void DRW_transform_none(GPUTexture *tex) GPU_batch_uniform_mat4(geom, "ModelViewProjectionMatrix", mat); GPU_batch_program_use_begin(geom); - GPU_batch_draw_range_ex(geom, 0, 0, false); + GPU_batch_bind(geom); + GPU_batch_draw_advanced(geom, 0, 0, 0, 0); GPU_batch_program_use_end(geom); GPU_texture_unbind(tex); @@ -457,7 +458,8 @@ void DRW_multisamples_resolve(GPUTexture *src_depth, GPUTexture *src_color, bool /* avoid gpuMatrix calls */ GPU_batch_program_use_begin(geom); - GPU_batch_draw_range_ex(geom, 0, 0, false); + GPU_batch_bind(geom); + GPU_batch_draw_advanced(geom, 0, 0, 0, 0); GPU_batch_program_use_end(geom); } @@ -539,9 +541,11 @@ static void drw_viewport_cache_resize(void) BLI_memblock_clear(DST.vmempool->calls, NULL); BLI_memblock_clear(DST.vmempool->states, NULL); + BLI_memblock_clear(DST.vmempool->cullstates, 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->views, NULL); BLI_memblock_clear(DST.vmempool->images, NULL); } @@ -607,22 +611,28 @@ static void drw_viewport_var_init(void) DST.vmempool = GPU_viewport_mempool_get(DST.viewport); if (DST.vmempool->calls == NULL) { - DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall), false); + DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall)); } if (DST.vmempool->states == NULL) { - DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState), false); + DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState)); + } + if (DST.vmempool->cullstates == NULL) { + DST.vmempool->cullstates = BLI_memblock_create(sizeof(DRWCullingState)); } if (DST.vmempool->shgroups == NULL) { - DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup), false); + DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup)); } if (DST.vmempool->uniforms == NULL) { - DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniform), false); + DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniform)); + } + if (DST.vmempool->views == NULL) { + DST.vmempool->views = BLI_memblock_create(sizeof(DRWView)); } if (DST.vmempool->passes == NULL) { - DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass), false); + DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass)); } if (DST.vmempool->images == NULL) { - DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *), false); + DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *)); } DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport); @@ -639,36 +649,35 @@ static void drw_viewport_var_init(void) DST.vmempool = NULL; } + DST.primary_view_ct = 0; + if (rv3d != NULL) { - /* Refresh DST.screenvecs */ - copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]); - copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]); - normalize_v3(DST.screenvecs[0]); - normalize_v3(DST.screenvecs[1]); + normalize_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]); + normalize_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]); - /* Refresh DST.pixelsize */ DST.pixsize = rv3d->pixsize; + DST.view_default = DRW_view_create(rv3d->viewmat, rv3d->winmat, NULL, NULL, NULL); + DRW_view_camtexco_set(DST.view_default, rv3d->viewcamtexcofac); - copy_m4_m4(DST.original_mat.mat[DRW_MAT_PERS], rv3d->persmat); - copy_m4_m4(DST.original_mat.mat[DRW_MAT_PERSINV], rv3d->persinv); - copy_m4_m4(DST.original_mat.mat[DRW_MAT_VIEW], rv3d->viewmat); - copy_m4_m4(DST.original_mat.mat[DRW_MAT_VIEWINV], rv3d->viewinv); - copy_m4_m4(DST.original_mat.mat[DRW_MAT_WIN], rv3d->winmat); - invert_m4_m4(DST.original_mat.mat[DRW_MAT_WININV], rv3d->winmat); - - memcpy(DST.view_data.matstate.mat, DST.original_mat.mat, sizeof(DST.original_mat.mat)); + if (DST.draw_ctx.sh_cfg == GPU_SHADER_CFG_CLIPPED) { + int plane_len = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; + DRW_view_clip_planes_set(DST.view_default, rv3d->clip, plane_len); + } - copy_v4_v4(DST.view_data.viewcamtexcofac, rv3d->viewcamtexcofac); + DST.view_active = DST.view_default; + DST.view_previous = NULL; } else { - copy_v4_fl4(DST.view_data.viewcamtexcofac, 1.0f, 1.0f, 0.0f, 0.0f); - } + zero_v3(DST.screenvecs[0]); + zero_v3(DST.screenvecs[1]); - /* Reset facing */ - DST.frontface = GL_CCW; - DST.backface = GL_CW; - glFrontFace(DST.frontface); + DST.pixsize = 1.0f; + DST.view_default = NULL; + DST.view_active = NULL; + DST.view_previous = NULL; + } + /* fclem: Is this still needed ? */ if (DST.draw_ctx.object_edit) { ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d); } @@ -677,103 +686,12 @@ static void drw_viewport_var_init(void) memset(&DST.RST, 0x0, sizeof(DST.RST)); if (G_draw.view_ubo == NULL) { - G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(ViewUboStorage), NULL); + G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(DRWViewUboStorage), NULL); } - DST.override_mat = 0; - DST.dirty_mat = true; - DST.state_cache_id = 1; - - DST.clipping.updated = false; - memset(DST.object_instance_data, 0x0, sizeof(DST.object_instance_data)); } -void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type) -{ - BLI_assert(type >= 0 && type < DRW_MAT_COUNT); - /* Can't use this in render mode. */ - BLI_assert(((DST.override_mat & (1 << type)) != 0) || DST.draw_ctx.rv3d != NULL); - - copy_m4_m4(mat, DST.view_data.matstate.mat[type]); -} - -void DRW_viewport_matrix_get_all(DRWMatrixState *state) -{ - memcpy(state, DST.view_data.matstate.mat, sizeof(DRWMatrixState)); -} - -void DRW_viewport_matrix_override_set(const float mat[4][4], DRWViewportMatrixType type) -{ - BLI_assert(type < DRW_MAT_COUNT); - copy_m4_m4(DST.view_data.matstate.mat[type], mat); - DST.override_mat |= (1 << type); - DST.dirty_mat = true; - DST.clipping.updated = false; -} - -void DRW_viewport_matrix_override_unset(DRWViewportMatrixType type) -{ - BLI_assert(type < DRW_MAT_COUNT); - copy_m4_m4(DST.view_data.matstate.mat[type], DST.original_mat.mat[type]); - DST.override_mat &= ~(1 << type); - DST.dirty_mat = true; - DST.clipping.updated = false; -} - -void DRW_viewport_matrix_override_set_all(DRWMatrixState *state) -{ - memcpy(DST.view_data.matstate.mat, state, sizeof(DRWMatrixState)); - DST.override_mat = 0xFFFFFF; - DST.dirty_mat = true; - DST.clipping.updated = false; -} - -void DRW_viewport_matrix_override_unset_all(void) -{ - memcpy(DST.view_data.matstate.mat, DST.original_mat.mat, sizeof(DRWMatrixState)); - DST.override_mat = 0; - DST.dirty_mat = true; - DST.clipping.updated = false; -} - -bool DRW_viewport_is_persp_get(void) -{ - RegionView3D *rv3d = DST.draw_ctx.rv3d; - if (rv3d) { - return rv3d->is_persp; - } - else { - return DST.view_data.matstate.mat[DRW_MAT_WIN][3][3] == 0.0f; - } -} - -float DRW_viewport_near_distance_get(void) -{ - float projmat[4][4]; - DRW_viewport_matrix_get(projmat, DRW_MAT_WIN); - - if (DRW_viewport_is_persp_get()) { - return -projmat[3][2] / (projmat[2][2] - 1.0f); - } - else { - return -(projmat[3][2] + 1.0f) / projmat[2][2]; - } -} - -float DRW_viewport_far_distance_get(void) -{ - float projmat[4][4]; - DRW_viewport_matrix_get(projmat, DRW_MAT_WIN); - - if (DRW_viewport_is_persp_get()) { - return -projmat[3][2] / (projmat[2][2] + 1.0f); - } - else { - return -(projmat[3][2] - 1.0f) / projmat[2][2]; - } -} - DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void) { return GPU_viewport_framebuffer_list_get(DST.viewport); @@ -1580,7 +1498,8 @@ void DRW_draw_view(const bContext *C) drw_state_prepare_clean_for_draw(&DST); DST.options.draw_text = ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) != 0); - DST.options.draw_background = scene->r.alphamode == R_ADDSKY; + DST.options.draw_background = (scene->r.alphamode == R_ADDSKY) || + (v3d->shading.type != OB_RENDER); DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C); } @@ -2058,6 +1977,11 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) /* grease pencil: render result is merged in the previous render result. */ if (DRW_render_check_grease_pencil(depsgraph)) { DRW_state_reset(); + /* HACK: this is just for sanity and not trigger asserts. */ + DST.view_default = NULL; + DST.view_active = NULL; + DST.view_previous = NULL; + DRW_render_gpencil_to_image(engine, render_layer, &render_rect); } DST.buffer_finish_called = false; @@ -2619,7 +2543,7 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, /** 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]); + GPU_batch_uniform_4fv_array(batch, "clipPlanes", 6, world_clip_planes[0]); } /** @@ -2685,7 +2609,7 @@ 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]) +static void draw_mesh_verts(GPUBatch *batch, uint offset, const float world_clip_planes[6][4]) { GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE)); @@ -2699,7 +2623,7 @@ static void draw_mesh_verts(GPUBatch *batch, int offset, const float world_clip_ GPU_batch_draw(batch); } -static void draw_mesh_edges(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) +static void draw_mesh_edges(GPUBatch *batch, uint offset, const float world_clip_planes[6][4]) { GPU_line_width(1.0f); glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); @@ -2718,7 +2642,7 @@ static void draw_mesh_edges(GPUBatch *batch, int offset, const float world_clip_ /* two options, facecolors or black */ static void draw_mesh_face(GPUBatch *batch, - int offset, + uint offset, const bool use_select, const float world_clip_planes[6][4]) { @@ -2744,7 +2668,7 @@ static void draw_mesh_face(GPUBatch *batch, } } -static void draw_mesh_face_dot(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) +static void draw_mesh_face_dot(GPUBatch *batch, uint offset, const float world_clip_planes[6][4]) { const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT; @@ -2772,7 +2696,6 @@ void DRW_draw_select_id_object(Scene *scene, } GPU_matrix_mul(ob->obmat); - GPU_depth_test(true); const float(*world_clip_planes)[4] = NULL; if (rv3d->rflag & RV3D_CLIPPING) { @@ -2780,7 +2703,7 @@ void DRW_draw_select_id_object(Scene *scene, world_clip_planes = rv3d->clip_local; } - initial_offset += 1; + BLI_assert(initial_offset > 0); switch (ob->type) { case OB_MESH: @@ -2862,6 +2785,7 @@ void DRW_draw_select_id_object(Scene *scene, draw_mesh_face(geom_faces, 0, false, world_clip_planes); draw_mesh_verts(geom_verts, 1, world_clip_planes); + *r_face_offset = *r_edge_offset = initial_offset; *r_vert_offset = me_eval->totvert + 1; } else { @@ -2870,7 +2794,8 @@ void DRW_draw_select_id_object(Scene *scene, draw_mesh_face(geom_faces, initial_offset, true, world_clip_planes); - *r_face_offset = initial_offset + me_eval->totface; + *r_face_offset = initial_offset + me_eval->totpoly; + *r_edge_offset = *r_vert_offset = *r_face_offset; } } break; @@ -2898,7 +2823,7 @@ void DRW_framebuffer_select_id_setup(ARegion *ar, const bool clear) glDisable(GL_DITHER); GPU_depth_test(true); - glDisable(GL_SCISSOR_TEST); + GPU_disable_program_point_size(); if (clear) { GPU_framebuffer_clear_color_depth( diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index b5dc88205db..6cf70f555eb 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -43,9 +43,9 @@ /* Use draw manager to call GPU_select, see: DRW_draw_select_loop */ #define USE_GPU_SELECT +// #define DRW_DEBUG_CULLING #define DRW_DEBUG_USE_UNIFORM_NAME 0 #define DRW_UNIFORM_BUFFER_NAME 64 -#define DRW_UNIFORM_BUFFER_NAME_INC 1024 /* ------------ Profiling --------------- */ @@ -92,9 +92,7 @@ /* Used by DRWCallState.flag */ enum { - DRW_CALL_CULLED = (1 << 0), DRW_CALL_NEGSCALE = (1 << 1), - DRW_CALL_BYPASS_CULLING = (1 << 2), }; /* Used by DRWCallState.matflag */ @@ -105,22 +103,24 @@ enum { DRW_CALL_OBJECTINFO = (1 << 3), }; -typedef struct DRWCallState { - DRWCallVisibilityFn *visibility_cb; +typedef struct DRWCullingState { + uint32_t mask; + /* Culling: Using Bounding Sphere for now for faster culling. + * Not ideal for planes. Could be extended. */ + BoundSphere bsphere; + /* Grrr only used by EEVEE. */ void *user_data; +} DRWCullingState; +typedef struct DRWCallState { + DRWCullingState *culling; uchar flag; - uchar cache_id; /* Compared with DST.state_cache_id to see if matrices are still valid. */ - uchar matflag; /* Which matrices to compute. */ + 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 modelviewprojection[4][4]; - float orcotexfac[2][3]; /* Not view dependent */ + float orcotexfac[2][3]; float ob_random; } DRWCallState; @@ -214,24 +214,50 @@ struct DRWPass { char name[MAX_PASS_NAME]; }; +/* keep in sync with viewBlock */ +typedef struct DRWViewUboStorage { + /* View matrices */ + float persmat[4][4]; + float persinv[4][4]; + float viewmat[4][4]; + float viewinv[4][4]; + float winmat[4][4]; + float wininv[4][4]; + + float clipplanes[6][4]; + /* Should not be here. Not view dependant (only main view). */ + float viewcamtexcofac[4]; +} DRWViewUboStorage; + +#define MAX_CULLED_VIEWS 32 + +struct DRWView { + /** Parent view if this is a sub view. NULL otherwise. */ + struct DRWView *parent; + + DRWViewUboStorage storage; + /** Number of active clipplanes. */ + int clip_planes_len; + /** Does culling result needs to be updated. */ + bool is_dirty; + /** Culling */ + uint32_t culling_mask; + BoundBox frustum_corners; + BoundSphere frustum_bsphere; + float frustum_planes[6][4]; + /** Custom visibility function. */ + DRWCallVisibilityFn *visibility_fn; + void *user_data; +}; + /* 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]; - float clipplanes[2][4]; -} ViewUboStorage; - /* ------------- DRAW DEBUG ------------ */ typedef struct DRWDebugLine { @@ -259,7 +285,6 @@ typedef struct DRWManager { DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE]; /* State of the object being evaluated if already allocated. */ DRWCallState *ob_state; - 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; @@ -268,6 +293,7 @@ typedef struct DRWManager { /* Rendering state */ GPUShader *shader; + GPUBatch *batch; /* Managed by `DRW_state_set`, `DRW_state_reset` */ DRWState state; @@ -282,8 +308,6 @@ typedef struct DRWManager { float screenvecs[2][3]; float pixsize; - GLenum backface, frontface; - struct { uint is_select : 1; uint is_depth : 1; @@ -305,21 +329,13 @@ typedef struct DRWManager { bool buffer_finish_called; /* Avoid bad usage of DRW_render_instance_buffer_finish */ - /* View dependent uniforms. */ - DRWMatrixState original_mat; /* Original rv3d matrices. */ - int override_mat; /* Bitflag of which matrices are overridden. */ - int clip_planes_len; /* Number of active clipplanes. */ - bool dirty_mat; - - /* keep in sync with viewBlock */ - ViewUboStorage view_data; - - struct { - float frustum_planes[6][4]; - BoundBox frustum_corners; - BoundSphere frustum_bsphere; - bool updated; - } clipping; + DRWView *view_default; + DRWView *view_active; + DRWView *view_previous; + uint primary_view_ct; + /** TODO(fclem) Remove this. Only here to support + * shaders without common_view_lib.glsl */ + DRWViewUboStorage view_storage_cpy; #ifdef USE_GPU_SELECT uint select_id; diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index f8ef1bcf065..c3b905323cc 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -39,6 +39,10 @@ #include "BLI_mempool.h" #include "BLI_memblock.h" +#ifdef DRW_DEBUG_CULLING +# include "BLI_math_bits.h" +#endif + #include "GPU_buffers.h" #include "intern/gpu_codegen.h" @@ -142,7 +146,7 @@ static void drw_shgroup_uniform(DRWShadingGroup *shgroup, size_t len = strlen(name) + 1; if (len >= max_len) { - DST.uniform_names.buffer_len += DRW_UNIFORM_BUFFER_NAME_INC; + DST.uniform_names.buffer_len += MAX2(DST.uniform_names.buffer_len, len); DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer, DST.uniform_names.buffer_len); } @@ -389,8 +393,6 @@ static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obm { DRWCallState *state = BLI_memblock_alloc(DST.vmempool->states); state->flag = 0; - state->cache_id = 0; - state->visibility_cb = NULL; state->matflag = 0; /* Matrices */ @@ -407,18 +409,23 @@ static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obm drw_call_state_update_matflag(state, shgroup, ob); + DRWCullingState *cull = BLI_memblock_alloc(DST.vmempool->cullstates); + state->culling = cull; + if (ob != NULL) { float corner[3]; BoundBox *bbox = BKE_object_boundbox_get(ob); /* Get BoundSphere center and radius from the BoundBox. */ - mid_v3_v3v3(state->bsphere.center, bbox->vec[0], bbox->vec[6]); + mid_v3_v3v3(cull->bsphere.center, bbox->vec[0], bbox->vec[6]); mul_v3_m4v3(corner, obmat, bbox->vec[0]); - mul_m4_v3(obmat, state->bsphere.center); - state->bsphere.radius = len_v3v3(state->bsphere.center, corner); + mul_m4_v3(obmat, cull->bsphere.center); + cull->bsphere.radius = len_v3v3(cull->bsphere.center, corner); } else { + /* TODO(fclem) Bypass alloc if we can (see if eevee's + * probe visibility collection still works). */ /* Bypass test. */ - state->bsphere.radius = -1.0f; + cull->bsphere.radius = -1.0f; } return state; @@ -531,8 +538,6 @@ void DRW_shgroup_call_object_ex(DRWShadingGroup *shgroup, BLI_LINKS_APPEND(&shgroup->calls, call); call->state = drw_call_state_object(shgroup, ob->obmat, ob); - /* 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. */ @@ -541,12 +546,15 @@ void DRW_shgroup_call_object_ex(DRWShadingGroup *shgroup, call->select_id = DST.select_id; call->inst_selectid = NULL; #endif + if (bypass_culling) { + /* NOTE this will disable culling for the whole object. */ + call->state->culling->bsphere.radius = -1.0f; + } } void DRW_shgroup_call_object_with_callback(DRWShadingGroup *shgroup, GPUBatch *geom, Object *ob, - DRWCallVisibilityFn *callback, void *user_data) { BLI_assert(geom != NULL); @@ -555,8 +563,7 @@ void DRW_shgroup_call_object_with_callback(DRWShadingGroup *shgroup, 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->state->culling->user_data = user_data; call->batch = geom; call->vert_first = 0; call->vert_count = 0; /* Auto from batch. */ @@ -859,23 +866,15 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) } else { /* Only here to support builtin shaders. This should not be used by engines. */ - drw_shgroup_builtin_uniform( - shgroup, GPU_UNIFORM_VIEW, DST.view_data.matstate.mat[DRW_MAT_VIEW], 16, 1); - drw_shgroup_builtin_uniform( - shgroup, GPU_UNIFORM_VIEW_INV, DST.view_data.matstate.mat[DRW_MAT_VIEWINV], 16, 1); - drw_shgroup_builtin_uniform( - shgroup, GPU_UNIFORM_VIEWPROJECTION, DST.view_data.matstate.mat[DRW_MAT_PERS], 16, 1); - drw_shgroup_builtin_uniform(shgroup, - GPU_UNIFORM_VIEWPROJECTION_INV, - DST.view_data.matstate.mat[DRW_MAT_PERSINV], - 16, - 1); - drw_shgroup_builtin_uniform( - shgroup, GPU_UNIFORM_PROJECTION, DST.view_data.matstate.mat[DRW_MAT_WIN], 16, 1); - drw_shgroup_builtin_uniform( - shgroup, GPU_UNIFORM_PROJECTION_INV, DST.view_data.matstate.mat[DRW_MAT_WININV], 16, 1); - drw_shgroup_builtin_uniform( - shgroup, GPU_UNIFORM_CAMERATEXCO, DST.view_data.viewcamtexcofac, 3, 2); + /* TODO remove. */ + DRWViewUboStorage *storage = &DST.view_storage_cpy; + drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEW, storage->viewmat, 16, 1); + drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEW_INV, storage->viewinv, 16, 1); + drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEWPROJECTION, storage->persmat, 16, 1); + drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEWPROJECTION_INV, storage->persinv, 16, 1); + drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_PROJECTION, storage->winmat, 16, 1); + drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_PROJECTION_INV, storage->wininv, 16, 1); + drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_CLIPPLANES, storage->clipplanes, 4, 6); } /* Not supported. */ @@ -1050,7 +1049,6 @@ bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup) DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup) { - /* Remove this assertion if needed but implement the other cases first! */ DRWShadingGroup *shgroup_new = BLI_memblock_alloc(DST.vmempool->shgroups); *shgroup_new = *shgroup; @@ -1066,6 +1064,477 @@ DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup) /** \} */ /* -------------------------------------------------------------------- */ +/** \name View (DRW_view) + * \{ */ + +/* Extract the 8 corners from a Projection Matrix. + * Although less accurate, this solution can be simplified as follows: + * BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const + * float[3]){1.0f, 1.0f, 1.0f}); for (int i = 0; i < 8; i++) {mul_project_m4_v3(projinv, + * bbox.vec[i]);} + */ +static void draw_frustum_boundbox_calc(const float (*viewinv)[4], + const float (*projmat)[4], + BoundBox *r_bbox) +{ + float left, right, bottom, top, near, far; + bool is_persp = projmat[3][3] == 0.0f; + +#if 0 /* Equivalent to this but it has accuracy problems. */ + BKE_boundbox_init_from_minmax( + &bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f}); + for (int i = 0; i < 8; i++) { + mul_project_m4_v3(projinv, bbox.vec[i]); + } +#endif + + projmat_dimensions(projmat, &left, &right, &bottom, &top, &near, &far); + + if (is_persp) { + left *= near; + right *= near; + bottom *= near; + top *= near; + } + + r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near; + r_bbox->vec[0][0] = r_bbox->vec[3][0] = left; + r_bbox->vec[4][0] = r_bbox->vec[7][0] = right; + r_bbox->vec[0][1] = r_bbox->vec[4][1] = bottom; + r_bbox->vec[7][1] = r_bbox->vec[3][1] = top; + + /* Get the coordinates of the far plane. */ + if (is_persp) { + float sca_far = far / near; + left *= sca_far; + right *= sca_far; + bottom *= sca_far; + top *= sca_far; + } + + r_bbox->vec[1][2] = r_bbox->vec[2][2] = r_bbox->vec[6][2] = r_bbox->vec[5][2] = -far; + r_bbox->vec[1][0] = r_bbox->vec[2][0] = left; + r_bbox->vec[6][0] = r_bbox->vec[5][0] = right; + r_bbox->vec[1][1] = r_bbox->vec[5][1] = bottom; + r_bbox->vec[2][1] = r_bbox->vec[6][1] = top; + + /* Transform into world space. */ + for (int i = 0; i < 8; i++) { + mul_m4_v3(viewinv, r_bbox->vec[i]); + } +} + +static void draw_frustum_culling_planes_calc(const BoundBox *bbox, float (*frustum_planes)[4]) +{ + /* TODO See if planes_from_projmat cannot do the job. */ + + /* Compute clip planes using the world space frustum corners. */ + for (int p = 0; p < 6; p++) { + int q, r, s; + switch (p) { + case 0: + q = 1; + r = 2; + s = 3; + break; /* -X */ + case 1: + q = 0; + r = 4; + s = 5; + break; /* -Y */ + case 2: + q = 1; + r = 5; + s = 6; + break; /* +Z (far) */ + case 3: + q = 2; + r = 6; + s = 7; + break; /* +Y */ + case 4: + q = 0; + r = 3; + s = 7; + break; /* -Z (near) */ + default: + q = 4; + r = 7; + s = 6; + break; /* +X */ + } + + normal_quad_v3(frustum_planes[p], bbox->vec[p], bbox->vec[q], bbox->vec[r], bbox->vec[s]); + /* Increase precision and use the mean of all 4 corners. */ + frustum_planes[p][3] = -dot_v3v3(frustum_planes[p], bbox->vec[p]); + frustum_planes[p][3] += -dot_v3v3(frustum_planes[p], bbox->vec[q]); + frustum_planes[p][3] += -dot_v3v3(frustum_planes[p], bbox->vec[r]); + frustum_planes[p][3] += -dot_v3v3(frustum_planes[p], bbox->vec[s]); + frustum_planes[p][3] *= 0.25f; + } +} + +static void draw_frustum_bound_sphere_calc(const BoundBox *bbox, + const float (*viewinv)[4], + const float (*projmat)[4], + const float (*projinv)[4], + BoundSphere *bsphere) +{ + /* Extract Bounding Sphere */ + if (projmat[3][3] != 0.0f) { + /* Orthographic */ + /* The most extreme points on the near and far plane. (normalized device coords). */ + const float *nearpoint = bbox->vec[0]; + const float *farpoint = bbox->vec[6]; + + /* just use median point */ + mid_v3_v3v3(bsphere->center, farpoint, nearpoint); + bsphere->radius = len_v3v3(bsphere->center, farpoint); + } + else if (projmat[2][0] == 0.0f && projmat[2][1] == 0.0f) { + /* Perspective with symmetrical frustum. */ + + /* We obtain the center and radius of the circumscribed circle of the + * isosceles trapezoid composed by the diagonals of the near and far clipping plane */ + + /* center of each clipping plane */ + float mid_min[3], mid_max[3]; + mid_v3_v3v3(mid_min, bbox->vec[3], bbox->vec[4]); + mid_v3_v3v3(mid_max, bbox->vec[2], bbox->vec[5]); + + /* square length of the diagonals of each clipping plane */ + float a_sq = len_squared_v3v3(bbox->vec[3], bbox->vec[4]); + float b_sq = len_squared_v3v3(bbox->vec[2], bbox->vec[5]); + + /* distance squared between clipping planes */ + float h_sq = len_squared_v3v3(mid_min, mid_max); + + float fac = (4 * h_sq + b_sq - a_sq) / (8 * h_sq); + + /* The goal is to get the smallest sphere, + * not the sphere that passes through each corner */ + CLAMP(fac, 0.0f, 1.0f); + + interp_v3_v3v3(bsphere->center, mid_min, mid_max, fac); + + /* distance from the center to one of the points of the far plane (1, 2, 5, 6) */ + bsphere->radius = len_v3v3(bsphere->center, bbox->vec[1]); + } + else { + /* Perspective with asymmetrical frustum. */ + + /* We put the sphere center on the line that goes from origin + * to the center of the far clipping plane. */ + + /* Detect which of the corner of the far clipping plane is the farthest to the origin */ + float nfar[4]; /* most extreme far point in NDC space */ + float farxy[2]; /* farpoint projection onto the near plane */ + float farpoint[3] = {0.0f}; /* most extreme far point in camera coordinate */ + float nearpoint[3]; /* most extreme near point in camera coordinate */ + float farcenter[3] = {0.0f}; /* center of far cliping plane in camera coordinate */ + float F = -1.0f, N; /* square distance of far and near point to origin */ + float f, n; /* distance of far and near point to z axis. f is always > 0 but n can be < 0 */ + float e, s; /* far and near clipping distance (<0) */ + float c; /* slope of center line = distance of far clipping center + * to z axis / far clipping distance. */ + float z; /* projection of sphere center on z axis (<0) */ + + /* Find farthest corner and center of far clip plane. */ + float corner[3] = {1.0f, 1.0f, 1.0f}; /* in clip space */ + for (int i = 0; i < 4; i++) { + float point[3]; + mul_v3_project_m4_v3(point, projinv, corner); + float len = len_squared_v3(point); + if (len > F) { + copy_v3_v3(nfar, corner); + copy_v3_v3(farpoint, point); + F = len; + } + add_v3_v3(farcenter, point); + /* rotate by 90 degree to walk through the 4 points of the far clip plane */ + float tmp = corner[0]; + corner[0] = -corner[1]; + corner[1] = tmp; + } + + /* the far center is the average of the far clipping points */ + mul_v3_fl(farcenter, 0.25f); + /* the extreme near point is the opposite point on the near clipping plane */ + copy_v3_fl3(nfar, -nfar[0], -nfar[1], -1.0f); + mul_v3_project_m4_v3(nearpoint, projinv, nfar); + /* this is a frustum projection */ + N = len_squared_v3(nearpoint); + e = farpoint[2]; + s = nearpoint[2]; + /* distance to view Z axis */ + f = len_v2(farpoint); + /* get corresponding point on the near plane */ + mul_v2_v2fl(farxy, farpoint, s / e); + /* this formula preserve the sign of n */ + sub_v2_v2(nearpoint, farxy); + n = f * s / e - len_v2(nearpoint); + c = len_v2(farcenter) / e; + /* the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case */ + z = (F - N) / (2.0f * (e - s + c * (f - n))); + + bsphere->center[0] = farcenter[0] * z / e; + bsphere->center[1] = farcenter[1] * z / e; + bsphere->center[2] = z; + bsphere->radius = len_v3v3(bsphere->center, farpoint); + + /* Transform to world space. */ + mul_m4_v3(viewinv, bsphere->center); + } +} + +static void draw_view_matrix_state_update(DRWViewUboStorage *storage, + const float viewmat[4][4], + const float winmat[4][4]) +{ + /* If only one the matrices is negative, then the + * polygon winding changes and we don't want that. */ + BLI_assert(is_negative_m4(viewmat) != is_negative_m4(winmat)); + + copy_m4_m4(storage->viewmat, viewmat); + invert_m4_m4(storage->viewinv, storage->viewmat); + + copy_m4_m4(storage->winmat, winmat); + invert_m4_m4(storage->wininv, storage->winmat); + + mul_m4_m4m4(storage->persmat, winmat, viewmat); + invert_m4_m4(storage->persinv, storage->persmat); +} + +/* Create a view with culling. */ +DRWView *DRW_view_create(const float viewmat[4][4], + const float winmat[4][4], + const float (*culling_viewmat)[4], + const float (*culling_winmat)[4], + DRWCallVisibilityFn *visibility_fn) +{ + DRWView *view = BLI_memblock_alloc(DST.vmempool->views); + + if (DST.primary_view_ct < MAX_CULLED_VIEWS) { + view->culling_mask = 1u << DST.primary_view_ct++; + } + else { + BLI_assert(0); + view->culling_mask = 0u; + } + view->clip_planes_len = 0; + view->visibility_fn = visibility_fn; + view->parent = NULL; + + copy_v4_fl4(view->storage.viewcamtexcofac, 1.0f, 1.0f, 0.0f, 0.0f); + + DRW_view_update(view, viewmat, winmat, culling_viewmat, culling_winmat); + + return view; +} + +/* Create a view with culling done by another view. */ +DRWView *DRW_view_create_sub(const DRWView *parent_view, + const float viewmat[4][4], + const float winmat[4][4]) +{ + BLI_assert(parent_view && parent_view->parent == NULL); + + DRWView *view = BLI_memblock_alloc(DST.vmempool->views); + + /* Perform copy. */ + *view = *parent_view; + view->parent = (DRWView *)parent_view; + + DRW_view_update_sub(view, viewmat, winmat); + + return view; +} + +/** + * DRWView Update: + * This is meant to be done on existing views when rendering in a loop and there is no + * need to allocate more DRWViews. + **/ + +/* Update matrices of a view created with DRW_view_create_sub. */ +void DRW_view_update_sub(DRWView *view, const float viewmat[4][4], const float winmat[4][4]) +{ + BLI_assert(view->parent != NULL); + + view->is_dirty = true; + + draw_view_matrix_state_update(&view->storage, viewmat, winmat); +} + +/* Update matrices of a view created with DRW_view_create. */ +void DRW_view_update(DRWView *view, + const float viewmat[4][4], + const float winmat[4][4], + const float (*culling_viewmat)[4], + const float (*culling_winmat)[4]) +{ + /* DO NOT UPDATE THE DEFAULT VIEW. + * Create subviews instead, or a copy. */ + BLI_assert(view != DST.view_default); + BLI_assert(view->parent == NULL); + + view->is_dirty = true; + + draw_view_matrix_state_update(&view->storage, viewmat, winmat); + + /* Prepare frustum culling. */ + +#ifdef DRW_DEBUG_CULLING + static float mv[MAX_CULLED_VIEWS][4][4], mw[MAX_CULLED_VIEWS][4][4]; + + /* Select view here. */ + if (view->culling_mask != 0) { + uint index = bitscan_forward_uint(view->culling_mask); + + if (G.debug_value == 0) { + copy_m4_m4(mv[index], culling_viewmat ? culling_viewmat : viewmat); + copy_m4_m4(mw[index], culling_winmat ? culling_winmat : winmat); + } + else { + culling_winmat = mw[index]; + culling_viewmat = mv[index]; + } + } +#endif + + float wininv[4][4]; + if (culling_winmat) { + winmat = culling_winmat; + invert_m4_m4(wininv, winmat); + } + else { + copy_m4_m4(wininv, view->storage.wininv); + } + + float viewinv[4][4]; + if (culling_viewmat) { + viewmat = culling_viewmat; + invert_m4_m4(viewinv, viewmat); + } + else { + copy_m4_m4(viewinv, view->storage.viewinv); + } + + draw_frustum_boundbox_calc(viewinv, winmat, &view->frustum_corners); + draw_frustum_culling_planes_calc(&view->frustum_corners, view->frustum_planes); + draw_frustum_bound_sphere_calc( + &view->frustum_corners, viewinv, winmat, wininv, &view->frustum_bsphere); + +#ifdef DRW_DEBUG_CULLING + if (G.debug_value != 0) { + DRW_debug_sphere( + view->frustum_bsphere.center, view->frustum_bsphere.radius, (const float[4]){1, 1, 0, 1}); + DRW_debug_bbox(&view->frustum_corners, (const float[4]){1, 1, 0, 1}); + } +#endif +} + +/* Return default view if it is a viewport render. */ +const DRWView *DRW_view_default_get(void) +{ + return DST.view_default; +} + +/* MUST only be called once per render and only in render mode. Sets default view. */ +void DRW_view_default_set(DRWView *view) +{ + BLI_assert(DST.view_default == NULL); + DST.view_default = view; +} + +/** + * This only works if DRWPasses have been tagged with DRW_STATE_CLIP_PLANES, + * and if the shaders have support for it (see usage of gl_ClipDistance). + * NOTE: planes must be in world space. + */ +void DRW_view_clip_planes_set(DRWView *view, float (*planes)[4], int plane_len) +{ + BLI_assert(plane_len <= MAX_CLIP_PLANES); + view->clip_planes_len = plane_len; + if (plane_len > 0) { + memcpy(view->storage.clipplanes, planes, sizeof(float) * 4 * plane_len); + } +} + +void DRW_view_camtexco_set(DRWView *view, float texco[4]) +{ + copy_v4_v4(view->storage.viewcamtexcofac, texco); +} + +/* Return world space frustum corners. */ +void DRW_view_frustum_corners_get(const DRWView *view, BoundBox *corners) +{ + memcpy(corners, &view->frustum_corners, sizeof(view->frustum_corners)); +} + +/* Return world space frustum sides as planes. + * See draw_frustum_culling_planes_calc() for the plane order. */ +void DRW_view_frustum_planes_get(const DRWView *view, float planes[6][4]) +{ + memcpy(planes, &view->frustum_planes, sizeof(view->frustum_planes)); +} + +bool DRW_view_is_persp_get(const DRWView *view) +{ + view = (view) ? view : DST.view_default; + return view->storage.winmat[3][3] == 0.0f; +} + +float DRW_view_near_distance_get(const DRWView *view) +{ + view = (view) ? view : DST.view_default; + const float(*projmat)[4] = view->storage.winmat; + + if (DRW_view_is_persp_get(view)) { + return -projmat[3][2] / (projmat[2][2] - 1.0f); + } + else { + return -(projmat[3][2] + 1.0f) / projmat[2][2]; + } +} + +float DRW_view_far_distance_get(const DRWView *view) +{ + view = (view) ? view : DST.view_default; + const float(*projmat)[4] = view->storage.winmat; + + if (DRW_view_is_persp_get(view)) { + return -projmat[3][2] / (projmat[2][2] + 1.0f); + } + else { + return -(projmat[3][2] - 1.0f) / projmat[2][2]; + } +} + +void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse) +{ + view = (view) ? view : DST.view_default; + const DRWViewUboStorage *storage = &view->storage; + copy_m4_m4(mat, (inverse) ? storage->viewinv : storage->viewmat); +} + +void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse) +{ + view = (view) ? view : DST.view_default; + const DRWViewUboStorage *storage = &view->storage; + copy_m4_m4(mat, (inverse) ? storage->wininv : storage->winmat); +} + +void DRW_view_persmat_get(const DRWView *view, float mat[4][4], bool inverse) +{ + view = (view) ? view : DST.view_default; + const DRWViewUboStorage *storage = &view->storage; + copy_m4_m4(mat, (inverse) ? storage->persinv : storage->persmat); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Passes (DRW_pass) * \{ */ @@ -1118,8 +1587,8 @@ void DRW_pass_foreach_shgroup(DRWPass *pass, } typedef struct ZSortData { - float *axis; - float *origin; + const float *axis; + const float *origin; } ZSortData; static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b) @@ -1182,8 +1651,7 @@ static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b) */ void DRW_pass_sort_shgroup_z(DRWPass *pass) { - float(*viewinv)[4]; - viewinv = DST.view_data.matstate.mat[DRW_MAT_VIEWINV]; + const float(*viewinv)[4] = DST.view_active->storage.viewinv; ZSortData zsortdata = {viewinv[2], viewinv[3]}; diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 2c29ce343dd..b232cfd01ad 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -238,7 +238,7 @@ void drw_state_set(DRWState state) int test; if ((test = CHANGED_TO(DRW_STATE_CLIP_PLANES))) { if (test == 1) { - for (int i = 0; i < DST.clip_planes_len; ++i) { + for (int i = 0; i < DST.view_active->clip_planes_len; ++i) { glEnable(GL_CLIP_DISTANCE0 + i); } } @@ -306,33 +306,6 @@ void drw_state_set(DRWState state) } } - /* Polygon Offset */ - { - int test; - if (CHANGED_ANY_STORE_VAR(DRW_STATE_OFFSET_POSITIVE | DRW_STATE_OFFSET_NEGATIVE, test)) { - if (test) { - glEnable(GL_POLYGON_OFFSET_FILL); - glEnable(GL_POLYGON_OFFSET_LINE); - glEnable(GL_POLYGON_OFFSET_POINT); - /* Stencil Write */ - if ((state & DRW_STATE_OFFSET_POSITIVE) != 0) { - glPolygonOffset(1.0f, 1.0f); - } - else if ((state & DRW_STATE_OFFSET_NEGATIVE) != 0) { - glPolygonOffset(-1.0f, -1.0f); - } - else { - BLI_assert(0); - } - } - else { - glDisable(GL_POLYGON_OFFSET_FILL); - glDisable(GL_POLYGON_OFFSET_LINE); - glDisable(GL_POLYGON_OFFSET_POINT); - } - } - } - #undef CHANGED_TO #undef CHANGED_ANY #undef CHANGED_ANY_STORE_VAR @@ -387,282 +360,34 @@ void DRW_state_reset(void) glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } -/** - * This only works if DRWPasses have been tagged with DRW_STATE_CLIP_PLANES, - * and if the shaders have support for it (see usage of gl_ClipDistance). - * Be sure to call DRW_state_clip_planes_reset() after you finish drawing. - */ -void DRW_state_clip_planes_len_set(uint plane_len) -{ - BLI_assert(plane_len <= MAX_CLIP_PLANES); - DST.clip_planes_len = plane_len; -} - -void DRW_state_clip_planes_reset(void) -{ - DST.clip_planes_len = 0; -} - -void DRW_state_clip_planes_set_from_rv3d(RegionView3D *rv3d) -{ - int max_len = 6; - int real_len = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : max_len; - while (real_len < max_len) { - /* Fill in dummy values that wont change results (6 is hard coded in shaders). */ - copy_v4_v4(rv3d->clip[real_len], rv3d->clip[3]); - real_len++; - } - - DRW_state_clip_planes_len_set(max_len); -} - /** \} */ /* -------------------------------------------------------------------- */ -/** \name Clipping (DRW_clipping) +/** \name Culling (DRW_culling) * \{ */ -/* Extract the 8 corners from a Projection Matrix. - * Although less accurate, this solution can be simplified as follows: - * BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const - * float[3]){1.0f, 1.0f, 1.0f}); for (int i = 0; i < 8; i++) {mul_project_m4_v3(projinv, - * bbox.vec[i]);} - */ -static void draw_frustum_boundbox_calc(const float (*projmat)[4], BoundBox *r_bbox) +static bool draw_call_is_culled(DRWCall *call, DRWView *view) { - float left, right, bottom, top, near, far; - bool is_persp = projmat[3][3] == 0.0f; - - projmat_dimensions(projmat, &left, &right, &bottom, &top, &near, &far); - - if (is_persp) { - left *= near; - right *= near; - bottom *= near; - top *= near; - } - - r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near; - r_bbox->vec[0][0] = r_bbox->vec[3][0] = left; - r_bbox->vec[4][0] = r_bbox->vec[7][0] = right; - r_bbox->vec[0][1] = r_bbox->vec[4][1] = bottom; - r_bbox->vec[7][1] = r_bbox->vec[3][1] = top; - - /* Get the coordinates of the far plane. */ - if (is_persp) { - float sca_far = far / near; - left *= sca_far; - right *= sca_far; - bottom *= sca_far; - top *= sca_far; - } - - r_bbox->vec[1][2] = r_bbox->vec[2][2] = r_bbox->vec[6][2] = r_bbox->vec[5][2] = -far; - r_bbox->vec[1][0] = r_bbox->vec[2][0] = left; - r_bbox->vec[6][0] = r_bbox->vec[5][0] = right; - r_bbox->vec[1][1] = r_bbox->vec[5][1] = bottom; - r_bbox->vec[2][1] = r_bbox->vec[6][1] = top; + return (call->state->culling->mask & view->culling_mask) != 0; } -static void draw_clipping_setup_from_view(void) +/* Set active view for rendering. */ +void DRW_view_set_active(DRWView *view) { - if (DST.clipping.updated) { - return; - } - - float(*viewinv)[4] = DST.view_data.matstate.mat[DRW_MAT_VIEWINV]; - float(*projmat)[4] = DST.view_data.matstate.mat[DRW_MAT_WIN]; - float(*projinv)[4] = DST.view_data.matstate.mat[DRW_MAT_WININV]; - BoundSphere *bsphere = &DST.clipping.frustum_bsphere; - - /* Extract Clipping Planes */ - BoundBox bbox; -#if 0 /* It has accuracy problems. */ - BKE_boundbox_init_from_minmax( - &bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f}); - for (int i = 0; i < 8; i++) { - mul_project_m4_v3(projinv, bbox.vec[i]); - } -#else - draw_frustum_boundbox_calc(projmat, &bbox); -#endif - /* Transform into world space. */ - for (int i = 0; i < 8; i++) { - mul_m4_v3(viewinv, bbox.vec[i]); - } - - memcpy(&DST.clipping.frustum_corners, &bbox, sizeof(BoundBox)); - - /* Compute clip planes using the world space frustum corners. */ - for (int p = 0; p < 6; p++) { - int q, r, s; - switch (p) { - case 0: - q = 1; - r = 2; - s = 3; - break; /* -X */ - case 1: - q = 0; - r = 4; - s = 5; - break; /* -Y */ - case 2: - q = 1; - r = 5; - s = 6; - break; /* +Z (far) */ - case 3: - q = 2; - r = 6; - s = 7; - break; /* +Y */ - case 4: - q = 0; - r = 3; - s = 7; - break; /* -Z (near) */ - default: - q = 4; - r = 7; - s = 6; - break; /* +X */ - } - if (DST.frontface == GL_CW) { - SWAP(int, q, s); - } - - normal_quad_v3( - DST.clipping.frustum_planes[p], bbox.vec[p], bbox.vec[q], bbox.vec[r], bbox.vec[s]); - /* Increase precision and use the mean of all 4 corners. */ - DST.clipping.frustum_planes[p][3] = -dot_v3v3(DST.clipping.frustum_planes[p], bbox.vec[p]); - DST.clipping.frustum_planes[p][3] += -dot_v3v3(DST.clipping.frustum_planes[p], bbox.vec[q]); - DST.clipping.frustum_planes[p][3] += -dot_v3v3(DST.clipping.frustum_planes[p], bbox.vec[r]); - DST.clipping.frustum_planes[p][3] += -dot_v3v3(DST.clipping.frustum_planes[p], bbox.vec[s]); - DST.clipping.frustum_planes[p][3] *= 0.25f; - } - - /* Extract Bounding Sphere */ - if (projmat[3][3] != 0.0f) { - /* Orthographic */ - /* The most extreme points on the near and far plane. (normalized device coords). */ - float *nearpoint = bbox.vec[0]; - float *farpoint = bbox.vec[6]; - - /* just use median point */ - mid_v3_v3v3(bsphere->center, farpoint, nearpoint); - bsphere->radius = len_v3v3(bsphere->center, farpoint); - } - else if (projmat[2][0] == 0.0f && projmat[2][1] == 0.0f) { - /* Perspective with symmetrical frustum. */ - - /* We obtain the center and radius of the circumscribed circle of the - * isosceles trapezoid composed by the diagonals of the near and far clipping plane */ - - /* center of each clipping plane */ - float mid_min[3], mid_max[3]; - mid_v3_v3v3(mid_min, bbox.vec[3], bbox.vec[4]); - mid_v3_v3v3(mid_max, bbox.vec[2], bbox.vec[5]); - - /* square length of the diagonals of each clipping plane */ - float a_sq = len_squared_v3v3(bbox.vec[3], bbox.vec[4]); - float b_sq = len_squared_v3v3(bbox.vec[2], bbox.vec[5]); - - /* distance squared between clipping planes */ - float h_sq = len_squared_v3v3(mid_min, mid_max); - - float fac = (4 * h_sq + b_sq - a_sq) / (8 * h_sq); - - /* The goal is to get the smallest sphere, - * not the sphere that passes through each corner */ - CLAMP(fac, 0.0f, 1.0f); - - interp_v3_v3v3(bsphere->center, mid_min, mid_max, fac); - - /* distance from the center to one of the points of the far plane (1, 2, 5, 6) */ - bsphere->radius = len_v3v3(bsphere->center, bbox.vec[1]); - } - else { - /* Perspective with asymmetrical frustum. */ - - /* We put the sphere center on the line that goes from origin - * to the center of the far clipping plane. */ - - /* Detect which of the corner of the far clipping plane is the farthest to the origin */ - float nfar[4]; /* most extreme far point in NDC space */ - float farxy[2]; /* farpoint projection onto the near plane */ - float farpoint[3] = {0.0f}; /* most extreme far point in camera coordinate */ - float nearpoint[3]; /* most extreme near point in camera coordinate */ - float farcenter[3] = {0.0f}; /* center of far cliping plane in camera coordinate */ - float F = -1.0f, N; /* square distance of far and near point to origin */ - float f, n; /* distance of far and near point to z axis. f is always > 0 but n can be < 0 */ - float e, s; /* far and near clipping distance (<0) */ - float c; /* slope of center line = distance of far clipping center - * to z axis / far clipping distance. */ - float z; /* projection of sphere center on z axis (<0) */ - - /* Find farthest corner and center of far clip plane. */ - float corner[3] = {1.0f, 1.0f, 1.0f}; /* in clip space */ - for (int i = 0; i < 4; i++) { - float point[3]; - mul_v3_project_m4_v3(point, projinv, corner); - float len = len_squared_v3(point); - if (len > F) { - copy_v3_v3(nfar, corner); - copy_v3_v3(farpoint, point); - F = len; - } - add_v3_v3(farcenter, point); - /* rotate by 90 degree to walk through the 4 points of the far clip plane */ - float tmp = corner[0]; - corner[0] = -corner[1]; - corner[1] = tmp; - } - - /* the far center is the average of the far clipping points */ - mul_v3_fl(farcenter, 0.25f); - /* the extreme near point is the opposite point on the near clipping plane */ - copy_v3_fl3(nfar, -nfar[0], -nfar[1], -1.0f); - mul_v3_project_m4_v3(nearpoint, projinv, nfar); - /* this is a frustum projection */ - N = len_squared_v3(nearpoint); - e = farpoint[2]; - s = nearpoint[2]; - /* distance to view Z axis */ - f = len_v2(farpoint); - /* get corresponding point on the near plane */ - mul_v2_v2fl(farxy, farpoint, s / e); - /* this formula preserve the sign of n */ - sub_v2_v2(nearpoint, farxy); - n = f * s / e - len_v2(nearpoint); - c = len_v2(farcenter) / e; - /* the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case */ - z = (F - N) / (2.0f * (e - s + c * (f - n))); - - bsphere->center[0] = farcenter[0] * z / e; - bsphere->center[1] = farcenter[1] * z / e; - bsphere->center[2] = z; - bsphere->radius = len_v3v3(bsphere->center, farpoint); - - /* Transform to world space. */ - mul_m4_v3(viewinv, bsphere->center); - } - - DST.clipping.updated = true; + DST.view_active = (view) ? view : DST.view_default; } /* Return True if the given BoundSphere intersect the current view frustum */ -bool DRW_culling_sphere_test(BoundSphere *bsphere) +static bool draw_culling_sphere_test(const BoundSphere *frustum_bsphere, + const float (*frustum_planes)[4], + const BoundSphere *bsphere) { - draw_clipping_setup_from_view(); - /* Bypass test if radius is negative. */ if (bsphere->radius < 0.0f) { return true; } /* Do a rough test first: Sphere VS Sphere intersect. */ - BoundSphere *frustum_bsphere = &DST.clipping.frustum_bsphere; float center_dist_sq = len_squared_v3v3(bsphere->center, frustum_bsphere->center); float radius_sum = bsphere->radius + frustum_bsphere->radius; if (center_dist_sq > SQUARE(radius_sum)) { @@ -674,26 +399,21 @@ bool DRW_culling_sphere_test(BoundSphere *bsphere) /* TODO order planes with sides first then far then near clip. Should be better culling * heuristic when sculpting. */ for (int p = 0; p < 6; p++) { - float dist = plane_point_side_v3(DST.clipping.frustum_planes[p], bsphere->center); + float dist = plane_point_side_v3(frustum_planes[p], bsphere->center); if (dist < -bsphere->radius) { return false; } } - return true; } -/* Return True if the given BoundBox intersect the current view frustum. - * bbox must be in world space. */ -bool DRW_culling_box_test(BoundBox *bbox) +static bool draw_culling_box_test(const float (*frustum_planes)[4], const BoundBox *bbox) { - draw_clipping_setup_from_view(); - /* 6 view frustum planes */ for (int p = 0; p < 6; p++) { /* 8 box vertices. */ for (int v = 0; v < 8; v++) { - float dist = plane_point_side_v3(DST.clipping.frustum_planes[p], bbox->vec[v]); + float dist = plane_point_side_v3(frustum_planes[p], bbox->vec[v]); if (dist > 0.0f) { /* At least one point in front of this plane. * Go to next plane. */ @@ -705,152 +425,162 @@ bool DRW_culling_box_test(BoundBox *bbox) } } } - return true; } -/* Return True if the current view frustum is inside or intersect the given plane */ -bool DRW_culling_plane_test(float plane[4]) +static bool draw_culling_plane_test(const BoundBox *corners, const float plane[4]) { - draw_clipping_setup_from_view(); - /* Test against the 8 frustum corners. */ for (int c = 0; c < 8; c++) { - float dist = plane_point_side_v3(plane, DST.clipping.frustum_corners.vec[c]); + float dist = plane_point_side_v3(plane, corners->vec[c]); if (dist < 0.0f) { return true; } } - return false; } -void DRW_culling_frustum_corners_get(BoundBox *corners) +/* Return True if the given BoundSphere intersect the current view frustum. + * bsphere must be in world space. */ +bool DRW_culling_sphere_test(const DRWView *view, const BoundSphere *bsphere) { - draw_clipping_setup_from_view(); - memcpy(corners, &DST.clipping.frustum_corners, sizeof(BoundBox)); + view = view ? view : DST.view_default; + return draw_culling_sphere_test(&view->frustum_bsphere, view->frustum_planes, bsphere); } -/* See draw_clipping_setup_from_view() for the plane order. */ -void DRW_culling_frustum_planes_get(float planes[6][4]) +/* Return True if the given BoundBox intersect the current view frustum. + * bbox must be in world space. */ +bool DRW_culling_box_test(const DRWView *view, const BoundBox *bbox) { - draw_clipping_setup_from_view(); - memcpy(planes, &DST.clipping.frustum_planes, sizeof(DST.clipping.frustum_planes)); + view = view ? view : DST.view_default; + return draw_culling_box_test(view->frustum_planes, bbox); } -/** \} */ +/* Return True if the view frustum is inside or intersect the given plane. + * plane must be in world space. */ +bool DRW_culling_plane_test(const DRWView *view, const float plane[4]) +{ + view = view ? view : DST.view_default; + return draw_culling_plane_test(&view->frustum_corners, plane); +} -/* -------------------------------------------------------------------- */ -/** \name Draw (DRW_draw) - * \{ */ +void DRW_culling_frustum_corners_get(const DRWView *view, BoundBox *corners) +{ + view = view ? view : DST.view_default; + *corners = view->frustum_corners; +} + +void DRW_culling_frustum_planes_get(const DRWView *view, float planes[6][4]) +{ + view = view ? view : DST.view_default; + memcpy(planes, view->frustum_planes, sizeof(float) * 6 * 4); +} -static void draw_visibility_eval(DRWCallState *st) +static void draw_compute_culling(DRWView *view) { - bool culled = st->flag & DRW_CALL_CULLED; + view = view->parent ? view->parent : view; - if (st->cache_id != DST.state_cache_id) { - /* Update culling result for this view. */ - culled = !DRW_culling_sphere_test(&st->bsphere); + /* TODO(fclem) multithread this. */ + /* TODO(fclem) compute all dirty views at once. */ + if (!view->is_dirty) { + return; } - if (st->visibility_cb) { - culled = !st->visibility_cb(!culled, st->user_data); + BLI_memblock_iter iter; + BLI_memblock_iternew(DST.vmempool->cullstates, &iter); + DRWCullingState *cull; + while ((cull = BLI_memblock_iterstep(&iter))) { + if (cull->bsphere.radius < 0.0) { + cull->mask = 0; + } + else { + bool culled = !draw_culling_sphere_test( + &view->frustum_bsphere, view->frustum_planes, &cull->bsphere); + +#ifdef DRW_DEBUG_CULLING + if (G.debug_value != 0) { + if (culled) { + DRW_debug_sphere( + cull->bsphere.center, cull->bsphere.radius, (const float[4]){1, 0, 0, 1}); + } + else { + DRW_debug_sphere( + cull->bsphere.center, cull->bsphere.radius, (const float[4]){0, 1, 0, 1}); + } + } +#endif + + if (view->visibility_fn) { + culled = !view->visibility_fn(!culled, cull->user_data); + } + + SET_FLAG_FROM_TEST(cull->mask, culled, view->culling_mask); + } } - SET_FLAG_FROM_TEST(st->flag, culled, DRW_CALL_CULLED); + view->is_dirty = false; } -static void draw_matrices_model_prepare(DRWCallState *st) +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Draw (DRW_draw) + * \{ */ + +static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call) { - if (st->cache_id == DST.state_cache_id) { - /* Values are already updated for this view. */ - return; + BLI_assert(call); + DRWCallState *state = call->state; + + if (shgroup->model != -1) { + GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)state->model); } - else { - st->cache_id = DST.state_cache_id; + if (shgroup->modelinverse != -1) { + GPU_shader_uniform_vector( + shgroup->shader, shgroup->modelinverse, 16, 1, (float *)state->modelinverse); } - - /* No need to go further the call will not be used. */ - if ((st->flag & DRW_CALL_CULLED) != 0 && (st->flag & DRW_CALL_BYPASS_CULLING) == 0) { - return; + 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 (st->matflag & DRW_CALL_MODELVIEWPROJECTION) { - mul_m4_m4m4(st->modelviewprojection, DST.view_data.matstate.mat[DRW_MAT_PERS], st->model); + if (shgroup->orcotexfac != -1) { + GPU_shader_uniform_vector( + shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac); + } + /* Still supported for compatibility with gpu_shader_* but should be forbidden + * and is slow (since it does not cache the result). */ + if (shgroup->modelviewprojection != -1) { + float mvp[4][4]; + mul_m4_m4m4(mvp, DST.view_active->storage.persmat, state->model); + GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)mvp); } } -static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call) +BLI_INLINE void draw_geometry_execute(DRWShadingGroup *shgroup, + GPUBatch *geom, + uint vert_first, + uint vert_count, + uint inst_first, + uint inst_count) { - /* step 1 : bind object dependent matrices */ - if (call != NULL) { - DRWCallState *state = call->state; + /* bind vertex array */ + if (DST.batch != geom) { + DST.batch = geom; - 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 { - /* For instancing and batching. */ - float unitmat[4][4]; - unit_m4(unitmat); + GPU_batch_program_set_no_use( + geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader)); - 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); - } + GPU_batch_bind(geom); } -} -static void draw_geometry_execute( - DRWShadingGroup *shgroup, GPUBatch *geom, uint start, uint count, bool draw_instance) -{ - /* 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)); /* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */ geom->program_in_use = true; - GPU_batch_draw_range_ex(geom, start, count, draw_instance); + GPU_batch_draw_advanced(geom, vert_first, vert_count, inst_first, inst_count); geom->program_in_use = false; /* XXX hacking gawain */ } @@ -863,7 +593,7 @@ enum { static void set_bound_flags(uint64_t *slots, uint64_t *persist_slots, int slot_idx, char bind_type) { - uint64_t slot = 1lu << (unsigned long)slot_idx; + uint64_t slot = 1llu << (unsigned long)slot_idx; *slots |= slot; if (bind_type == BIND_PERSIST) { *persist_slots |= slot; @@ -1023,6 +753,67 @@ static void release_ubo_slots(bool with_persist) } } +static void draw_update_uniforms(DRWShadingGroup *shgroup) +{ + for (DRWUniform *uni = shgroup->uniforms; uni; uni = uni->next) { + GPUTexture *tex; + GPUUniformBuffer *ubo; + if (uni->location == -2) { + uni->location = GPU_shader_get_uniform_ensure(shgroup->shader, + DST.uniform_names.buffer + uni->name_ofs); + if (uni->location == -1) { + 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_INT_COPY: + case DRW_UNIFORM_INT: + GPU_shader_uniform_vector_int( + shgroup->shader, uni->location, uni->length, uni->arraysize, data); + break; + case DRW_UNIFORM_FLOAT_COPY: + case DRW_UNIFORM_FLOAT: + GPU_shader_uniform_vector( + shgroup->shader, uni->location, uni->length, uni->arraysize, data); + break; + case DRW_UNIFORM_TEXTURE: + tex = (GPUTexture *)uni->pvalue; + BLI_assert(tex); + bind_texture(tex, BIND_TEMP); + GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); + break; + case DRW_UNIFORM_TEXTURE_PERSIST: + tex = (GPUTexture *)uni->pvalue; + BLI_assert(tex); + bind_texture(tex, BIND_PERSIST); + GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); + break; + case DRW_UNIFORM_TEXTURE_REF: + tex = *((GPUTexture **)uni->pvalue); + BLI_assert(tex); + bind_texture(tex, BIND_TEMP); + GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); + break; + case DRW_UNIFORM_BLOCK: + ubo = (GPUUniformBuffer *)uni->pvalue; + bind_ubo(ubo, BIND_TEMP); + GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); + break; + case DRW_UNIFORM_BLOCK_PERSIST: + ubo = (GPUUniformBuffer *)uni->pvalue; + bind_ubo(ubo, BIND_PERSIST); + GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); + break; + } + } + + BLI_assert(ubo_bindings_validate(shgroup)); +} + BLI_INLINE bool draw_select_do_call(DRWShadingGroup *shgroup, DRWCall *call) { #ifdef USE_GPU_SELECT @@ -1052,7 +843,12 @@ BLI_INLINE bool draw_select_do_call(DRWShadingGroup *shgroup, DRWCall *call) while (start < tot) { GPU_select_load_id(select_id[start]); - draw_geometry_execute(shgroup, call->batch, start, count, is_instancing); + if (is_instancing) { + draw_geometry_execute(shgroup, call->batch, 0, 0, start, count); + } + else { + draw_geometry_execute(shgroup, call->batch, start, count, 0, 0); + } start += count; } return true; @@ -1070,8 +866,6 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) { BLI_assert(shgroup->shader); - GPUTexture *tex; - GPUUniformBuffer *ubo; const bool shader_changed = (DST.shader != shgroup->shader); bool use_tfeedback = false; @@ -1081,6 +875,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) } GPU_shader_bind(shgroup->shader); DST.shader = shgroup->shader; + DST.batch = NULL; } if (shgroup->tfeedback_target != NULL) { @@ -1094,62 +889,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) drw_state_set((pass_state & shgroup->state_extra_disable) | shgroup->state_extra); drw_stencil_set(shgroup->stencil_mask); - /* Binding Uniform */ - for (DRWUniform *uni = shgroup->uniforms; uni; uni = uni->next) { - if (uni->location == -2) { - uni->location = GPU_shader_get_uniform_ensure(shgroup->shader, - DST.uniform_names.buffer + uni->name_ofs); - if (uni->location == -1) { - 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_INT_COPY: - case DRW_UNIFORM_INT: - GPU_shader_uniform_vector_int( - shgroup->shader, uni->location, uni->length, uni->arraysize, data); - break; - case DRW_UNIFORM_FLOAT_COPY: - case DRW_UNIFORM_FLOAT: - GPU_shader_uniform_vector( - shgroup->shader, uni->location, uni->length, uni->arraysize, data); - break; - case DRW_UNIFORM_TEXTURE: - tex = (GPUTexture *)uni->pvalue; - BLI_assert(tex); - bind_texture(tex, BIND_TEMP); - GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); - break; - case DRW_UNIFORM_TEXTURE_PERSIST: - tex = (GPUTexture *)uni->pvalue; - BLI_assert(tex); - bind_texture(tex, BIND_PERSIST); - GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); - break; - case DRW_UNIFORM_TEXTURE_REF: - tex = *((GPUTexture **)uni->pvalue); - BLI_assert(tex); - bind_texture(tex, BIND_TEMP); - GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); - break; - case DRW_UNIFORM_BLOCK: - ubo = (GPUUniformBuffer *)uni->pvalue; - bind_ubo(ubo, BIND_TEMP); - GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); - break; - case DRW_UNIFORM_BLOCK_PERSIST: - ubo = (GPUUniformBuffer *)uni->pvalue; - bind_ubo(ubo, BIND_PERSIST); - GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); - break; - } - } - - BLI_assert(ubo_bindings_validate(shgroup)); + draw_update_uniforms(shgroup); /* Rendering Calls */ { @@ -1157,12 +897,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) int callid = 0; for (DRWCall *call = shgroup->calls.first; call; call = call->next) { - /* OPTI/IDEA(clem): Do this preparation in another thread. */ - draw_visibility_eval(call->state); - draw_matrices_model_prepare(call->state); - - if ((call->state->flag & DRW_CALL_CULLED) != 0 && - (call->state->flag & DRW_CALL_BYPASS_CULLING) == 0) { + if (draw_call_is_culled(call, DST.view_active)) { continue; } @@ -1175,7 +910,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) /* Negative scale objects */ bool neg_scale = call->state->flag & DRW_CALL_NEGSCALE; if (neg_scale != prev_neg_scale) { - glFrontFace((neg_scale) ? DST.backface : DST.frontface); + glFrontFace((neg_scale) ? GL_CW : GL_CCW); prev_neg_scale = neg_scale; } @@ -1185,16 +920,11 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) 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); - } + draw_geometry_execute( + shgroup, call->batch, call->vert_first, call->vert_count, 0, call->inst_count); } /* Reset state */ - glFrontFace(DST.frontface); + glFrontFace(GL_CCW); } if (use_tfeedback) { @@ -1204,29 +934,13 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) static void drw_update_view(void) { - if (DST.dirty_mat) { - DST.state_cache_id++; - DST.dirty_mat = false; - - DRW_uniformbuffer_update(G_draw.view_ubo, &DST.view_data); - - /* Catch integer wrap around. */ - if (UNLIKELY(DST.state_cache_id == 0)) { - 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_memblock_iter iter; - DRWCallState *state; - BLI_memblock_iternew(DST.vmempool->states, &iter); - while ((state = BLI_memblock_iterstep(&iter))) { - state->cache_id = 0; - } - } + /* TODO(fclem) update a big UBO and only bind ranges here. */ + DRW_uniformbuffer_update(G_draw.view_ubo, &DST.view_active->storage); - /* TODO dispatch threads to compute matrices/culling */ - } + /* TODO get rid of this. */ + DST.view_storage_cpy = DST.view_active->storage; - draw_clipping_setup_from_view(); + draw_compute_culling(DST.view_active); } static void drw_draw_pass_ex(DRWPass *pass, @@ -1242,7 +956,11 @@ static void drw_draw_pass_ex(DRWPass *pass, BLI_assert(DST.buffer_finish_called && "DRW_render_instance_buffer_finish had not been called before drawing"); - drw_update_view(); + if (DST.view_previous != DST.view_active || DST.view_active->is_dirty) { + drw_update_view(); + DST.view_active->is_dirty = false; + DST.view_previous = DST.view_active; + } /* GPU_framebuffer_clear calls can change the state outside the DRW module. * Force reset the affected states to avoid problems later. */ diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c index 98b35cc60a4..d1ea8af86f2 100644 --- a/source/blender/draw/modes/edit_curve_mode.c +++ b/source/blender/draw/modes/edit_curve_mode.c @@ -112,10 +112,6 @@ static void EDIT_CURVE_engine_init(void *UNUSED(vedata)) const DRWContextState *draw_ctx = DRW_context_state_get(); EDIT_CURVE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } - const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; if (!sh_data->wire_sh) { @@ -172,7 +168,7 @@ static void EDIT_CURVE_wire_shgrp_create(EDIT_CURVE_Shaders *sh_data, DRWShadingGroup *grp = DRW_shgroup_create(sh_data->wire_sh, pass); DRW_shgroup_uniform_vec4(grp, "color", G_draw.block.colorWireEdit, 1); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } *wire_shgrp = grp; @@ -180,7 +176,7 @@ static void EDIT_CURVE_wire_shgrp_create(EDIT_CURVE_Shaders *sh_data, DRW_shgroup_uniform_vec4(grp, "color", G_draw.block.colorWireEdit, 1); DRW_shgroup_uniform_float_copy(grp, "normalSize", v3d->overlay.normals_length); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } *wire_normals_shgrp = grp; } @@ -233,7 +229,7 @@ static void EDIT_CURVE_cache_init(void *vedata) DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); DRW_shgroup_uniform_bool(grp, "showCurveHandles", &stl->g_data->show_handles, 1); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } stl->g_data->overlay_edge_shgrp = grp; @@ -242,7 +238,7 @@ static void EDIT_CURVE_cache_init(void *vedata) grp = DRW_shgroup_create(sh_data->overlay_vert_sh, psl->overlay_vert_pass); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } stl->g_data->overlay_vert_shgrp = grp; } @@ -334,8 +330,6 @@ static void EDIT_CURVE_draw_scene(void *vedata) /* Thoses passes don't write to depth and are AA'ed using other tricks. */ DRW_draw_pass(psl->overlay_edge_pass); DRW_draw_pass(psl->overlay_vert_pass); - - DRW_state_clip_planes_reset(); } /* Cleanup when destroying the engine. diff --git a/source/blender/draw/modes/edit_lattice_mode.c b/source/blender/draw/modes/edit_lattice_mode.c index 5604f7f27c1..3058c5c829c 100644 --- a/source/blender/draw/modes/edit_lattice_mode.c +++ b/source/blender/draw/modes/edit_lattice_mode.c @@ -139,9 +139,7 @@ static void EDIT_LATTICE_engine_init(void *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); EDIT_LATTICE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; if (!sh_data->wire) { @@ -186,7 +184,7 @@ static void EDIT_LATTICE_cache_init(void *vedata) DRW_STATE_DEPTH_LESS_EQUAL); stl->g_data->wire_shgrp = DRW_shgroup_create(sh_data->wire, psl->wire_pass); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->wire_shgrp, rv3d); + DRW_shgroup_state_enable(stl->g_data->wire_shgrp, DRW_STATE_CLIP_PLANES); } psl->vert_pass = DRW_pass_create("Lattice Verts", @@ -194,7 +192,7 @@ static void EDIT_LATTICE_cache_init(void *vedata) stl->g_data->vert_shgrp = DRW_shgroup_create(sh_data->overlay_vert, psl->vert_pass); DRW_shgroup_uniform_block(stl->g_data->vert_shgrp, "globalsBlock", G_draw.block_ubo); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->vert_shgrp, rv3d); + DRW_shgroup_state_enable(stl->g_data->vert_shgrp, DRW_STATE_CLIP_PLANES); } } } diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index 1bd94cbeecf..865e443b186 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -38,8 +38,6 @@ #include "BKE_editmesh.h" #include "BKE_object.h" -#include "BIF_glutil.h" - #include "BLI_dynstr.h" #include "BLI_string_utils.h" @@ -68,16 +66,25 @@ extern char datatoc_gpu_shader_flat_color_frag_glsl[]; extern char datatoc_gpu_shader_point_varying_color_frag_glsl[]; /* *********** LISTS *********** */ + +typedef struct EDIT_MESH_ComponentPassList { + struct DRWPass *faces; + struct DRWPass *faces_cage; + struct DRWPass *edges; + struct DRWPass *verts; +} EDIT_MESH_ComponentPassList; + typedef struct EDIT_MESH_PassList { struct DRWPass *weight_faces; struct DRWPass *depth_hidden_wire; struct DRWPass *depth_hidden_wire_in_front; - struct DRWPass *edit_face_overlay; - struct DRWPass *edit_face_overlay_in_front; - struct DRWPass *edit_face_in_front; - struct DRWPass *edit_face_occluded; + + EDIT_MESH_ComponentPassList edit_passes; + EDIT_MESH_ComponentPassList edit_passes_in_front; + struct DRWPass *mix_occlude; struct DRWPass *facefill_occlude; + struct DRWPass *facefill_occlude_cage; struct DRWPass *mesh_analysis_pass; struct DRWPass *normals; } EDIT_MESH_PassList; @@ -134,6 +141,14 @@ static struct { struct GPUTexture *occlude_wire_color_tx; } e_data = {{{NULL}}}; /* Engine data */ +typedef struct EDIT_MESH_ComponentShadingGroupList { + DRWShadingGroup *verts; + DRWShadingGroup *edges; + DRWShadingGroup *faces; + DRWShadingGroup *faces_cage; + DRWShadingGroup *facedots; +} EDIT_MESH_ComponentShadingGroupList; + typedef struct EDIT_MESH_PrivateData { /* weight */ DRWShadingGroup *fweights_shgrp; @@ -144,11 +159,8 @@ typedef struct EDIT_MESH_PrivateData { DRWShadingGroup *vnormals_shgrp; DRWShadingGroup *lnormals_shgrp; - DRWShadingGroup *vert_shgrp; - DRWShadingGroup *edge_shgrp; - DRWShadingGroup *face_shgrp; - DRWShadingGroup *face_cage_shgrp; - DRWShadingGroup *facedot_shgrp; + EDIT_MESH_ComponentShadingGroupList edit_shgrps; + EDIT_MESH_ComponentShadingGroupList edit_in_front_shgrps; DRWShadingGroup *vert_shgrp_in_front; DRWShadingGroup *edge_shgrp_in_front; @@ -157,8 +169,14 @@ typedef struct EDIT_MESH_PrivateData { DRWShadingGroup *facedot_shgrp_in_front; DRWShadingGroup *facefill_occluded_shgrp; + DRWShadingGroup *facefill_occluded_cage_shgrp; DRWShadingGroup *mesh_analysis_shgrp; + DRWView *view_faces; + DRWView *view_faces_cage; + DRWView *view_edges; + DRWView *view_wires; + int data_mask[4]; int ghost_ob; int edit_ob; @@ -172,6 +190,7 @@ typedef struct EDIT_MESH_PrivateData { static void EDIT_MESH_engine_init(void *vedata) { EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl; + EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl; const DRWContextState *draw_ctx = DRW_context_state_get(); EDIT_MESH_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; @@ -188,10 +207,6 @@ static void EDIT_MESH_engine_init(void *vedata) {GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_depth_tx), GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_color_tx)}); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } - const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; if (!sh_data->weight_face) { @@ -307,17 +322,27 @@ static void EDIT_MESH_engine_init(void *vedata) sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg); } + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Create view with depth offset */ + stl->g_data->view_faces = (DRWView *)DRW_view_default_get(); + stl->g_data->view_faces_cage = DRW_view_create_with_zoffset(draw_ctx->rv3d, 0.5f); + stl->g_data->view_edges = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f); + stl->g_data->view_wires = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.5f); + } } -static DRWPass *edit_mesh_create_overlay_pass(float *face_alpha, - int *data_mask, - bool do_edges, - DRWState statemod, - DRWShadingGroup **r_face_shgrp, - DRWShadingGroup **r_face_cage_shgrp, - DRWShadingGroup **r_facedot_shgrp, - DRWShadingGroup **r_edge_shgrp, - DRWShadingGroup **r_vert_shgrp) +static void edit_mesh_create_overlay_passes(float face_alpha, + int *data_mask, + bool do_edges, + DRWState statemod, + EDIT_MESH_ComponentPassList *passes, + EDIT_MESH_ComponentShadingGroupList *shgrps) { const DRWContextState *draw_ctx = DRW_context_state_get(); RegionView3D *rv3d = draw_ctx->rv3d; @@ -328,17 +353,6 @@ static DRWPass *edit_mesh_create_overlay_pass(float *face_alpha, const bool select_face = (tsettings->selectmode & SCE_SELECT_FACE) != 0; const bool select_edge = (tsettings->selectmode & SCE_SELECT_EDGE) != 0; - float winmat[4][4]; - float viewdist = rv3d->dist; - DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); - /* special exception for ortho camera (viewdist isnt used for perspective cameras) */ - if (rv3d->persp == RV3D_CAMOB && rv3d->is_persp == false) { - viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1])); - } - const float depth_ofs = bglPolygonOffsetCalc((float *)winmat, viewdist, 1.0f); - - DRWPass *pass = DRW_pass_create("Edit Mesh Face Overlay Pass", DRW_STATE_WRITE_COLOR | statemod); - DRWShadingGroup *grp; GPUShader *vert_sh = sh_data->overlay_vert; @@ -347,70 +361,67 @@ static DRWPass *edit_mesh_create_overlay_pass(float *face_alpha, GPUShader *facedot_sh = sh_data->overlay_facedot; /* Faces */ - if (select_face) { - grp = *r_facedot_shgrp = DRW_shgroup_create(facedot_sh, pass); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_state_enable(grp, DRW_STATE_WRITE_DEPTH); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); - } - } - - grp = *r_face_shgrp = DRW_shgroup_create(face_sh, pass); + passes->faces = DRW_pass_create("Edit Mesh Faces", DRW_STATE_WRITE_COLOR | statemod); + grp = shgrps->faces = DRW_shgroup_create(face_sh, passes->faces); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_float(grp, "faceAlphaMod", face_alpha, 1); + DRW_shgroup_uniform_float_copy(grp, "faceAlphaMod", face_alpha); DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1); - DRW_shgroup_uniform_float_copy(grp, "ofs", 0.0f); DRW_shgroup_uniform_bool_copy(grp, "selectFaces", select_face); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } /* Cage geom needs to be offseted to avoid Z-fighting. */ - grp = *r_face_cage_shgrp = DRW_shgroup_create_sub(*r_face_shgrp); - DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE); + passes->faces_cage = DRW_pass_create("Edit Mesh Faces Cage", DRW_STATE_WRITE_COLOR | statemod); + grp = shgrps->faces_cage = DRW_shgroup_create(face_sh, passes->faces_cage); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float_copy(grp, "faceAlphaMod", face_alpha); + DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1); + DRW_shgroup_uniform_bool_copy(grp, "selectFaces", select_face); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); + } /* Edges */ - grp = *r_edge_shgrp = DRW_shgroup_create(edge_sh, pass); + /* Change first vertex convention to match blender loop structure. */ + passes->edges = DRW_pass_create( + "Edit Mesh Edges", DRW_STATE_WRITE_COLOR | DRW_STATE_FIRST_VERTEX_CONVENTION | statemod); + grp = shgrps->edges = DRW_shgroup_create(edge_sh, passes->edges); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); DRW_shgroup_uniform_vec2(grp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1); DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1); - DRW_shgroup_uniform_bool_copy(grp, "doEdges", do_edges); - DRW_shgroup_uniform_float_copy(grp, "ofs", depth_ofs); - DRW_shgroup_uniform_bool_copy(grp, "selectEdges", select_edge); - - DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE); - /* To match blender loop structure. */ - DRW_shgroup_state_enable(grp, DRW_STATE_FIRST_VERTEX_CONVENTION); + DRW_shgroup_uniform_bool_copy(grp, "selectEdges", do_edges || select_edge); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } /* Verts */ + passes->verts = DRW_pass_create("Edit Mesh Verts", + (DRW_STATE_WRITE_COLOR | statemod) & ~DRW_STATE_BLEND); if (select_vert) { - grp = *r_vert_shgrp = DRW_shgroup_create(vert_sh, pass); + grp = shgrps->verts = DRW_shgroup_create(vert_sh, passes->verts); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); - DRW_shgroup_uniform_float_copy(grp, "ofs", depth_ofs * 1.5f); - DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE | DRW_STATE_WRITE_DEPTH); - DRW_shgroup_state_disable(grp, DRW_STATE_BLEND); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); + } + } + if (select_face) { + grp = shgrps->facedots = DRW_shgroup_create(facedot_sh, passes->verts); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_state_enable(grp, DRW_STATE_WRITE_DEPTH); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } } - - return pass; } -static float backwire_opacity; -static float face_mod; -static float size_normal; - static void EDIT_MESH_cache_init(void *vedata) { EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl; EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl; + EDIT_MESH_PrivateData *g_data = stl->g_data; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -419,70 +430,70 @@ static void EDIT_MESH_cache_init(void *vedata) Scene *scene = draw_ctx->scene; ToolSettings *tsettings = scene->toolsettings; EDIT_MESH_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - static float zero = 0.0f; - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - } - stl->g_data->ghost_ob = 0; - stl->g_data->edit_ob = 0; - stl->g_data->do_faces = true; - stl->g_data->do_edges = true; + bool do_occlude_wire = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0; + + g_data->ghost_ob = 0; + g_data->edit_ob = 0; + g_data->do_faces = true; + g_data->do_edges = true; - stl->g_data->do_zbufclip = XRAY_FLAG_ENABLED(v3d); + g_data->do_zbufclip = XRAY_FLAG_ENABLED(v3d); - stl->g_data->data_mask[0] = 0xFF; /* Face Flag */ - stl->g_data->data_mask[1] = 0xFF; /* Edge Flag */ - stl->g_data->data_mask[2] = 0xFF; /* Crease */ - stl->g_data->data_mask[3] = 0xFF; /* BWeight */ + g_data->data_mask[0] = 0xFF; /* Face Flag */ + g_data->data_mask[1] = 0xFF; /* Edge Flag */ + g_data->data_mask[2] = 0xFF; /* Crease */ + g_data->data_mask[3] = 0xFF; /* BWeight */ if (draw_ctx->object_edit->type == OB_MESH) { if (BKE_object_is_in_editmode(draw_ctx->object_edit)) { if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FREESTYLE_FACE) == 0) { - stl->g_data->data_mask[0] &= ~VFLAG_FACE_FREESTYLE; + g_data->data_mask[0] &= ~VFLAG_FACE_FREESTYLE; } if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACES) == 0) { - stl->g_data->data_mask[0] &= ~(VFLAG_FACE_SELECTED & VFLAG_FACE_FREESTYLE); - stl->g_data->do_faces = false; - stl->g_data->do_zbufclip = false; + g_data->data_mask[0] &= ~(VFLAG_FACE_SELECTED & VFLAG_FACE_FREESTYLE); + g_data->do_faces = false; + g_data->do_zbufclip = false; } if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_SEAMS) == 0) { - stl->g_data->data_mask[1] &= ~VFLAG_EDGE_SEAM; + g_data->data_mask[1] &= ~VFLAG_EDGE_SEAM; } if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_SHARP) == 0) { - stl->g_data->data_mask[1] &= ~VFLAG_EDGE_SHARP; + g_data->data_mask[1] &= ~VFLAG_EDGE_SHARP; } if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FREESTYLE_EDGE) == 0) { - stl->g_data->data_mask[1] &= ~VFLAG_EDGE_FREESTYLE; + g_data->data_mask[1] &= ~VFLAG_EDGE_FREESTYLE; } if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) { if ((tsettings->selectmode & SCE_SELECT_EDGE) == 0) { - stl->g_data->data_mask[1] &= ~(VFLAG_EDGE_ACTIVE & VFLAG_EDGE_SELECTED); - stl->g_data->do_edges = false; + g_data->do_edges = false; } } if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CREASES) == 0) { - stl->g_data->data_mask[2] = 0x0; + g_data->data_mask[2] = 0x0; } if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_BWEIGHTS) == 0) { - stl->g_data->data_mask[3] = 0x0; + g_data->data_mask[3] = 0x0; } } } + float backwire_opacity = v3d->overlay.backwire_opacity; + float size_normal = v3d->overlay.normals_length; + float face_mod = (do_occlude_wire || !g_data->do_faces) ? 0.0f : 1.0f; + { psl->weight_faces = DRW_pass_create( "Weight Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); - stl->g_data->fweights_shgrp = DRW_shgroup_create(sh_data->weight_face, psl->weight_faces); + g_data->fweights_shgrp = DRW_shgroup_create(sh_data->weight_face, psl->weight_faces); static float alpha = 1.0f; - DRW_shgroup_uniform_float(stl->g_data->fweights_shgrp, "opacity", &alpha, 1); - DRW_shgroup_uniform_texture(stl->g_data->fweights_shgrp, "colorramp", G_draw.weight_ramp); - DRW_shgroup_uniform_block(stl->g_data->fweights_shgrp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_float(g_data->fweights_shgrp, "opacity", &alpha, 1); + DRW_shgroup_uniform_texture(g_data->fweights_shgrp, "colorramp", G_draw.weight_ramp); + DRW_shgroup_uniform_block(g_data->fweights_shgrp, "globalsBlock", G_draw.block_ubo); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fweights_shgrp, rv3d); + DRW_shgroup_state_enable(g_data->fweights_shgrp, DRW_STATE_CLIP_PLANES); } } @@ -491,19 +502,18 @@ static void EDIT_MESH_cache_init(void *vedata) psl->depth_hidden_wire = DRW_pass_create("Depth Pass Hidden Wire", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK); - stl->g_data->depth_shgrp_hidden_wire = DRW_shgroup_create(sh_data->depth, - psl->depth_hidden_wire); + g_data->depth_shgrp_hidden_wire = DRW_shgroup_create(sh_data->depth, psl->depth_hidden_wire); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp_hidden_wire, rv3d); + DRW_shgroup_state_enable(g_data->depth_shgrp_hidden_wire, DRW_STATE_CLIP_PLANES); } psl->depth_hidden_wire_in_front = DRW_pass_create( "Depth Pass Hidden Wire In Front", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK); - stl->g_data->depth_shgrp_hidden_wire_in_front = DRW_shgroup_create( - sh_data->depth, psl->depth_hidden_wire_in_front); + g_data->depth_shgrp_hidden_wire_in_front = DRW_shgroup_create(sh_data->depth, + psl->depth_hidden_wire_in_front); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp_hidden_wire_in_front, rv3d); + DRW_shgroup_state_enable(g_data->depth_shgrp_hidden_wire_in_front, DRW_STATE_CLIP_PLANES); } } @@ -513,25 +523,25 @@ static void EDIT_MESH_cache_init(void *vedata) DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL); - stl->g_data->fnormals_shgrp = DRW_shgroup_create(sh_data->normals_face, psl->normals); - DRW_shgroup_uniform_float(stl->g_data->fnormals_shgrp, "normalSize", &size_normal, 1); - DRW_shgroup_uniform_vec4(stl->g_data->fnormals_shgrp, "color", G_draw.block.colorNormal, 1); + g_data->fnormals_shgrp = DRW_shgroup_create(sh_data->normals_face, psl->normals); + DRW_shgroup_uniform_float(g_data->fnormals_shgrp, "normalSize", &size_normal, 1); + DRW_shgroup_uniform_vec4(g_data->fnormals_shgrp, "color", G_draw.block.colorNormal, 1); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fnormals_shgrp, rv3d); + DRW_shgroup_state_enable(g_data->fnormals_shgrp, DRW_STATE_CLIP_PLANES); } - stl->g_data->vnormals_shgrp = DRW_shgroup_create(sh_data->normals, psl->normals); - DRW_shgroup_uniform_float(stl->g_data->vnormals_shgrp, "normalSize", &size_normal, 1); - DRW_shgroup_uniform_vec4(stl->g_data->vnormals_shgrp, "color", G_draw.block.colorVNormal, 1); + g_data->vnormals_shgrp = DRW_shgroup_create(sh_data->normals, psl->normals); + DRW_shgroup_uniform_float(g_data->vnormals_shgrp, "normalSize", &size_normal, 1); + DRW_shgroup_uniform_vec4(g_data->vnormals_shgrp, "color", G_draw.block.colorVNormal, 1); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->vnormals_shgrp, rv3d); + DRW_shgroup_state_enable(g_data->vnormals_shgrp, DRW_STATE_CLIP_PLANES); } - stl->g_data->lnormals_shgrp = DRW_shgroup_create(sh_data->normals_loop, psl->normals); - DRW_shgroup_uniform_float(stl->g_data->lnormals_shgrp, "normalSize", &size_normal, 1); - DRW_shgroup_uniform_vec4(stl->g_data->lnormals_shgrp, "color", G_draw.block.colorLNormal, 1); + g_data->lnormals_shgrp = DRW_shgroup_create(sh_data->normals_loop, psl->normals); + DRW_shgroup_uniform_float(g_data->lnormals_shgrp, "normalSize", &size_normal, 1); + DRW_shgroup_uniform_vec4(g_data->lnormals_shgrp, "color", G_draw.block.colorLNormal, 1); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->lnormals_shgrp, rv3d); + DRW_shgroup_state_enable(g_data->lnormals_shgrp, DRW_STATE_CLIP_PLANES); } } @@ -540,63 +550,66 @@ static void EDIT_MESH_cache_init(void *vedata) DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND; psl->mesh_analysis_pass = DRW_pass_create("Mesh Analysis", state); const bool is_vertex_color = scene->toolsettings->statvis.type == SCE_STATVIS_SHARP; - stl->g_data->mesh_analysis_shgrp = DRW_shgroup_create( + g_data->mesh_analysis_shgrp = DRW_shgroup_create( is_vertex_color ? sh_data->mesh_analysis_vertex : sh_data->mesh_analysis_face, psl->mesh_analysis_pass); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->mesh_analysis_shgrp, rv3d); + DRW_shgroup_state_enable(g_data->mesh_analysis_shgrp, DRW_STATE_CLIP_PLANES); } } /* For in front option */ - psl->edit_face_overlay_in_front = edit_mesh_create_overlay_pass( - &face_mod, - stl->g_data->data_mask, - stl->g_data->do_edges, - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND, - &stl->g_data->face_shgrp_in_front, - &stl->g_data->face_cage_shgrp_in_front, - &stl->g_data->facedot_shgrp_in_front, - &stl->g_data->edge_shgrp_in_front, - &stl->g_data->vert_shgrp_in_front); - - if (!stl->g_data->do_zbufclip) { - psl->edit_face_overlay = edit_mesh_create_overlay_pass(&face_mod, - stl->g_data->data_mask, - stl->g_data->do_edges, - DRW_STATE_DEPTH_LESS_EQUAL | - DRW_STATE_BLEND, - &stl->g_data->face_shgrp, - &stl->g_data->face_cage_shgrp, - &stl->g_data->facedot_shgrp, - &stl->g_data->edge_shgrp, - &stl->g_data->vert_shgrp); + edit_mesh_create_overlay_passes(face_mod, + g_data->data_mask, + g_data->do_edges, + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND, + &psl->edit_passes_in_front, + &g_data->edit_in_front_shgrps); + + if (!g_data->do_zbufclip) { + edit_mesh_create_overlay_passes(face_mod, + g_data->data_mask, + g_data->do_edges, + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND, + &psl->edit_passes, + &g_data->edit_shgrps); } else { /* We render all wires with depth and opaque to a new fbo and blend the result based on depth * values */ - psl->edit_face_occluded = edit_mesh_create_overlay_pass(&zero, - stl->g_data->data_mask, - stl->g_data->do_edges, - DRW_STATE_DEPTH_LESS_EQUAL | - DRW_STATE_WRITE_DEPTH, - &stl->g_data->face_shgrp, - &stl->g_data->face_cage_shgrp, - &stl->g_data->facedot_shgrp, - &stl->g_data->edge_shgrp, - &stl->g_data->vert_shgrp); - - /* however we loose the front faces value (because we need the depth of occluded wires and - * faces are alpha blended ) so we recover them in a new pass. */ - psl->facefill_occlude = DRW_pass_create( - "Front Face Color", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); - stl->g_data->facefill_occluded_shgrp = DRW_shgroup_create(sh_data->overlay_facefill, - psl->facefill_occlude); - DRW_shgroup_uniform_block( - stl->g_data->facefill_occluded_shgrp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_ivec4( - stl->g_data->facefill_occluded_shgrp, "dataMask", stl->g_data->data_mask, 1); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->facefill_occluded_shgrp, rv3d); + edit_mesh_create_overlay_passes(0.0f, + g_data->data_mask, + g_data->do_edges, + DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH, + &psl->edit_passes, + &g_data->edit_shgrps); + + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND; + psl->facefill_occlude = DRW_pass_create("Front Face Color", state); + psl->facefill_occlude_cage = DRW_pass_create("Front Face Cage Color", state); + + if (g_data->do_faces) { + DRWShadingGroup *shgrp; + + /* however we loose the front faces value (because we need the depth of occluded wires and + * faces are alpha blended ) so we recover them in a new pass. */ + shgrp = g_data->facefill_occluded_shgrp = DRW_shgroup_create(sh_data->overlay_facefill, + psl->facefill_occlude); + DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_ivec4(shgrp, "dataMask", g_data->data_mask, 1); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); + } + + shgrp = g_data->facefill_occluded_cage_shgrp = DRW_shgroup_create( + sh_data->overlay_facefill, psl->facefill_occlude_cage); + DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_ivec4(shgrp, "dataMask", g_data->data_mask, 1); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); + } + } + else { + g_data->facefill_occluded_shgrp = NULL; } /* we need a full screen pass to combine the result */ @@ -606,11 +619,26 @@ static void EDIT_MESH_cache_init(void *vedata) DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); DRWShadingGroup *mix_shgrp = DRW_shgroup_create(sh_data->overlay_mix, psl->mix_occlude); DRW_shgroup_call(mix_shgrp, quad, NULL); - DRW_shgroup_uniform_float(mix_shgrp, "alpha", &backwire_opacity, 1); + DRW_shgroup_uniform_float_copy(mix_shgrp, "alpha", backwire_opacity); 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); DRW_shgroup_uniform_texture_ref(mix_shgrp, "sceneDepth", &dtxl->depth); } + + bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0; + + if (g_data->do_faces == false && g_data->do_edges == false && + (tsettings->selectmode & SCE_SELECT_FACE)) { + /* Force display of face centers in this case because that's + * the only way to see if a face is selected. */ + show_face_dots = true; + } + + /* HACK: set pointers to NULL even if generated. */ + if (!show_face_dots) { + g_data->edit_shgrps.facedots = NULL; + g_data->edit_in_front_shgrps.facedots = NULL; + } } static void edit_mesh_add_ob_to_pass(Scene *scene, @@ -619,8 +647,7 @@ static void edit_mesh_add_ob_to_pass(Scene *scene, DRWShadingGroup *edge_shgrp, DRWShadingGroup *face_shgrp, DRWShadingGroup *face_cage_shgrp, - DRWShadingGroup *facedot_shgrp, - DRWShadingGroup *facefill_shgrp) + DRWShadingGroup *facedot_shgrp) { struct GPUBatch *geom_tris, *geom_verts, *geom_edges, *geom_fcenter; ToolSettings *tsettings = scene->toolsettings; @@ -634,7 +661,6 @@ static void edit_mesh_add_ob_to_pass(Scene *scene, } face_shgrp = (has_edit_mesh_cage) ? face_cage_shgrp : face_shgrp; - face_shgrp = (facefill_shgrp != NULL) ? facefill_shgrp : face_shgrp; geom_tris = DRW_mesh_batch_cache_get_edit_triangles(ob->data); geom_edges = DRW_mesh_batch_cache_get_edit_edges(ob->data); @@ -659,7 +685,6 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob) const DRWContextState *draw_ctx = DRW_context_state_get(); View3D *v3d = draw_ctx->v3d; Scene *scene = draw_ctx->scene; - ToolSettings *tsettings = scene->toolsettings; struct GPUBatch *geom; if (ob->type == OB_MESH) { @@ -672,25 +697,6 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob) bool vnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_VERT_NORMALS) != 0; bool lnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_LOOP_NORMALS) != 0; - bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0; - - if (g_data->do_faces == false && g_data->do_edges == false && - (tsettings->selectmode & SCE_SELECT_FACE)) { - /* Force display of face centers in this case because that's - * the only way to see if a face is selected. */ - show_face_dots = true; - } - - /* Updating uniform */ - backwire_opacity = v3d->overlay.backwire_opacity; - size_normal = v3d->overlay.normals_length; - - face_mod = (do_occlude_wire) ? 0.0f : 1.0f; - - if (!g_data->do_faces) { - face_mod = 0.0f; - } - if (do_show_weight) { geom = DRW_cache_mesh_surface_weights_get(ob); DRW_shgroup_call(g_data->fweights_shgrp, geom, ob->obmat); @@ -733,32 +739,29 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob) if (g_data->do_zbufclip) { edit_mesh_add_ob_to_pass(scene, ob, - g_data->vert_shgrp, - g_data->edge_shgrp, - g_data->face_shgrp, - g_data->face_cage_shgrp, - g_data->facedot_shgrp, - (g_data->do_faces) ? g_data->facefill_occluded_shgrp : NULL); + g_data->edit_shgrps.verts, + g_data->edit_shgrps.edges, + g_data->facefill_occluded_shgrp, + g_data->facefill_occluded_cage_shgrp, + g_data->edit_shgrps.facedots); } else if (do_in_front) { edit_mesh_add_ob_to_pass(scene, ob, - g_data->vert_shgrp_in_front, - g_data->edge_shgrp_in_front, - g_data->face_shgrp_in_front, - g_data->face_cage_shgrp_in_front, - (show_face_dots) ? g_data->facedot_shgrp_in_front : NULL, - NULL); + g_data->edit_in_front_shgrps.verts, + g_data->edit_in_front_shgrps.edges, + g_data->edit_in_front_shgrps.faces, + g_data->edit_in_front_shgrps.faces_cage, + g_data->edit_in_front_shgrps.facedots); } else { edit_mesh_add_ob_to_pass(scene, ob, - g_data->vert_shgrp, - g_data->edge_shgrp, - g_data->face_shgrp, - g_data->face_cage_shgrp, - (show_face_dots) ? g_data->facedot_shgrp : NULL, - NULL); + g_data->edit_shgrps.verts, + g_data->edit_shgrps.edges, + g_data->edit_shgrps.faces, + g_data->edit_shgrps.faces_cage, + g_data->edit_shgrps.facedots); } g_data->ghost_ob += (ob->dtx & OB_DRAWXRAY) ? 1 : 0; @@ -776,6 +779,24 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob) } } +static void edit_mesh_draw_components(EDIT_MESH_ComponentPassList *passes, + EDIT_MESH_PrivateData *g_data) +{ + DRW_view_set_active(g_data->view_faces); + DRW_draw_pass(passes->faces); + + DRW_view_set_active(g_data->view_faces_cage); + DRW_draw_pass(passes->faces_cage); + + DRW_view_set_active(g_data->view_edges); + DRW_draw_pass(passes->edges); + + DRW_view_set_active(g_data->view_wires); + DRW_draw_pass(passes->verts); + + DRW_view_set_active(NULL); +} + static void EDIT_MESH_draw_scene(void *vedata) { EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl; @@ -794,13 +815,20 @@ static void EDIT_MESH_draw_scene(void *vedata) DRW_draw_pass(psl->depth_hidden_wire_in_front); /* render facefill */ + DRW_view_set_active(stl->g_data->view_faces); DRW_draw_pass(psl->facefill_occlude); + DRW_view_set_active(stl->g_data->view_faces_cage); + DRW_draw_pass(psl->facefill_occlude_cage); + + DRW_view_set_active(NULL); + /* Render wires on a separate framebuffer */ GPU_framebuffer_bind(fbl->occlude_wire_fb); GPU_framebuffer_clear_color_depth(fbl->occlude_wire_fb, clearcol, 1.0f); DRW_draw_pass(psl->normals); - DRW_draw_pass(psl->edit_face_occluded); + + edit_mesh_draw_components(&psl->edit_passes, stl->g_data); /* Combine with scene buffer */ GPU_framebuffer_bind(dfbl->color_only_fb); @@ -811,7 +839,7 @@ static void EDIT_MESH_draw_scene(void *vedata) View3D *v3d = draw_ctx->v3d; DRW_draw_pass(psl->normals); - DRW_draw_pass(psl->edit_face_overlay); + edit_mesh_draw_components(&psl->edit_passes, stl->g_data); if (v3d->shading.type == OB_SOLID && !XRAY_FLAG_ENABLED(v3d) && stl->g_data->ghost_ob == 1 && stl->g_data->edit_ob == 1) { @@ -822,10 +850,8 @@ static void EDIT_MESH_draw_scene(void *vedata) } DRW_draw_pass(psl->depth_hidden_wire_in_front); - DRW_draw_pass(psl->edit_face_overlay_in_front); + edit_mesh_draw_components(&psl->edit_passes_in_front, stl->g_data); } - - DRW_state_clip_planes_reset(); } static void EDIT_MESH_engine_free(void) diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c index 1dc6bd84fa1..82b1ddbd66d 100644 --- a/source/blender/draw/modes/edit_metaball_mode.c +++ b/source/blender/draw/modes/edit_metaball_mode.c @@ -93,14 +93,6 @@ typedef struct EDIT_METABALL_PrivateData { /* *********** FUNCTIONS *********** */ -static void EDIT_METABALL_engine_init(void *UNUSED(vedata)) -{ - const DRWContextState *draw_ctx = DRW_context_state_get(); - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } -} - /* Here init all passes and shading groups * Assume that all Passes are NULL */ static void EDIT_METABALL_cache_init(void *vedata) @@ -209,11 +201,6 @@ static void EDIT_METABALL_draw_scene(void *vedata) EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl; /* render passes on default framebuffer. */ DRW_draw_pass(psl->pass); - - /* If you changed framebuffer, double check you rebind - * the default one with its textures attached before finishing */ - - DRW_state_clip_planes_reset(); } /* Cleanup when destroying the engine. @@ -232,7 +219,7 @@ DrawEngineType draw_engine_edit_metaball_type = { NULL, N_("EditMetaballMode"), &EDIT_METABALL_data_size, - &EDIT_METABALL_engine_init, + NULL, &EDIT_METABALL_engine_free, &EDIT_METABALL_cache_init, &EDIT_METABALL_cache_populate, diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 3407aeee302..58bfa2f23cc 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -531,7 +531,7 @@ static void OBJECT_engine_init(void *vedata) { /* Grid precompute */ - float invviewmat[4][4], invwinmat[4][4]; + float viewinv[4][4], wininv[4][4]; float viewmat[4][4], winmat[4][4]; View3D *v3d = draw_ctx->v3d; Scene *scene = draw_ctx->scene; @@ -546,10 +546,10 @@ static void OBJECT_engine_init(void *vedata) const bool show_ortho_grid = (v3d->gridflag & V3D_SHOW_ORTHO_GRID) != 0; e_data.draw_grid = show_axis_x || show_axis_y || show_axis_z || show_floor; - DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); - DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); - DRW_viewport_matrix_get(invwinmat, DRW_MAT_WININV); - DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); + DRW_view_winmat_get(NULL, winmat, false); + DRW_view_winmat_get(NULL, wininv, true); + DRW_view_viewmat_get(NULL, viewmat, false); + DRW_view_viewmat_get(NULL, viewinv, true); /* if perps */ if (winmat[3][3] == 0.0f) { @@ -561,7 +561,7 @@ static void OBJECT_engine_init(void *vedata) /* convert the view vectors to view space */ for (int i = 0; i < 2; i++) { - mul_m4_v4(invwinmat, viewvecs[i]); + mul_m4_v4(wininv, viewvecs[i]); mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); /* perspective divide */ } @@ -623,8 +623,8 @@ static void OBJECT_engine_init(void *vedata) e_data.zpos_flag = SHOW_AXIS_Z; float zvec[3], campos[3]; - negate_v3_v3(zvec, invviewmat[2]); - copy_v3_v3(campos, invviewmat[3]); + negate_v3_v3(zvec, viewinv[2]); + copy_v3_v3(campos, viewinv[3]); /* z axis : chose the most facing plane */ if (fabsf(zvec[0]) < fabsf(zvec[1])) { @@ -708,7 +708,7 @@ static DRWShadingGroup *shgroup_outline(DRWPass *pass, DRW_shgroup_uniform_int(grp, "baseId", ofs, 1); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return grp; } @@ -723,7 +723,7 @@ static DRWShadingGroup *shgroup_wire(DRWPass *pass, DRW_shgroup_uniform_vec4(grp, "color", col, 1); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return grp; } @@ -739,7 +739,7 @@ static DRWShadingGroup *shgroup_points(DRWPass *pass, DRW_shgroup_uniform_vec4(grp, "innerColor", G_draw.block.colorEditMeshMiddle, 1); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } return grp; } @@ -1016,7 +1016,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data, DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1); DRW_shgroup_uniform_vec3(grp, "color", color, 1); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } DRW_shgroup_call(grp, DRW_cache_image_plane_wire_get(), ob->obmat); } @@ -1036,7 +1036,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data, DRW_shgroup_uniform_vec4(grp, "objectColor", ob->color, 1); DRW_shgroup_uniform_bool_copy(grp, "useAlphaTest", !use_alpha_blend); if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } DRW_shgroup_call(grp, DRW_cache_image_plane_get(), ob->obmat); } @@ -1404,7 +1404,7 @@ static void OBJECT_cache_init(void *vedata) DRW_shgroup_uniform_vec4(grp, "color", gb->colorLightNoAlpha, 1); DRW_shgroup_uniform_float(grp, "size", &gb->sizeLightCenter, 1); if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } sgl->light_center = buffer_dynpoints_uniform_color(grp); @@ -1492,7 +1492,7 @@ static void OBJECT_cache_init(void *vedata) 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); + DRW_shgroup_state_enable(grp_transp, DRW_STATE_CLIP_PLANES); } DRWShadingGroup *grp_cull_back = DRW_shgroup_create_sub(grp_transp); @@ -1544,7 +1544,7 @@ static void OBJECT_cache_init(void *vedata) DRW_shgroup_uniform_vec4(grp, "color", gb->colorActive, 1); DRW_shgroup_uniform_vec4(grp, "outlineColor", gb->colorOutline, 1); if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d); + DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES); } /* TODO find better name. */ stl->g_data->center_active = buffer_dynpoints_uniform_color(grp); @@ -2134,29 +2134,31 @@ static void DRW_shgroup_camera(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLay cam->runtime.drw_tria[1][1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]); if (look_through) { - /* Only draw the frame. */ - float mat[4][4]; - if (is_multiview) { - const bool is_left = v3d->multiview_eye == STEREO_LEFT_ID; - const char *view_name = is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME; - BKE_camera_multiview_model_matrix(&scene->r, ob, view_name, mat); - const float shiftx = BKE_camera_multiview_shift_x(&scene->r, ob, view_name); - const float delta_shiftx = shiftx - cam->shiftx; - const float width = cam->runtime.drw_corners[0][2][0] - cam->runtime.drw_corners[0][0][0]; - for (int i = 0; i < 4; i++) { - cam->runtime.drw_corners[0][i][0] -= delta_shiftx * width; + if (!DRW_state_is_image_render()) { + /* Only draw the frame. */ + float mat[4][4]; + if (is_multiview) { + const bool is_left = v3d->multiview_eye == STEREO_LEFT_ID; + const char *view_name = is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME; + BKE_camera_multiview_model_matrix(&scene->r, ob, view_name, mat); + const float shiftx = BKE_camera_multiview_shift_x(&scene->r, ob, view_name); + const float delta_shiftx = shiftx - cam->shiftx; + const float width = cam->runtime.drw_corners[0][2][0] - cam->runtime.drw_corners[0][0][0]; + for (int i = 0; i < 4; i++) { + cam->runtime.drw_corners[0][i][0] -= delta_shiftx * width; + } + } + else { + copy_m4_m4(mat, ob->obmat); } - } - else { - copy_m4_m4(mat, ob->obmat); - } - DRW_buffer_add_entry(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) { @@ -2437,12 +2439,11 @@ static void DRW_shgroup_volume_extra(OBJECT_ShadingGroupList *sgl, if (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED && sds->axis_slice_method == AXIS_SLICE_SINGLE) { - float invviewmat[4][4]; - DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); + float viewinv[4][4]; + DRW_view_viewmat_get(NULL, viewinv, true); - const int axis = (sds->slice_axis == SLICE_AXIS_AUTO) ? - axis_dominant_v3_single(invviewmat[2]) : - sds->slice_axis - 1; + const int axis = (sds->slice_axis == SLICE_AXIS_AUTO) ? axis_dominant_v3_single(viewinv[2]) : + sds->slice_axis - 1; slice_axis = axis; line_count /= sds->res[axis]; } diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c index 36493c5eff5..6e484d3bcc0 100644 --- a/source/blender/draw/modes/overlay_mode.c +++ b/source/blender/draw/modes/overlay_mode.c @@ -71,6 +71,7 @@ typedef struct OVERLAY_Data { typedef struct OVERLAY_PrivateData { DRWShadingGroup *face_orientation_shgrp; DRWShadingGroup *face_wires_shgrp; + DRWView *view_wires; BLI_mempool *wire_color_mempool; View3DOverlay overlay; float wire_step_param; @@ -111,10 +112,6 @@ static void overlay_engine_init(void *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } - if (!stl->g_data) { /* Alloc transient pointers */ stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); @@ -167,6 +164,8 @@ static void overlay_engine_init(void *vedata) }); #endif } + + stl->g_data->view_wires = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f); } static void overlay_cache_init(void *vedata) @@ -211,19 +210,19 @@ static void overlay_cache_init(void *vedata) g_data->face_orientation_shgrp = DRW_shgroup_create(sh_data->face_orientation, psl->face_orientation_pass); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_orientation_shgrp, rv3d); + DRW_shgroup_state_enable(g_data->face_orientation_shgrp, DRW_STATE_CLIP_PLANES); } } { /* Wireframe */ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | - DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_OFFSET_NEGATIVE; + DRW_STATE_FIRST_VERTEX_CONVENTION; float wire_size = U.pixelsize * 0.5f; float winmat[4][4]; float viewdist = rv3d->dist; - DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); + DRW_view_winmat_get(NULL, winmat, false); /* special exception for ortho camera (viewdist isnt used for perspective cameras) */ if (rv3d->persp == RV3D_CAMOB && rv3d->is_persp == false) { viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1])); @@ -247,7 +246,7 @@ static void overlay_cache_init(void *vedata) g_data->face_wires_shgrp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1); } if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_wires_shgrp, rv3d); + DRW_shgroup_state_enable(g_data->face_wires_shgrp, DRW_STATE_CLIP_PLANES); } g_data->wire_step_param = stl->g_data->overlay.wireframe_threshold - 254.0f / 255.0f; @@ -493,8 +492,11 @@ static void overlay_draw_scene(void *vedata) DRW_stats_query_end(); } + DRW_view_set_active(stl->g_data->view_wires); DRW_draw_pass(psl->face_wireframe_pass); + DRW_view_set_active(NULL); + /* TODO(fclem): find a way to unify the multisample pass together * (non meshes + armature + wireframe) */ MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl); diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c index 847d2d2f8aa..a27895f6ce8 100644 --- a/source/blender/draw/modes/paint_texture_mode.c +++ b/source/blender/draw/modes/paint_texture_mode.c @@ -128,14 +128,17 @@ typedef struct PAINT_TEXTURE_PrivateData { /* face-mask */ DRWShadingGroup *lwire_select_shgrp; DRWShadingGroup *face_select_shgrp; + + DRWView *view_wires; } PAINT_TEXTURE_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ /* Init Textures, Framebuffers, Storage and Shaders. * It is called for every frames. */ -static void PAINT_TEXTURE_engine_init(void *UNUSED(vedata)) +static void PAINT_TEXTURE_engine_init(void *vedata) { + PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; const DRWContextState *draw_ctx = DRW_context_state_get(); PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; @@ -154,6 +157,16 @@ static void PAINT_TEXTURE_engine_init(void *UNUSED(vedata)) .defs = (const char *[]){sh_cfg_data->def, NULL}, }); + sh_data->image_mask = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_globals_lib_glsl, + datatoc_common_view_lib_glsl, + datatoc_paint_texture_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_paint_texture_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define TEXTURE_PAINT_MASK\n", NULL}, + }); + sh_data->wire_select_overlay = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, datatoc_common_globals_lib_glsl, @@ -175,6 +188,14 @@ static void PAINT_TEXTURE_engine_init(void *UNUSED(vedata)) .defs = (const char *[]){sh_cfg_data->def, NULL}, }); } + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + stl->g_data->shgroup_image_array = NULL; + } + + stl->g_data->view_wires = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f); } static DRWShadingGroup *create_texture_paint_shading_group(PAINT_TEXTURE_PassList *psl, @@ -212,12 +233,6 @@ static void PAINT_TEXTURE_cache_init(void *vedata) PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - stl->g_data->shgroup_image_array = NULL; - } - const DRWContextState *draw_ctx = DRW_context_state_get(); PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; @@ -233,7 +248,7 @@ static void PAINT_TEXTURE_cache_init(void *vedata) DRW_shgroup_uniform_vec4(shgrp, "color", color, 1); if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, draw_ctx->rv3d); + DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); } psl->image_faces = pass; stl->g_data->shgroup_fallback = shgrp; @@ -286,31 +301,29 @@ static void PAINT_TEXTURE_cache_init(void *vedata) /* Face Mask */ { - DRWPass *pass = DRW_pass_create("Wire Mask Pass", - (DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE)); + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + DRWPass *pass = DRW_pass_create("Wire Mask Pass", state); DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->wire_select_overlay, pass); DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, draw_ctx->rv3d); + DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); } psl->wire_select_overlay = pass; stl->g_data->lwire_select_shgrp = shgrp; } { - - DRWPass *pass = DRW_pass_create("Face Mask Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND); + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND; + DRWPass *pass = DRW_pass_create("Face Mask Pass", state); DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->face_select_overlay, pass); static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f}; DRW_shgroup_uniform_vec4(shgrp, "color", col, 1); if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, draw_ctx->rv3d); + DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); } psl->face_select_overlay = pass; stl->g_data->face_select_shgrp = shgrp; @@ -395,6 +408,7 @@ static void PAINT_TEXTURE_draw_scene(void *vedata) { PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl; PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl; + PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl; /* Default framebuffer and texture */ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); @@ -405,7 +419,11 @@ static void PAINT_TEXTURE_draw_scene(void *vedata) DRW_draw_pass(psl->image_faces); DRW_draw_pass(psl->face_select_overlay); + + DRW_view_set_active(stl->g_data->view_wires); DRW_draw_pass(psl->wire_select_overlay); + + DRW_view_set_active(NULL); } /* Cleanup when destroying the engine. diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c index da76573a7e4..051f57fd9e0 100644 --- a/source/blender/draw/modes/paint_vertex_mode.c +++ b/source/blender/draw/modes/paint_vertex_mode.c @@ -100,18 +100,17 @@ typedef struct PAINT_VERTEX_PrivateData { } by_mode[MODE_LEN]; DRWShadingGroup *face_select_shgrp; DRWShadingGroup *vert_select_shgrp; + DRWView *view_wires; } PAINT_VERTEX_PrivateData; /* Transient data */ /* *********** FUNCTIONS *********** */ -static void PAINT_VERTEX_engine_init(void *UNUSED(vedata)) +static void PAINT_VERTEX_engine_init(void *vedata) { + PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl; const DRWContextState *draw_ctx = DRW_context_state_get(); PAINT_VERTEX_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { - DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); - } const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; if (!sh_data->face_select_overlay) { @@ -178,6 +177,13 @@ static void PAINT_VERTEX_engine_init(void *UNUSED(vedata)) }); } } + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + stl->g_data->view_wires = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f); } static void PAINT_VERTEX_cache_init(void *vedata) @@ -189,11 +195,6 @@ static void PAINT_VERTEX_cache_init(void *vedata) const RegionView3D *rv3d = draw_ctx->rv3d; PAINT_VERTEX_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - if (!stl->g_data) { - /* Alloc transient pointers */ - stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); - } - /* Vertex color pass */ { DRWPass *pass = DRW_pass_create( @@ -202,7 +203,7 @@ static void PAINT_VERTEX_cache_init(void *vedata) DRW_shgroup_uniform_float_copy( shgrp, "white_factor", 1.0f - v3d->overlay.vertex_paint_mode_opacity); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); + DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); } psl->by_mode[VERTEX_MODE].color_faces = pass; stl->g_data->by_mode[VERTEX_MODE].color_shgrp = shgrp; @@ -219,21 +220,20 @@ static void PAINT_VERTEX_cache_init(void *vedata) DRW_shgroup_uniform_texture(shgrp, "colorramp", G_draw.weight_ramp); DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); + DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); } psl->by_mode[WEIGHT_MODE].color_faces = pass; stl->g_data->by_mode[WEIGHT_MODE].color_shgrp = shgrp; } { - DRWPass *pass = DRW_pass_create("Wire Pass", - DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE); + DRWPass *pass = DRW_pass_create( + "Wire Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL); for (int i = 0; i < MODE_LEN; i++) { DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[i].wire_overlay, pass); DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); + DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); } stl->g_data->by_mode[i].lwire_shgrp = shgrp; } @@ -243,12 +243,12 @@ static void PAINT_VERTEX_cache_init(void *vedata) { DRWPass *pass = DRW_pass_create("Wire Mask Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE); + DRW_STATE_DEPTH_LESS_EQUAL); for (int i = 0; i < MODE_LEN; i++) { DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[i].wire_select_overlay, pass); DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); + DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); } stl->g_data->by_mode[i].lwire_select_shgrp = shgrp; } @@ -263,7 +263,7 @@ static void PAINT_VERTEX_cache_init(void *vedata) DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->face_select_overlay, pass); DRW_shgroup_uniform_vec4(shgrp, "color", col, 1); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); + DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); } psl->face_select_overlay = pass; stl->g_data->face_select_shgrp = shgrp; @@ -272,11 +272,11 @@ static void PAINT_VERTEX_cache_init(void *vedata) { DRWPass *pass = DRW_pass_create("Vert Mask Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | - DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE); + DRW_STATE_DEPTH_LESS_EQUAL); DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->vert_select_overlay, pass); DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo); if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d); + DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); } psl->vert_select_overlay = pass; stl->g_data->vert_select_shgrp = shgrp; @@ -337,13 +337,18 @@ static void PAINT_VERTEX_cache_populate(void *vedata, Object *ob) static void PAINT_VERTEX_draw_scene(void *vedata) { PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl; + PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl; for (int i = 0; i < MODE_LEN; i++) { DRW_draw_pass(psl->by_mode[i].color_faces); } + DRW_draw_pass(psl->face_select_overlay); + + DRW_view_set_active(stl->g_data->view_wires); DRW_draw_pass(psl->wire_overlay); DRW_draw_pass(psl->wire_select_overlay); DRW_draw_pass(psl->vert_select_overlay); - DRW_draw_pass(psl->face_select_overlay); + + DRW_view_set_active(NULL); } static void PAINT_VERTEX_engine_free(void) diff --git a/source/blender/draw/modes/shaders/common_view_lib.glsl b/source/blender/draw/modes/shaders/common_view_lib.glsl index 79ac351912d..20a54947db7 100644 --- a/source/blender/draw/modes/shaders/common_view_lib.glsl +++ b/source/blender/draw/modes/shaders/common_view_lib.glsl @@ -1,3 +1,5 @@ +#define COMMON_VIEW_LIB + /* keep in sync with DRWManager.view_data */ layout(std140) uniform viewBlock { @@ -9,11 +11,18 @@ layout(std140) uniform viewBlock mat4 ProjectionMatrix; mat4 ProjectionMatrixInverse; - vec4 CameraTexCoFactors; + vec4 clipPlanes[6]; - vec4 clipPlanes[2]; + /* TODO move it elsewhere. */ + vec4 CameraTexCoFactors; }; +#ifdef world_clip_planes_calc_clip_distance +# undef world_clip_planes_calc_clip_distance +# define world_clip_planes_calc_clip_distance(p) \ + _world_clip_planes_calc_clip_distance(p, clipPlanes) +#endif + uniform mat4 ModelMatrix; uniform mat4 ModelMatrixInverse; @@ -48,3 +57,11 @@ uniform mat4 ModelMatrixInverse; #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) + +/* Due to some shader compiler bug, we somewhat need to access gl_VertexID + * to make vertex shaders work. even if it's actually dead code. */ +#ifdef GPU_INTEL +# define GPU_INTEL_VERTEX_SHADER_WORKAROUND gl_Position.x = float(gl_VertexID); +#else +# define GPU_INTEL_VERTEX_SHADER_WORKAROUND +#endif 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 2f3d37a6e73..590c2905be6 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 @@ -7,6 +7,8 @@ flat out int vertFlag; void main() { + GPU_INTEL_VERTEX_SHADER_WORKAROUND + vec3 world_pos = point_object_to_world(pos); gl_Position = point_world_to_ndc(world_pos); vertFlag = data; 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 b1b707b59f4..6eec43d99be 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 @@ -9,6 +9,8 @@ out vec4 finalColor; void main() { + GPU_INTEL_VERTEX_SHADER_WORKAROUND + if ((data & VERT_SELECTED) != 0) { if ((data & VERT_ACTIVE) != 0) { finalColor = colorEditMeshActive; 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 ef60ddbc395..e1d5319ffb9 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 @@ -9,6 +9,8 @@ in float rad; void main() { + GPU_INTEL_VERTEX_SHADER_WORKAROUND + vec3 final_pos = pos; float flip = (gl_InstanceID != 0) ? -1.0 : 1.0; 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 f7df6bb4b68..ac6b353412d 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 @@ -22,6 +22,8 @@ vec2 proj(vec4 pos) void main() { + GPU_INTEL_VERTEX_SHADER_WORKAROUND + clipCase = 0; vec3 world_pos = point_object_to_world(pos); diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl index 7d4cba66933..6aa20a9d21b 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl @@ -1,5 +1,4 @@ -uniform bool doEdges = true; uniform bool selectFaces = true; uniform bool selectEdges = true; @@ -17,21 +16,23 @@ vec4 EDIT_MESH_edge_color_outer(int edge_flag, int face_flag, float crease, floa vec4 EDIT_MESH_edge_color_inner(int edge_flag) { vec4 color = colorWireEdit; - vec4 color_select = (selectEdges) ? colorEdgeSelect : colorFaceSelect; - color = (doEdges && ((edge_flag & EDGE_SELECTED) != 0)) ? color_select : color; - color = (doEdges && ((edge_flag & EDGE_ACTIVE) != 0)) ? colorEditMeshActive : color; + vec4 color_select = (selectEdges) ? colorEdgeSelect : mix(colorEdgeSelect, colorWireEdit, .45); + color = ((edge_flag & EDGE_SELECTED) != 0) ? color_select : color; + color = ((edge_flag & EDGE_ACTIVE) != 0) ? colorEditMeshActive : color; - float non_edge_select_alpha = (selectFaces && (edge_flag & EDGE_SELECTED) != 0) ? 0.75 : 0.4; - color.a = (selectEdges) ? 1.0 : non_edge_select_alpha; + color.a = (selectEdges || (edge_flag & (EDGE_SELECTED | EDGE_ACTIVE)) != 0) ? 1.0 : 0.4; return color; } vec4 EDIT_MESH_edge_vertex_color(int vertex_flag) { vec4 color = colorWireEdit; - vec4 color_select = (selectEdges) ? colorEdgeSelect : colorFaceSelect; - color = (doEdges && (vertex_flag & (VERT_ACTIVE | VERT_SELECTED)) != 0) ? color_select : color; - color.a = (selectEdges) ? 1.0 : 0.4; + vec4 color_select = (selectEdges) ? colorEdgeSelect : mix(colorEdgeSelect, colorWireEdit, .45); + + bool edge_selected = (vertex_flag & (VERT_ACTIVE | VERT_SELECTED)) != 0; + color = (edge_selected) ? color_select : color; + + color.a = (selectEdges || edge_selected) ? 1.0 : 0.4; return color; } 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 a20c1124fe1..df37c6fb0bc 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 @@ -8,6 +8,8 @@ flat out vec4 faceColor; void main() { + GPU_INTEL_VERTEX_SHADER_WORKAROUND + vec3 world_pos = point_object_to_world(pos); gl_Position = point_world_to_ndc(world_pos); 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 968a63c7780..7065ce3df7c 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 @@ -12,6 +12,8 @@ out vec4 weightColor; void main() { + GPU_INTEL_VERTEX_SHADER_WORKAROUND + vec3 world_pos = point_object_to_world(pos); gl_Position = point_world_to_ndc(world_pos); weightColor = vec4(weight_color.rgb, 1.0); 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 9aa656818cb..fabc317cf4f 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl @@ -20,6 +20,8 @@ out int selectOveride; void main() { + GPU_INTEL_VERTEX_SHADER_WORKAROUND + vec3 world_pos = point_object_to_world(pos); #if !defined(FACE) diff --git a/source/blender/draw/modes/shaders/edit_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_normals_vert.glsl index 9bf0fb7315c..384d13923f6 100644 --- a/source/blender/draw/modes/shaders/edit_normals_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_normals_vert.glsl @@ -21,6 +21,8 @@ flat out vec4 v2; void main() { + GPU_INTEL_VERTEX_SHADER_WORKAROUND + vec3 n = normalize(normal_object_to_world(nor)); vec3 world_pos = point_object_to_world(pos); diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 876bc9ae3e4..90632da8a7c 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -482,7 +482,7 @@ static void draw_markers_background(rctf *rect) immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); unsigned char shade[4]; - UI_GetThemeColor4ubv(TH_SCRUBBING_BACKGROUND, shade); + UI_GetThemeColor4ubv(TH_TIME_SCRUB_BACKGROUND, shade); immUniformColor4ubv(shade); diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c index 37e7eab74d4..70a9b7ba1fa 100644 --- a/source/blender/editors/animation/time_scrub_ui.c +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -46,12 +46,12 @@ #include "RNA_access.h" -static void get_scrubbing_region_rect(const ARegion *ar, rcti *rect) +static void get_time_scrub_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; + rect->ymin = rect->ymax - UI_TIME_SCRUB_MARGIN_Y; } static int get_centered_text_y(const rcti *rect) @@ -64,7 +64,7 @@ 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); + immUniformThemeColor(TH_TIME_SCRUB_BACKGROUND); GPU_blend(true); GPU_blend_set_func_separate( @@ -91,7 +91,7 @@ static void get_current_time_str( static void draw_current_frame(const Scene *scene, bool display_seconds, const View2D *v2d, - const rcti *scrubbing_region_rect, + const rcti *scrub_region_rect, int current_frame) { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; @@ -111,9 +111,9 @@ static void draw_current_frame(const Scene *scene, UI_draw_roundbox_3fvAlpha(true, frame_x - box_width / 2 + U.pixelsize / 2, - scrubbing_region_rect->ymin + box_padding, + scrub_region_rect->ymin + box_padding, frame_x + box_width / 2 + U.pixelsize / 2, - scrubbing_region_rect->ymax - box_padding, + scrub_region_rect->ymax - box_padding, 4 * UI_DPI_FAC, bg_color, 1.0f); @@ -121,36 +121,36 @@ static void draw_current_frame(const Scene *scene, 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, + scrub_region_rect->ymin + box_padding, frame_x + box_width / 2 + U.pixelsize / 2, - scrubbing_region_rect->ymax - box_padding, + scrub_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), + get_centered_text_y(scrub_region_rect), frame_str, color); } -void ED_scrubbing_draw(const ARegion *ar, - const Scene *scene, - bool display_seconds, - bool discrete_frames) +void ED_time_scrub_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); + rcti scrub_region_rect; + get_time_scrub_region_rect(ar, &scrub_region_rect); - draw_background(&scrubbing_region_rect); + draw_background(&scrub_region_rect); - rcti numbers_rect = scrubbing_region_rect; - numbers_rect.ymin = get_centered_text_y(&scrubbing_region_rect) - 4 * UI_DPI_FAC; + rcti numbers_rect = scrub_region_rect; + numbers_rect.ymin = get_centered_text_y(&scrub_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); @@ -160,19 +160,19 @@ void ED_scrubbing_draw(const ARegion *ar, ar, v2d, &numbers_rect, scene, display_seconds, TH_TEXT); } - draw_current_frame(scene, display_seconds, v2d, &scrubbing_region_rect, scene->r.cfra); + draw_current_frame(scene, display_seconds, v2d, &scrub_region_rect, scene->r.cfra); GPU_matrix_pop_projection(); } -bool ED_event_in_scrubbing_region(const ARegion *ar, const wmEvent *event) +bool ED_time_scrub_event_in_region(const ARegion *ar, const wmEvent *event) { rcti rect = ar->winrct; - rect.ymin = rect.ymax - UI_SCRUBBING_MARGIN_Y; + rect.ymin = rect.ymax - UI_TIME_SCRUB_MARGIN_Y; return BLI_rcti_isect_pt(&rect, event->x, event->y); } -void ED_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopesheet) +void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopesheet) { GPU_matrix_push_projection(); wmOrtho2_region_pixelspace(ar); @@ -180,7 +180,7 @@ void ED_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopeshee 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.ymin = ar->sizey * UI_DPI_FAC - UI_TIME_SCRUB_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); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 65f502d5cd2..8d131ee28ba 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -2584,33 +2584,42 @@ void CURVE_OT_switch_direction(wmOperatorType *ot) static int set_goal_weight_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - float weight = RNA_float_get(op->ptr, "weight"); - int a; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->bezt) { - for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { - if (bezt->f2 & SELECT) { - bezt->weight = weight; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + float weight = RNA_float_get(op->ptr, "weight"); + int a; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { + if (bezt->f2 & SELECT) { + bezt->weight = weight; + } } } - } - else if (nu->bp) { - for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { - if (bp->f1 & SELECT) { - bp->weight = weight; + else if (nu->bp) { + for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { + if (bp->f1 & SELECT) { + bp->weight = weight; + } } } } + + DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); } - DEG_id_tag_update(obedit->data, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -2638,33 +2647,42 @@ void CURVE_OT_spline_weight_set(wmOperatorType *ot) static int set_radius_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - float radius = RNA_float_get(op->ptr, "radius"); - int a; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->bezt) { - for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { - if (bezt->f2 & SELECT) { - bezt->radius = radius; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + float radius = RNA_float_get(op->ptr, "radius"); + int a; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { + if (bezt->f2 & SELECT) { + bezt->radius = radius; + } } } - } - else if (nu->bp) { - for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { - if (bp->f1 & SELECT) { - bp->radius = radius; + else if (nu->bp) { + for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { + if (bp->f1 & SELECT) { + bp->radius = radius; + } } } } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -2743,81 +2761,90 @@ static void smooth_single_bp(BPoint *bp, static int smooth_exec(bContext *C, wmOperator *UNUSED(op)) { const float factor = 1.0f / 6.0f; - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); - int a, a_end; - bool changed = false; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->bezt) { - /* duplicate the curve to use in weight calculation */ - const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt); - BezTriple *bezt; - changed = false; + int a, a_end; + bool changed = false; - /* check whether its cyclic or not, and set initial & final conditions */ - if (nu->flagu & CU_NURB_CYCLIC) { - a = 0; - a_end = nu->pntsu; - } - else { - a = 1; - a_end = nu->pntsu - 1; - } + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + /* duplicate the curve to use in weight calculation */ + const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt); + BezTriple *bezt; + changed = false; + + /* check whether its cyclic or not, and set initial & final conditions */ + if (nu->flagu & CU_NURB_CYCLIC) { + a = 0; + a_end = nu->pntsu; + } + else { + a = 1; + a_end = nu->pntsu - 1; + } - /* for all the curve points */ - for (; a < a_end; a++) { - /* respect selection */ - bezt = &nu->bezt[a]; - if (bezt->f2 & SELECT) { - const BezTriple *bezt_orig_prev, *bezt_orig_next; + /* for all the curve points */ + for (; a < a_end; a++) { + /* respect selection */ + bezt = &nu->bezt[a]; + if (bezt->f2 & SELECT) { + const BezTriple *bezt_orig_prev, *bezt_orig_next; - bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)]; - bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)]; + bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)]; + bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)]; - smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor); + smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor); - changed = true; + changed = true; + } + } + MEM_freeN((void *)bezt_orig); + if (changed) { + BKE_nurb_handles_calc(nu); } } - MEM_freeN((void *)bezt_orig); - if (changed) { - BKE_nurb_handles_calc(nu); - } - } - else if (nu->bp) { - /* Same as above, keep these the same! */ - const BPoint *bp_orig = MEM_dupallocN(nu->bp); - BPoint *bp; + else if (nu->bp) { + /* Same as above, keep these the same! */ + const BPoint *bp_orig = MEM_dupallocN(nu->bp); + BPoint *bp; - if (nu->flagu & CU_NURB_CYCLIC) { - a = 0; - a_end = nu->pntsu; - } - else { - a = 1; - a_end = nu->pntsu - 1; - } + if (nu->flagu & CU_NURB_CYCLIC) { + a = 0; + a_end = nu->pntsu; + } + else { + a = 1; + a_end = nu->pntsu - 1; + } - for (; a < a_end; a++) { - bp = &nu->bp[a]; - if (bp->f1 & SELECT) { - const BPoint *bp_orig_prev, *bp_orig_next; + for (; a < a_end; a++) { + bp = &nu->bp[a]; + if (bp->f1 & SELECT) { + const BPoint *bp_orig_prev, *bp_orig_next; - bp_orig_prev = &bp_orig[mod_i(a - 1, nu->pntsu)]; - bp_orig_next = &bp_orig[mod_i(a + 1, nu->pntsu)]; + bp_orig_prev = &bp_orig[mod_i(a - 1, nu->pntsu)]; + bp_orig_next = &bp_orig[mod_i(a + 1, nu->pntsu)]; - smooth_single_bp(bp, bp_orig_prev, bp_orig_next, factor); + smooth_single_bp(bp, bp_orig_prev, bp_orig_next, factor); + } } + MEM_freeN((void *)bp_orig); } - MEM_freeN((void *)bp_orig); } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -3023,13 +3050,22 @@ static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, cons static int curve_smooth_weight_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); + + curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight)); - curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight)); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -3051,13 +3087,22 @@ void CURVE_OT_smooth_weight(wmOperatorType *ot) static int curve_smooth_radius_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); - curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius)); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius)); + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -3079,13 +3124,22 @@ void CURVE_OT_smooth_radius(wmOperatorType *ot) static int curve_smooth_tilt_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); - curve_smooth_value(editnurb, offsetof(BezTriple, tilt), offsetof(BPoint, tilt)); + curve_smooth_value(editnurb, offsetof(BezTriple, tilt), offsetof(BPoint, tilt)); + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -3253,7 +3307,8 @@ static int reveal_exec(bContext *C, wmOperator *op) } if (changed) { - DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); + DEG_id_tag_update(obedit->data, + ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); changed_multi = true; } @@ -3909,54 +3964,63 @@ static void findselectedNurbvert( static int set_spline_type_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - Object *obedit = CTX_data_edit_object(C); - View3D *v3d = CTX_wm_view3d(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - bool changed = false; - bool changed_size = false; - const bool use_handles = RNA_boolean_get(op->ptr, "use_handles"); - const int type = RNA_enum_get(op->ptr, "type"); + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + int ret_value = OPERATOR_CANCELLED; - if (type == CU_CARDINAL || type == CU_BSPLINE) { - BKE_report(op->reports, RPT_ERROR, "Not yet implemented"); - return OPERATOR_CANCELLED; - } + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Main *bmain = CTX_data_main(C); + View3D *v3d = CTX_wm_view3d(C); + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + bool changed = false; + bool changed_size = false; + const bool use_handles = RNA_boolean_get(op->ptr, "use_handles"); + const int type = RNA_enum_get(op->ptr, "type"); - for (nu = editnurb->first; nu; nu = nu->next) { - if (ED_curve_nurb_select_check(v3d, nu)) { - const int pntsu_prev = nu->pntsu; - if (BKE_nurb_type_convert(nu, type, use_handles)) { - changed = true; - if (pntsu_prev != nu->pntsu) { - changed_size = true; + if (type == CU_CARDINAL || type == CU_BSPLINE) { + BKE_report(op->reports, RPT_ERROR, "Not yet implemented"); + continue; + } + + for (nu = editnurb->first; nu; nu = nu->next) { + if (ED_curve_nurb_select_check(v3d, nu)) { + const int pntsu_prev = nu->pntsu; + if (BKE_nurb_type_convert(nu, type, use_handles)) { + changed = true; + if (pntsu_prev != nu->pntsu) { + changed_size = true; + } + } + else { + BKE_report(op->reports, RPT_ERROR, "No conversion possible"); } - } - else { - BKE_report(op->reports, RPT_ERROR, "No conversion possible"); } } - } - if (changed) { - if (ED_curve_updateAnimPaths(bmain, obedit->data)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } + if (changed) { + if (ED_curve_updateAnimPaths(bmain, obedit->data)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } - DEG_id_tag_update(obedit->data, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - if (changed_size) { - Curve *cu = obedit->data; - cu->actvert = CU_ACT_NONE; - } + if (changed_size) { + Curve *cu = obedit->data; + cu->actvert = CU_ACT_NONE; + } - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; + ret_value = OPERATOR_FINISHED; + } } + + MEM_freeN(objects); + + return ret_value; } void CURVE_OT_spline_type_set(wmOperatorType *ot) @@ -6747,31 +6811,41 @@ void CURVE_OT_decimate(wmOperatorType *ot) static int shade_smooth_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); View3D *v3d = CTX_wm_view3d(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; + ViewLayer *view_layer = CTX_data_view_layer(C); int clear = (STREQ(op->idname, "CURVE_OT_shade_flat")); + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + int ret_value = OPERATOR_CANCELLED; - if (obedit->type != OB_CURVE) { - return OPERATOR_CANCELLED; - } + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); - for (nu = editnurb->first; nu; nu = nu->next) { - if (ED_curve_nurb_select_check(v3d, nu)) { - if (!clear) { - nu->flag |= CU_SMOOTH; - } - else { - nu->flag &= ~CU_SMOOTH; + if (obedit->type != OB_CURVE) { + continue; + } + + for (Nurb *nu = editnurb->first; nu; nu = nu->next) { + if (ED_curve_nurb_select_check(v3d, nu)) { + if (!clear) { + nu->flag |= CU_SMOOTH; + } + else { + nu->flag &= ~CU_SMOOTH; + } } } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + ret_value = OPERATOR_FINISHED; } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + MEM_freeN(objects); - return OPERATOR_FINISHED; + return ret_value; } void CURVE_OT_shade_smooth(wmOperatorType *ot) @@ -7026,7 +7100,7 @@ static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op)) int a; if (object->runtime.curve_cache == NULL) { - BKE_displist_make_curveTypes(depsgraph, scene, object, false, false, NULL); + BKE_displist_make_curveTypes(depsgraph, scene, object, false, false); } INIT_MINMAX(min, max); diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 0759b64d14a..ffbfb692ca9 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -2007,7 +2007,7 @@ static int font_open_exec(bContext *C, wmOperator *op) id_us_min(&font->id); RNA_id_pointer_create(&font->id, &idptr); - RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL); RNA_property_update(C, &pprop->ptr, pprop->prop); } @@ -2090,7 +2090,7 @@ static int font_unlink_exec(bContext *C, wmOperator *op) builtin_font = BKE_vfont_builtin_get(); RNA_id_pointer_create(&builtin_font->id, &idptr); - RNA_property_pointer_set(NULL, &pprop.ptr, pprop.prop, idptr); + RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, NULL); RNA_property_update(C, &pprop.ptr, pprop.prop); return OPERATOR_FINISHED; diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 316ad3f91d6..d2d0095bdb2 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -569,9 +569,9 @@ set(ICON_NAMES loop_forwards back forward + file_cache file_volume - alembic - volume + file_3d file_hidden file_backup disk_drive diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 96f405fab2f..bf15b846bb6 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -401,7 +401,8 @@ static bool gp_render_offscreen(tGPDfill *tgpf) glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - ED_view3d_update_viewmat(tgpf->depsgraph, tgpf->scene, tgpf->v3d, tgpf->ar, NULL, winmat, NULL); + ED_view3d_update_viewmat( + tgpf->depsgraph, tgpf->scene, tgpf->v3d, tgpf->ar, NULL, winmat, NULL, true); /* set for opengl */ GPU_matrix_projection_set(tgpf->rv3d->winmat); GPU_matrix_set(tgpf->rv3d->viewmat); diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index cd68981dee3..7a29e6b5e66 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -404,7 +404,7 @@ typedef enum eAnimFilter_Flags { /* channel heights */ #define ACHANNEL_FIRST_TOP(ac) \ - (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_SCRUBBING_MARGIN_Y - ACHANNEL_SKIP) + (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_TIME_SCRUB_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) @@ -422,7 +422,7 @@ typedef enum eAnimFilter_Flags { /* NLA channel heights */ #define NLACHANNEL_FIRST_TOP(ac) \ - (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_SCRUBBING_MARGIN_Y - NLACHANNEL_SKIP) + (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_TIME_SCRUB_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) diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index c3883de0722..3322cf0a863 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -24,6 +24,7 @@ #ifndef __ED_MASK_H__ #define __ED_MASK_H__ +struct Depsgraph; struct KeyframeEditData; struct MaskLayer; struct MaskLayerShape; @@ -55,7 +56,8 @@ void ED_operatormacros_mask(void); /* mask_draw.c */ void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type); -void ED_mask_draw_region(struct Mask *mask, +void ED_mask_draw_region(struct Depsgraph *depsgraph, + struct Mask *mask, struct ARegion *ar, const char draw_flag, const char draw_type, diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 4e6bf7d4df5..0a8304f3f8a 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -152,24 +152,16 @@ struct BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ct const uint sel_id, uint *r_base_index); +uint EDBM_select_id_context_offset_for_object_elem(const struct EDBMSelectID_Context *sel_id_ctx, + int base_index, + char htype); + +uint EDBM_select_id_context_elem_len(const struct EDBMSelectID_Context *sel_id_ctx); + void EDBM_select_mirrored( struct BMEditMesh *em, const int axis, const bool extend, int *r_totmirr, int *r_totfail); void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update, const char hflag); -bool EDBM_backbuf_border_init( - struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); -bool EDBM_backbuf_check(unsigned int index); -void EDBM_backbuf_free(void); - -bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, - const int mcords[][2], - short tot, - short xmin, - short ymin, - short xmax, - short ymax); -bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads); - struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc, float *r_dist, const bool use_select_bias, @@ -249,9 +241,6 @@ 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 */ struct EditMesh_PreSelEdgeRing; struct EditMesh_PreSelEdgeRing *EDBM_preselect_edgering_create(void); @@ -291,7 +280,6 @@ bool paintface_mouse_select(struct bContext *C, bool extend, bool deselect, bool toggle); -bool do_paintface_box_select(struct ViewContext *vc, const struct rcti *rect, int sel_op); bool paintface_deselect_all_visible(struct bContext *C, struct Object *ob, int action, diff --git a/source/blender/editors/include/ED_select_buffer_utils.h b/source/blender/editors/include/ED_select_buffer_utils.h new file mode 100644 index 00000000000..af745cee676 --- /dev/null +++ b/source/blender/editors/include/ED_select_buffer_utils.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. + */ + +/** \file + * \ingroup editors + */ + +#ifndef __ED_SELECT_BUFFER_UTILS_H__ +#define __ED_SELECT_BUFFER_UTILS_H__ + +struct rcti; + +/* Boolean array from selection ID's. */ +uint *ED_select_buffer_bitmap_from_rect(const uint bitmap_len, const struct rcti *rect); +uint *ED_select_buffer_bitmap_from_circle(const uint bitmap_len, + const int center[2], + const int radius); +uint *ED_select_buffer_bitmap_from_poly(const uint bitmap_len, + const int poly[][2], + const int poly_len, + const rcti *rect); + +/* Single result from selection ID's. */ +uint ED_select_buffer_sample_point(const int center[2]); +uint ED_select_buffer_find_nearest_to_point(const int center[2], + const uint id_min, + const uint id_max, + uint *dist); + +#endif /* __ED_SELECT_BUFFER_UTILS_H__ */ diff --git a/source/blender/editors/include/ED_time_scrub_ui.h b/source/blender/editors/include/ED_time_scrub_ui.h index a2e3098e949..b43e674224c 100644 --- a/source/blender/editors/include/ED_time_scrub_ui.h +++ b/source/blender/editors/include/ED_time_scrub_ui.h @@ -21,23 +21,23 @@ * \ingroup editors */ -#ifndef __ED_SCRUBBING_H__ -#define __ED_SCRUBBING_H__ +#ifndef __ED_TIME_SCRUB_UI_H__ +#define __ED_TIME_SCRUB_UI_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); +void ED_time_scrub_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); +bool ED_time_scrub_event_in_region(const struct ARegion *ar, const struct wmEvent *event); -void ED_channel_search_draw(const struct bContext *C, - struct ARegion *ar, - struct bDopeSheet *dopesheet); +void ED_time_scrub_channel_search_draw(const struct bContext *C, + struct ARegion *ar, + struct bDopeSheet *dopesheet); -#endif /* __ED_SCRUBBING_H__ */ +#endif /* __ED_TIME_SCRUB_UI_H__ */ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index cd4cefe8891..5ce9133a531 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -42,6 +42,7 @@ struct GPUFX; struct GPUFXSettings; struct GPUOffScreen; struct GPUViewport; +struct ID; struct ImBuf; struct MVert; struct Main; @@ -449,16 +450,9 @@ void ED_view3d_backbuf_depth_validate(struct ViewContext *vc); int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist); void ED_view3d_select_id_validate(struct ViewContext *vc); -void ED_view3d_select_id_validate_with_select_mode(struct ViewContext *vc, short select_mode); -uint ED_view3d_select_id_sample(struct ViewContext *vc, int x, int y); -uint *ED_view3d_select_id_read( - struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len); -uint *ED_view3d_select_id_read_rect(struct ViewContext *vc, - const struct rcti *rect, - uint *r_buf_len); -uint ED_view3d_select_id_read_nearest( - struct ViewContext *vc, const int mval[2], const uint min, const uint max, uint *r_dist); +uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_buf_len); +uint *ED_view3d_select_id_read_rect(const struct rcti *rect, uint *r_buf_len); bool ED_view3d_autodist(struct Depsgraph *depsgraph, struct ARegion *ar, @@ -590,7 +584,6 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Depsgraph *depsgraph, int sizex, int sizey, unsigned int flag, - unsigned int draw_flags, int alpha_mode, int samples, const char *viewname, @@ -621,7 +614,8 @@ void ED_view3d_update_viewmat(struct Depsgraph *depsgraph, struct ARegion *ar, float viewmat[4][4], float winmat[4][4], - const struct rcti *rect); + const struct rcti *rect, + bool offscreen); bool ED_view3d_quat_from_axis_view(const char view, float quat[4]); char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon); char ED_view3d_lock_view_from_index(int index); diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index f54e4d1c61b..048f30bdf26 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -96,8 +96,8 @@ DEF_ICON(PINNED) DEF_ICON(SCREEN_BACK) DEF_ICON(RIGHTARROW) DEF_ICON(DOWNARROW_HLT) -DEF_ICON_BLANK(103) -DEF_ICON_BLANK(104) +DEF_ICON(FCURVE_SNAPSHOT) +DEF_ICON(OBJECT_HIDDEN) DEF_ICON_BLANK(105) DEF_ICON_BLANK(106) DEF_ICON(PLUGIN) @@ -699,8 +699,8 @@ DEF_ICON(VIS_SEL_10) DEF_ICON(VIS_SEL_01) DEF_ICON(VIS_SEL_00) DEF_ICON_BLANK(231) -DEF_ICON(AUTOMERGE_ON) DEF_ICON(AUTOMERGE_OFF) +DEF_ICON(AUTOMERGE_ON) DEF_ICON_BLANK(234) DEF_ICON(UV_VERTEXSEL) DEF_ICON(UV_EDGESEL) @@ -821,9 +821,9 @@ DEF_ICON(FORWARD) DEF_ICON_BLANK(825) DEF_ICON_BLANK(826) DEF_ICON_BLANK(827) +DEF_ICON(FILE_CACHE) DEF_ICON(FILE_VOLUME) -DEF_ICON(ALEMBIC) -DEF_ICON(VOLUME) +DEF_ICON(FILE_3D) DEF_ICON(FILE_HIDDEN) DEF_ICON(FILE_BACKUP) DEF_ICON(DISK_DRIVE) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 14d681ee817..bf728ec7772 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -281,6 +281,9 @@ enum { /** Value is animated, but the current value differs from the animated one. */ UI_BUT_ANIMATED_CHANGED = 1 << 25, + + /* Draw the checkbox buttons inverted. */ + UI_BUT_CHECKBOX_INVERT = 1 << 26, }; /* scale fixed button widths by this to account for DPI */ @@ -1627,7 +1630,7 @@ struct Panel *UI_panel_begin(struct ScrArea *sa, struct PanelType *pt, struct Panel *pa, bool *r_open); -void UI_panel_end(uiBlock *block, int width, int height); +void UI_panel_end(uiBlock *block, int width, int height, bool open); void UI_panels_scale(struct ARegion *ar, float new_width); void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y); int UI_panel_size_y(const struct Panel *pa); @@ -1638,6 +1641,7 @@ struct PanelCategoryDyn *UI_panel_category_find(struct ARegion *ar, const char * struct PanelCategoryStack *UI_panel_category_active_find(struct ARegion *ar, const char *idname); const char *UI_panel_category_active_get(struct ARegion *ar, bool set_fallback); void UI_panel_category_active_set(struct ARegion *ar, const char *idname); +void UI_panel_category_active_set_default(struct ARegion *ar, const char *idname); struct PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(struct ARegion *ar, const int x, const int y); @@ -1711,14 +1715,28 @@ enum { UI_ITEM_O_RETURN_PROPS = 1 << 0, UI_ITEM_R_EXPAND = 1 << 1, UI_ITEM_R_SLIDER = 1 << 2, + /** + * Use for booleans, causes the button to draw with an outline (emboss), + * instead of text with a checkbox. + * This is implied when toggle buttons have an icon + * unless #UI_ITEM_R_ICON_NEVER flag is set. + */ UI_ITEM_R_TOGGLE = 1 << 3, - UI_ITEM_R_ICON_ONLY = 1 << 4, - UI_ITEM_R_EVENT = 1 << 5, - UI_ITEM_R_FULL_EVENT = 1 << 6, - UI_ITEM_R_NO_BG = 1 << 7, - UI_ITEM_R_IMMEDIATE = 1 << 8, - UI_ITEM_O_DEPRESS = 1 << 9, - UI_ITEM_R_COMPACT = 1 << 10, + /** + * Don't attempt to use an icon when the icon is set to #ICON_NONE. + * + * Use for boolean's, causes the buttons to always show as a checkbox + * even when there is an icon (which would normally show the button as a toggle). + */ + UI_ITEM_R_ICON_NEVER = 1 << 4, + UI_ITEM_R_ICON_ONLY = 1 << 5, + UI_ITEM_R_EVENT = 1 << 6, + UI_ITEM_R_FULL_EVENT = 1 << 7, + UI_ITEM_R_NO_BG = 1 << 8, + UI_ITEM_R_IMMEDIATE = 1 << 9, + UI_ITEM_O_DEPRESS = 1 << 10, + UI_ITEM_R_COMPACT = 1 << 11, + UI_ITEM_R_CHECKBOX_INVERT = 1 << 12, }; #define UI_HEADER_OFFSET ((void)0, 0.4f * UI_UNIT_X) @@ -2233,6 +2251,7 @@ void uiItemL(uiLayout *layout, const char *name, int icon); /* label */ /* label icon for dragging */ void uiItemLDrag(uiLayout *layout, struct PointerRNA *ptr, const char *name, int icon); /* menu */ +void uiItemM_ptr(uiLayout *layout, struct MenuType *mt, const char *name, int icon); void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon); /* menu contents */ void uiItemMContents(uiLayout *layout, const char *menuname); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 6dc632921ad..db6bb35560d 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -105,7 +105,7 @@ typedef enum ThemeColorID { TH_FACE_DOT, TH_FACEDOT_SIZE, TH_CFRAME, - TH_SCRUBBING_BACKGROUND, + TH_TIME_SCRUB_BACKGROUND, TH_TIME_KEYFRAME, TH_TIME_GP_KEYFRAME, TH_NURB_ULINE, diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index d03d4b1b4f5..42ac3bb30d8 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -260,6 +260,6 @@ void UI_view2d_smooth_view(struct bContext *C, const int smooth_viewtx); #define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC) -#define UI_SCRUBBING_MARGIN_Y (23 * UI_DPI_FAC) +#define UI_TIME_SCRUB_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 f1724d92402..931a4faa1c0 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1845,6 +1845,9 @@ int ui_but_is_pushed_ex(uiBut *but, double *value) } } + if ((but->drawflag & UI_BUT_CHECKBOX_INVERT) && (is_push != -1)) { + is_push = !((bool)is_push); + } return is_push; } int ui_but_is_pushed(uiBut *but) @@ -2772,7 +2775,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) } else if (type == PROP_POINTER) { if (str[0] == '\0') { - RNA_property_pointer_set(NULL, &but->rnapoin, but->rnaprop, PointerRNA_NULL); + RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL, NULL); return true; } else { @@ -2788,14 +2791,14 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) * Fact remains, using editstr as main 'reference' over whole search button thingy * is utterly weak and should be redesigned imho, but that's not a simple task. */ if (prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) { - RNA_property_pointer_set(NULL, &but->rnapoin, but->rnaprop, rptr); + RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr, NULL); } else if (but->func_arg2 != NULL) { RNA_pointer_create(NULL, RNA_property_pointer_type(&but->rnapoin, but->rnaprop), but->func_arg2, &rptr); - RNA_property_pointer_set(NULL, &but->rnapoin, but->rnaprop, rptr); + RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr, NULL); } return true; @@ -3735,6 +3738,16 @@ void ui_def_but_icon(uiBut *but, const int icon, const int flag) } } +/** + * Avoid using this where possible since it's better not to ask for an icon in the first place. + */ +void ui_def_but_icon_clear(uiBut *but) +{ + but->icon = ICON_NONE; + but->flag &= ~UI_HAS_ICON; + but->drawflag &= ~UI_BUT_ICON_LEFT; +} + static void ui_def_but_rna__disable(uiBut *but, const char *info) { but->flag |= UI_BUT_DISABLED; diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 9ef98db49f5..ca35689112f 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -47,6 +47,8 @@ #include "RNA_access.h" +#include "BPY_extern.h" + #include "WM_api.h" #include "WM_types.h" @@ -92,7 +94,7 @@ static const char *shortcut_get_operator_property(bContext *C, uiBut *but, IDPro { if (but->optype) { /* Operator */ - *prop = (but->opptr) ? IDP_CopyProperty(but->opptr->data) : NULL; + *prop = (but->opptr && but->opptr->data) ? IDP_CopyProperty(but->opptr->data) : NULL; return but->optype->idname; } else if (but->rnaprop) { @@ -358,7 +360,31 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um) if (drawstr[0] == '\0') { /* Hard code overrides for generic operators. */ if (UI_but_is_tool(but)) { - RNA_string_get(but->opptr, "name", drawstr); + char idname[64]; + RNA_string_get(but->opptr, "name", idname); +#ifdef WITH_PYTHON + { + const char *expr_imports[] = {"bpy", "bl_ui", NULL}; + char expr[256]; + SNPRINTF(expr, + "bl_ui.space_toolsystem_common.item_from_id(" + "bpy.context, " + "bpy.context.space_data.type, " + "'%s').label", + idname); + char *expr_result = NULL; + if (BPY_execute_string_as_string(C, expr_imports, expr, true, &expr_result)) { + STRNCPY(drawstr, expr_result); + MEM_freeN(expr_result); + } + else { + BLI_assert(0); + STRNCPY(drawstr, idname); + } + } +#else + STRNCPY(drawstr, idname); +#endif } } ED_screen_user_menu_item_add_operator( diff --git a/source/blender/editors/interface/interface_eyedropper_datablock.c b/source/blender/editors/interface/interface_eyedropper_datablock.c index 4a2d59c05de..658aa4f67f9 100644 --- a/source/blender/editors/interface/interface_eyedropper_datablock.c +++ b/source/blender/editors/interface/interface_eyedropper_datablock.c @@ -207,7 +207,7 @@ static bool datadropper_id_set(bContext *C, DataDropper *ddr, ID *id) RNA_id_pointer_create(id, &ptr_value); - RNA_property_pointer_set(NULL, &ddr->ptr, ddr->prop, ptr_value); + RNA_property_pointer_set(&ddr->ptr, ddr->prop, ptr_value, NULL); RNA_property_update(C, &ddr->ptr, ddr->prop); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index a3b438ece42..b8e97f58c2f 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -556,18 +556,9 @@ 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; - } + StructRNA *base = RNA_struct_base(but->rnapoin.type); + if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences, &RNA_KeyMapItem)) { + tag = true; } } @@ -1744,7 +1735,7 @@ static void ui_selectcontext_apply(bContext *C, } else if (rna_type == PROP_POINTER) { const PointerRNA other_value = delta.p; - RNA_property_pointer_set(NULL, &lptr, lprop, other_value); + RNA_property_pointer_set(&lptr, lprop, other_value, NULL); } RNA_property_update(C, &lptr, prop); @@ -5572,9 +5563,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co if ((int)(but->a1) == UI_PALETTE_COLOR) { if (!event->ctrl) { float color[3]; - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Paint *paint = BKE_paint_get_active(scene, view_layer); + Paint *paint = BKE_paint_get_active_from_context(C); Brush *brush = BKE_paint_brush(paint); if (brush->flag & BRUSH_USE_GRADIENT) { @@ -5589,6 +5578,8 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co } } else { + Scene *scene = CTX_data_scene(C); + if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) { RNA_property_float_get_array(&but->rnapoin, but->rnaprop, color); BKE_brush_color_set(scene, brush, color); @@ -6530,7 +6521,7 @@ static int ui_do_but_CURVE( CurveMap *cuma = cumap->cm + cumap->cur; CurveMapPoint *cmp; const float m_xy[2] = {mx, my}; - float dist_min_sq = SQUARE(14.0f); /* 14 pixels radius */ + float dist_min_sq = SQUARE(U.dpi_fac * 14.0f); /* 14 pixels radius */ int sel = -1; if (event->ctrl) { @@ -6565,7 +6556,7 @@ static int ui_do_but_CURVE( BLI_rctf_transform_pt_v(&but->rect, &cumap->curr, f_xy, &cmp[0].x); /* with 160px height 8px should translate to the old 0.05 coefficient at no zoom */ - dist_min_sq = SQUARE(8.0f); + dist_min_sq = SQUARE(U.dpi_fac * 8.0f); /* loop through the curve segment table and find what's near the mouse. */ for (i = 1; i <= CM_TABLE; i++) { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index e53e9694617..fa3605269ff 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1086,6 +1086,12 @@ static void free_iconfile_list(struct ListBase *list) } } +#else + +void UI_icons_reload_internal_textures(void) +{ +} + #endif /* WITH_HEADLESS */ int UI_iconfile_get_index(const char *filename) diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 33288df15ba..8a2b28ee2d4 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -500,6 +500,7 @@ extern int ui_but_string_get_max_length(uiBut *but); extern uiBut *ui_but_drag_multi_edit_get(uiBut *but); void ui_def_but_icon(uiBut *but, const int icon, const int flag); +void ui_def_but_icon_clear(uiBut *but); extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but); extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index dc57be4f07f..b89767171ab 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -484,7 +484,7 @@ static void ui_item_array(uiLayout *layout, int UNUSED(h), bool expand, bool slider, - bool toggle, + int toggle, bool icon_only, bool compact, bool show_text) @@ -691,7 +691,7 @@ static void ui_item_array(uiLayout *layout, if (slider && but->type == UI_BTYPE_NUM) { but->type = UI_BTYPE_NUM_SLIDER; } - if (toggle && but->type == UI_BTYPE_CHECKBOX) { + if ((toggle == 1) && but->type == UI_BTYPE_CHECKBOX) { but->type = UI_BTYPE_TOGGLE; } if ((a == 0) && (subtype == PROP_AXISANGLE)) { @@ -1858,12 +1858,7 @@ void uiItemFullR(uiLayout *layout, int icon) { uiBlock *block = layout->root->block; - uiBut *but = NULL; - PropertyType type; char namestr[UI_MAX_NAME_STR]; - int len, w, h; - bool slider, toggle, expand, icon_only, no_bg, compact; - bool is_array; const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0); /* By default 'use_prop_sep' uses a separate column for labels. @@ -1888,11 +1883,15 @@ void uiItemFullR(uiLayout *layout, UI_block_layout_set_current(block, layout); /* retrieve info */ - type = RNA_property_type(prop); - is_array = RNA_property_array_check(prop); - len = (is_array) ? RNA_property_array_length(ptr, prop) : 0; + const PropertyType type = RNA_property_type(prop); + const bool is_array = RNA_property_array_check(prop); + const int len = (is_array) ? RNA_property_array_length(ptr, prop) : 0; + + const bool icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0; - icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0; + /* Boolean with -1 to signify that the value depends on the presence of an icon. */ + const int toggle = ((flag & UI_ITEM_R_TOGGLE) ? 1 : ((flag & UI_ITEM_R_ICON_NEVER) ? 0 : -1)); + const bool no_icon = (toggle == 0); /* set name and icon */ if (!name) { @@ -1904,8 +1903,8 @@ void uiItemFullR(uiLayout *layout, } } - if (icon == ICON_NONE) { - icon = RNA_property_ui_icon(prop); + if (type != PROP_BOOLEAN) { + flag &= ~UI_ITEM_R_CHECKBOX_INVERT; } if (flag & UI_ITEM_R_ICON_ONLY) { @@ -1932,56 +1931,66 @@ void uiItemFullR(uiLayout *layout, } } -#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION - if (use_prop_sep) { - if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) { - use_prop_sep_split_label = false; + if (no_icon == false) { + if (icon == ICON_NONE) { + icon = RNA_property_ui_icon(prop); } - } -#endif - /* menus and pie-menus don't show checkbox without this */ - if ((layout->root->type == UI_LAYOUT_MENU) || - /* use checkboxes only as a fallback in pie-menu's, when no icon is defined */ - ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) { - int prop_flag = RNA_property_flag(prop); - if (type == PROP_BOOLEAN && ((is_array == false) || (index != RNA_NO_INDEX))) { - if (prop_flag & PROP_ICONS_CONSECUTIVE) { - icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */ - } - else if (is_array) { - icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT : - ICON_CHECKBOX_DEHLT; + /* Menus and pie-menus don't show checkbox without this. */ + if ((layout->root->type == UI_LAYOUT_MENU) || + /* Use checkboxes only as a fallback in pie-menu's, when no icon is defined. */ + ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) { + int prop_flag = RNA_property_flag(prop); + if (type == PROP_BOOLEAN) { + if ((is_array == false) || (index != RNA_NO_INDEX)) { + if (prop_flag & PROP_ICONS_CONSECUTIVE) { + icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */ + } + else if (is_array) { + icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT : + ICON_CHECKBOX_DEHLT; + } + else { + icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; + } + } } - else { - icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; + else if (type == PROP_ENUM) { + if (index == RNA_ENUM_VALUE) { + int enum_value = RNA_property_enum_get(ptr, prop); + if (prop_flag & PROP_ICONS_CONSECUTIVE) { + icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */ + } + else if (prop_flag & PROP_ENUM_FLAG) { + icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; + } + else { + icon = (enum_value == value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; + } + } } } - else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) { - int enum_value = RNA_property_enum_get(ptr, prop); - if (prop_flag & PROP_ICONS_CONSECUTIVE) { - icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */ - } - else if (prop_flag & PROP_ENUM_FLAG) { - icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; - } - else { - icon = (enum_value == value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT; - } + } + +#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION + if (use_prop_sep) { + if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) { + use_prop_sep_split_label = false; } } +#endif if ((type == PROP_ENUM) && (RNA_property_flag(prop) & PROP_ENUM_FLAG)) { flag |= UI_ITEM_R_EXPAND; } - slider = (flag & UI_ITEM_R_SLIDER) != 0; - toggle = (flag & UI_ITEM_R_TOGGLE) != 0; - expand = (flag & UI_ITEM_R_EXPAND) != 0; - no_bg = (flag & UI_ITEM_R_NO_BG) != 0; - compact = (flag & UI_ITEM_R_COMPACT) != 0; + const bool slider = (flag & UI_ITEM_R_SLIDER) != 0; + const bool expand = (flag & UI_ITEM_R_EXPAND) != 0; + const bool no_bg = (flag & UI_ITEM_R_NO_BG) != 0; + const bool compact = (flag & UI_ITEM_R_COMPACT) != 0; /* get size */ + int w, h; ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, compact, &w, &h); int prev_emboss = layout->emboss; @@ -1989,6 +1998,8 @@ void uiItemFullR(uiLayout *layout, layout->emboss = UI_EMBOSS_NONE; } + uiBut *but = NULL; + /* Split the label / property. */ uiLayout *layout_parent = layout; if (use_prop_sep) { @@ -2156,7 +2167,13 @@ void uiItemFullR(uiLayout *layout, but->type = UI_BTYPE_NUM_SLIDER; } - if (toggle && but->type == UI_BTYPE_CHECKBOX) { + if (flag & UI_ITEM_R_CHECKBOX_INVERT) { + if (ELEM(but->type, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N)) { + but->drawflag |= UI_BUT_CHECKBOX_INVERT; + } + } + + if ((toggle == 1) && but->type == UI_BTYPE_CHECKBOX) { but->type = UI_BTYPE_TOGGLE; } @@ -2175,6 +2192,18 @@ void uiItemFullR(uiLayout *layout, } } + /* The resulting button may have the icon set since boolean button drawing + * is being 'helpful' and adding an icon for us. + * In this case we want the ability not to have an icon. + * + * We could pass an argument not to set the icon to begin with however this is the one case + * the functionality is needed. */ + if (but && no_icon) { + if ((icon == ICON_NONE) && (but->icon != ICON_NONE)) { + ui_def_but_icon_clear(but); + } + } + /* Mark non-embossed textfields inside a listbox. */ if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) && (but->dt & UI_EMBOSS_NONE)) { @@ -2744,14 +2773,8 @@ static uiBut *ui_item_menu(uiLayout *layout, return but; } -void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon) +void uiItemM_ptr(uiLayout *layout, MenuType *mt, const char *name, int icon) { - MenuType *mt = WM_menutype_find(menuname, false); - if (mt == NULL) { - RNA_warning("not found %s", menuname); - return; - } - if (!name) { name = CTX_IFACE_(mt->translation_context, mt->label); } @@ -2770,6 +2793,16 @@ void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon) false); } +void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon) +{ + MenuType *mt = WM_menutype_find(menuname, false); + if (mt == NULL) { + RNA_warning("not found %s", menuname); + return; + } + uiItemM_ptr(layout, mt, name, icon); +} + void uiItemMContents(uiLayout *layout, const char *menuname) { MenuType *mt = WM_menutype_find(menuname, false); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index aa7ff015bad..9c5ce0c9d2c 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -367,7 +367,7 @@ Panel *UI_panel_begin( return pa; } -void UI_panel_end(uiBlock *block, int width, int height) +void UI_panel_end(uiBlock *block, int width, int height, bool open) { Panel *pa = block->panel; @@ -390,21 +390,21 @@ void UI_panel_end(uiBlock *block, int width, int height) pa->sizey = height; } else { - /* check if we need to do an animation */ - if (!ELEM(width, 0, pa->sizex) || !ELEM(height, 0, pa->sizey)) { - pa->runtime_flag |= PNL_ANIM_ALIGN; - if (height != 0) { - pa->ofsy += pa->sizey - height; - } - } + int old_sizex = pa->sizex, old_sizey = pa->sizey; /* update width/height if non-zero */ if (width != 0) { pa->sizex = width; } - if (height != 0) { + if (height != 0 || open) { pa->sizey = height; } + + /* check if we need to do an animation */ + if (pa->sizex != old_sizex || pa->sizey != old_sizey) { + pa->runtime_flag |= PNL_ANIM_ALIGN; + pa->ofsy += old_sizey - pa->sizey; + } } } @@ -1676,28 +1676,7 @@ PanelCategoryStack *UI_panel_category_active_find(ARegion *ar, const char *idnam return BLI_findstring(&ar->panels_category_active, idname, offsetof(PanelCategoryStack, idname)); } -const char *UI_panel_category_active_get(ARegion *ar, bool set_fallback) -{ - PanelCategoryStack *pc_act; - - for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) { - if (UI_panel_category_find(ar, pc_act->idname)) { - return pc_act->idname; - } - } - - if (set_fallback) { - PanelCategoryDyn *pc_dyn = ar->panels_category.first; - if (pc_dyn) { - UI_panel_category_active_set(ar, pc_dyn->idname); - return pc_dyn->idname; - } - } - - return NULL; -} - -void UI_panel_category_active_set(ARegion *ar, const char *idname) +static void ui_panel_category_active_set(ARegion *ar, const char *idname, bool fallback) { ListBase *lb = &ar->panels_category_active; PanelCategoryStack *pc_act = UI_panel_category_active_find(ar, idname); @@ -1710,7 +1689,13 @@ void UI_panel_category_active_set(ARegion *ar, const char *idname) BLI_strncpy(pc_act->idname, idname, sizeof(pc_act->idname)); } - BLI_addhead(lb, pc_act); + if (fallback) { + /* For fallbacks, add at the end so explicitly chosen categories have priority. */ + BLI_addtail(lb, pc_act); + } + else { + BLI_addhead(lb, pc_act); + } /* validate all active panels, we could do this on load, * they are harmless - but we should remove somewhere. @@ -1729,6 +1714,39 @@ void UI_panel_category_active_set(ARegion *ar, const char *idname) } } +void UI_panel_category_active_set(ARegion *ar, const char *idname) +{ + ui_panel_category_active_set(ar, idname, false); +} + +void UI_panel_category_active_set_default(ARegion *ar, const char *idname) +{ + if (!UI_panel_category_active_find(ar, idname)) { + ui_panel_category_active_set(ar, idname, true); + } +} + +const char *UI_panel_category_active_get(ARegion *ar, bool set_fallback) +{ + PanelCategoryStack *pc_act; + + for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) { + if (UI_panel_category_find(ar, pc_act->idname)) { + return pc_act->idname; + } + } + + if (set_fallback) { + PanelCategoryDyn *pc_dyn = ar->panels_category.first; + if (pc_dyn) { + ui_panel_category_active_set(ar, pc_dyn->idname, true); + return pc_dyn->idname; + } + } + + return NULL; +} + PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(ARegion *ar, const int x, const int y) { PanelCategoryDyn *ptd; diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index 5b205de21b8..6c780482777 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -883,8 +883,7 @@ static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *gz) /* Operator Actions */ { - bool use_drag = gz->drag_part != -1 && gz->highlight_part != gz->drag_part; - + const bool use_drag = gz->drag_part != -1 && gz->highlight_part != gz->drag_part; const struct { int part; const char *prefix; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 3dbfd3d2f6a..33602818fd4 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -298,7 +298,7 @@ static void template_ID_set_property_cb(bContext *C, void *arg_template, void *i PointerRNA idptr; RNA_id_pointer_create(item, &idptr); - RNA_property_pointer_set(NULL, &template_ui->ptr, template_ui->prop, idptr); + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); } } @@ -489,7 +489,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) break; case UI_ID_DELETE: memset(&idptr, 0, sizeof(idptr)); - RNA_property_pointer_set(NULL, &template_ui->ptr, template_ui->prop, idptr); + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); if (id && CTX_wm_window(C)->eventstate->shift) { @@ -532,7 +532,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); } } - RNA_property_pointer_set(NULL, &template_ui->ptr, template_ui->prop, idptr); + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); } break; @@ -541,7 +541,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) BKE_override_static_free(&id->override_static); /* reassign to get get proper updates/notifiers */ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); - RNA_property_pointer_set(NULL, &template_ui->ptr, template_ui->prop, idptr); + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL); RNA_property_update(C, &template_ui->ptr, template_ui->prop); } break; @@ -1455,7 +1455,7 @@ static void template_search_handle_cb(bContext *C, void *arg_template, void *ite PointerRNA item_ptr; RNA_pointer_create(NULL, type, item, &item_ptr); - RNA_property_pointer_set(NULL, &coll_search->target_ptr, coll_search->target_prop, item_ptr); + RNA_property_pointer_set(&coll_search->target_ptr, coll_search->target_prop, item_ptr, NULL); RNA_property_update(C, &coll_search->target_ptr, coll_search->target_prop); } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 594793371ae..71629d6297c 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1261,7 +1261,9 @@ void UI_widgetbase_draw_cache_flush(void) (float *)g_widget_base_batch.params); GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params); GPU_matrix_bind(batch->interface); - GPU_batch_draw_range_ex(batch, 0, g_widget_base_batch.count, true); + GPU_batch_bind(batch); + GPU_batch_draw_advanced(batch, 0, 0, 0, g_widget_base_batch.count); + GPU_batch_program_use_end(batch); } g_widget_base_batch.count = 0; @@ -1946,9 +1948,9 @@ static void ui_text_clip_right_label(const uiFontStyle *fstyle, uiBut *but, cons } #ifdef WITH_INPUT_IME -static void widget_draw_text_ime_underline(uiFontStyle *fstyle, - uiWidgetColors *wcol, - uiBut *but, +static void widget_draw_text_ime_underline(const uiFontStyle *fstyle, + const uiWidgetColors *wcol, + const uiBut *but, const rcti *rect, const wmIMEData *ime_data, const char *drawstr) @@ -2183,7 +2185,7 @@ static void widget_draw_text(const uiFontStyle *fstyle, ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) && /* if we're editing or multi-drag (fake editing), then use left alignment */ (but->editstr == NULL) && (drawstr == but->drawstr)) { - drawstr_right = strchr(drawstr + but->ofs, ':'); + drawstr_right = strrchr(drawstr + but->ofs, ':'); if (drawstr_right) { drawstr_right++; drawstr_left_len = (drawstr_right - drawstr); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 06acf59e07c..26beb08dd28 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -309,8 +309,8 @@ 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; + case TH_TIME_SCRUB_BACKGROUND: + cp = ts->time_scrub_background; break; case TH_VIEW_OVERLAY: cp = ts->view_overlay; diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index f2d4faff479..36b984e229b 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -190,7 +190,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr * 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; + v2d->vert.ymax -= UI_TIME_SCRUB_MARGIN_Y; } /* horizontal scroller */ diff --git a/source/blender/editors/interface/view2d_draw.c b/source/blender/editors/interface/view2d_draw.c index 2568193ee23..43b49825219 100644 --- a/source/blender/editors/interface/view2d_draw.c +++ b/source/blender/editors/interface/view2d_draw.c @@ -53,7 +53,7 @@ /* Compute display grid resolution ********************************************************/ -#define MIN_MAJOR_LINE_DISTANCE (UI_DPI_FAC * 50) +#define MIN_MAJOR_LINE_DISTANCE (U.v2d_min_gridsize * UI_DPI_FAC) static float select_major_distance(const float *possible_distances, uint amount, @@ -267,6 +267,10 @@ static void draw_horizontal_scale_indicators(const ARegion *ar, void *to_string_data, int colorid) { + if (UI_view2d_scale_get_x(v2d) <= 0.0f) { + return; + } + GPU_matrix_push_projection(); wmOrtho2_region_pixelspace(ar); @@ -318,6 +322,10 @@ static void draw_vertical_scale_indicators(const ARegion *ar, void *to_string_data, int colorid) { + if (UI_view2d_scale_get_y(v2d) <= 0.0f) { + return; + } + GPU_matrix_push_projection(); wmOrtho2_region_pixelspace(ar); diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c index e2b3b6aa8c6..9fdcec71cfd 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -108,7 +108,7 @@ static int cachefile_open_exec(bContext *C, wmOperator *op) PointerRNA idptr; RNA_id_pointer_create(&cache_file->id, &idptr); - RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL); RNA_property_update(C, &pprop->ptr, pprop->prop); } diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 9796bf89cf3..1f844961d19 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -81,6 +81,9 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) { char filepath[FILE_MAX]; int apply_modifiers; + int global_forward; + int global_up; + int apply_global_orientation; int export_mesh_type; int selected; int include_children; @@ -103,7 +106,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int use_object_instantiation; int use_blender_profile; int sort_by_name; - int export_transformation_type; + int export_object_transformation_type; + int export_animation_transformation_type; int open_sim; int limit_precision; @@ -140,6 +144,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) /* Options panel */ apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers"); export_mesh_type = RNA_enum_get(op->ptr, "export_mesh_type_selection"); + global_forward = RNA_enum_get(op->ptr, "export_global_forward_selection"); + global_up = RNA_enum_get(op->ptr, "export_global_up_selection"); + apply_global_orientation = RNA_boolean_get(op->ptr, "apply_global_orientation"); + selected = RNA_boolean_get(op->ptr, "selected"); include_children = RNA_boolean_get(op->ptr, "include_children"); include_armatures = RNA_boolean_get(op->ptr, "include_armatures"); @@ -163,9 +171,13 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation"); use_blender_profile = RNA_boolean_get(op->ptr, "use_blender_profile"); sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name"); - export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection"); - open_sim = RNA_boolean_get(op->ptr, "open_sim"); + export_object_transformation_type = RNA_enum_get(op->ptr, + "export_object_transformation_type_selection"); + export_animation_transformation_type = RNA_enum_get( + op->ptr, "export_animation_transformation_type_selection"); + + open_sim = RNA_boolean_get(op->ptr, "open_sim"); limit_precision = RNA_boolean_get(op->ptr, "limit_precision"); keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info"); @@ -181,6 +193,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) export_settings.filepath = filepath; export_settings.apply_modifiers = apply_modifiers != 0; + export_settings.global_forward = global_forward; + export_settings.global_up = global_up; + export_settings.apply_global_orientation = apply_global_orientation != 0; + export_settings.export_mesh_type = export_mesh_type; export_settings.selected = selected != 0; export_settings.include_children = include_children != 0; @@ -201,23 +217,24 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) export_settings.use_object_instantiation = use_object_instantiation != 0; export_settings.use_blender_profile = use_blender_profile != 0; export_settings.sort_by_name = sort_by_name != 0; + export_settings.object_transformation_type = export_object_transformation_type; + export_settings.animation_transformation_type = export_animation_transformation_type; + export_settings.keep_smooth_curves = keep_smooth_curves != 0; - if (export_animation_type == BC_ANIMATION_EXPORT_SAMPLES) { - export_settings.export_transformation_type = export_transformation_type; - } - else { + if (export_animation_type != BC_ANIMATION_EXPORT_SAMPLES) { // When curves are exported then we can not export as matrix - export_settings.export_transformation_type = BC_TRANSFORMATION_TYPE_TRANSROTLOC; + export_settings.animation_transformation_type = BC_TRANSFORMATION_TYPE_DECOMPOSED; } - if (export_settings.export_transformation_type == BC_TRANSFORMATION_TYPE_TRANSROTLOC) { - export_settings.keep_smooth_curves = keep_smooth_curves != 0; - } - else { + if (export_settings.animation_transformation_type != BC_TRANSFORMATION_TYPE_DECOMPOSED) { // Can not export smooth curves when Matrix export is enabled. export_settings.keep_smooth_curves = false; } + if (include_animations) { + export_settings.object_transformation_type = export_settings.animation_transformation_type; + } + export_settings.open_sim = open_sim != 0; export_settings.limit_precision = limit_precision != 0; export_settings.keep_bind_info = keep_bind_info != 0; @@ -250,14 +267,15 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) { - uiLayout *box, *row, *col, *split; + uiLayout *bbox, *box, *row, *col, *split; bool include_animations = RNA_boolean_get(imfptr, "include_animations"); int ui_section = RNA_enum_get(imfptr, "prop_bc_export_ui_section"); BC_export_animation_type animation_type = RNA_enum_get(imfptr, "export_animation_type_selection"); - BC_export_transformation_type transformation_type = RNA_enum_get( - imfptr, "export_transformation_type_selection"); + + BC_export_transformation_type animation_transformation_type = RNA_enum_get( + imfptr, "export_animation_transformation_type_selection"); bool sampling = animation_type == BC_ANIMATION_EXPORT_SAMPLES; @@ -272,6 +290,18 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) /* Export Data options */ /* =================== */ + bbox = uiLayoutBox(layout); + row = uiLayoutRow(bbox, false); + uiItemL(row, IFACE_("Global Orientation:"), ICON_ORIENTATION_GLOBAL); + row = uiLayoutRow(bbox, false); + uiItemR(row, imfptr, "export_global_forward_selection", 0, "", ICON_NONE); + + row = uiLayoutRow(bbox, false); + uiItemR(row, imfptr, "export_global_up_selection", 0, "", ICON_NONE); + + row = uiLayoutRow(bbox, false); + uiItemR(row, imfptr, "apply_global_orientation", 0, NULL, ICON_NONE); + row = uiLayoutRow(box, false); uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE); @@ -287,6 +317,8 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE); uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected")); + row = uiLayoutRow(box, false); + /* Texture options */ box = uiLayoutBox(layout); row = uiLayoutRow(box, false); @@ -304,13 +336,26 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutRow(box, false); split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT); + col = uiLayoutColumn(split, false); uiItemR(col, imfptr, "apply_modifiers", 0, NULL, ICON_NONE); + col = uiLayoutColumn(split, false); uiItemR(col, imfptr, "export_mesh_type_selection", 0, "", ICON_NONE); uiLayoutSetEnabled(col, RNA_boolean_get(imfptr, "apply_modifiers")); + + col = uiLayoutColumn(box, false); + uiItemR(col, imfptr, "triangulate", 1, NULL, ICON_NONE); + row = uiLayoutRow(box, false); - uiItemR(row, imfptr, "triangulate", 1, NULL, ICON_NONE); + split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT); + uiItemL(split, IFACE_("Transformation Type"), ICON_NONE); + if (RNA_boolean_get(imfptr, "include_animations")) { + uiItemR(split, imfptr, "export_animation_transformation_type_selection", 0, "", ICON_NONE); + } + else { + uiItemR(split, imfptr, "export_object_transformation_type_selection", 0, "", ICON_NONE); + } } else if (ui_section == BC_UI_SECTION_ARMATURE) { /* Armature options */ @@ -335,18 +380,24 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutRow(box, false); uiItemR(row, imfptr, "export_animation_type_selection", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiLayoutSetEnabled(row, include_animations); row = uiLayoutRow(box, false); split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT); uiItemL(split, IFACE_("Transformation Type"), ICON_NONE); - uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE); - uiLayoutSetEnabled(row, animation_type == BC_ANIMATION_EXPORT_SAMPLES); + if (RNA_boolean_get(imfptr, "include_animations")) { + uiItemR(split, imfptr, "export_animation_transformation_type_selection", 0, "", ICON_NONE); + } + else { + uiItemR(split, imfptr, "export_object_transformation_type_selection", 0, "", ICON_NONE); + } + uiLayoutSetEnabled(row, include_animations && animation_type == BC_ANIMATION_EXPORT_SAMPLES); row = uiLayoutColumn(box, false); uiItemR(row, imfptr, "keep_smooth_curves", 0, NULL, ICON_NONE); uiLayoutSetEnabled(row, include_animations && - (transformation_type == BC_TRANSFORMATION_TYPE_TRANSROTLOC || + (animation_transformation_type == BC_TRANSFORMATION_TYPE_DECOMPOSED || animation_type == BC_ANIMATION_EXPORT_KEYS)); row = uiLayoutColumn(box, false); @@ -359,6 +410,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutColumn(box, false); uiItemR(row, imfptr, "keep_flat_curves", 0, NULL, ICON_NONE); + uiLayoutSetEnabled(row, include_animations); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "include_all_actions", 0, NULL, ICON_NONE); @@ -418,17 +470,37 @@ void WM_OT_collada_export(wmOperatorType *ot) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem prop_bc_export_global_forward[] = { + {BC_GLOBAL_FORWARD_X, "X", 0, "X Forward", "Global Forward is positive X Axis"}, + {BC_GLOBAL_FORWARD_Y, "Y", 0, "Y Forward", "Global Forward is positive Y Axis"}, + {BC_GLOBAL_FORWARD_Z, "Z", 0, "Z Forward", "Global Forward is positive Z Axis"}, + {BC_GLOBAL_FORWARD_MINUS_X, "-X", 0, "-X Forward", "Global Forward is negative X Axis"}, + {BC_GLOBAL_FORWARD_MINUS_Y, "-Y", 0, "-Y Forward", "Global Forward is negative Y Axis"}, + {BC_GLOBAL_FORWARD_MINUS_Z, "-Z", 0, "-Z Forward", "Global Forward is negative Z Axis"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem prop_bc_export_global_up[] = { + {BC_GLOBAL_UP_X, "X", 0, "X Up", "Global UP is positive X Axis"}, + {BC_GLOBAL_UP_Y, "Y", 0, "Y Up", "Global UP is positive Y Axis"}, + {BC_GLOBAL_UP_Z, "Z", 0, "Z Up", "Global UP is positive Z Axis"}, + {BC_GLOBAL_UP_MINUS_X, "-X", 0, "-X Up", "Global UP is negative X Axis"}, + {BC_GLOBAL_UP_MINUS_Y, "-Y", 0, "-Y Up", "Global UP is negative Y Axis"}, + {BC_GLOBAL_UP_MINUS_Z, "-Z", 0, "-Z Up", "Global UP is negative Z Axis"}, + {0, NULL, 0, NULL, NULL}, + }; + static const EnumPropertyItem prop_bc_export_transformation_type[] = { {BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", - "Use <matrix> to specify transformations"}, - {BC_TRANSFORMATION_TYPE_TRANSROTLOC, - "transrotloc", + "Use <matrix> representation for exported transformations"}, + {BC_TRANSFORMATION_TYPE_DECOMPOSED, + "decomposed", 0, - "TransRotLoc", - "Use <translate>, <rotate>, <scale> to specify transformations"}, + "Decomposed", + "Use <rotate>, <translate> and <scale> representation for exported transformations"}, {0, NULL, 0, NULL, NULL}}; static const EnumPropertyItem prop_bc_export_animation_type[] = { @@ -503,6 +575,27 @@ void WM_OT_collada_export(wmOperatorType *ot) "Resolution", "Modifier resolution for export"); + RNA_def_enum(func, + "export_global_forward_selection", + prop_bc_export_global_forward, + BC_DEFAULT_FORWARD, + "Global Forward Axis", + "Global Forward axis for export"); + + RNA_def_enum(func, + "export_global_up_selection", + prop_bc_export_global_up, + BC_DEFAULT_UP, + "Global Up Axis", + "Global Up axis for export"); + + RNA_def_boolean(func, + "apply_global_orientation", + false, + "Apply Global Orientation", + "enabled: Rotate all root objects to match the global orientation " + "settings.\ndisabled: set global orientation in Collada assets"); + RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements"); RNA_def_boolean(func, @@ -611,21 +704,42 @@ void WM_OT_collada_export(wmOperatorType *ot) func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name"); RNA_def_int(func, - "export_transformation_type", + "export_object_transformation_type", + 0, + INT_MIN, + INT_MAX, + "Transform", + "Object Transformation type for translation, scale and rotation", + INT_MIN, + INT_MAX); + + RNA_def_enum(func, + "export_object_transformation_type_selection", + prop_bc_export_transformation_type, + 0, + "Transform", + "Object Transformation type for translation, scale and rotation"); + + RNA_def_int(func, + "export_animation_transformation_type", 0, INT_MIN, INT_MAX, "Transform", - "Transformation type for translation, scale and rotation", + "Transformation type for translation, scale and rotation\n" + "Note: The Animation transformation type in the Anim Tab\n" + "is always equal to the Object transformation type in the Geom tab", INT_MIN, INT_MAX); RNA_def_enum(func, - "export_transformation_type_selection", + "export_animation_transformation_type_selection", prop_bc_export_transformation_type, 0, "Transform", - "Transformation type for translation, scale and rotation"); + "Transformation type for translation, scale and rotation\n" + "Note: The Animation transformation type in the Anim Tab\n" + "is always equal to the Object transformation type in the Geom tab"); RNA_def_boolean(func, "open_sim", diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 3c456f9e2e2..fc85eab6e66 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -29,6 +29,7 @@ #include "BKE_mask.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -47,7 +48,7 @@ #include "mask_intern.h" /* own include */ bool ED_mask_find_nearest_diff_point(const bContext *C, - struct Mask *mask, + struct Mask *mask_orig, const float normal_co[2], int threshold, bool feather, @@ -63,7 +64,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - MaskLayer *masklay, *point_masklay; + MaskLayer *point_masklay; MaskSpline *point_spline; MaskSplinePoint *point = NULL; float dist_best_sq = FLT_MAX, co[2]; @@ -71,31 +72,36 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, float u = 0.0f; float scalex, scaley; + Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C); + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id); + ED_mask_get_size(sa, &width, &height); ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley); co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - MaskSpline *spline; - - if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + for (MaskLayer *masklay_orig = mask_orig->masklayers.first, + *masklay_eval = mask_eval->masklayers.first; + masklay_orig != NULL; + masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next) { + if (masklay_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = masklay->splines.first; spline; spline = spline->next) { + for (MaskSpline *spline_orig = masklay_orig->splines.first, + *spline_eval = masklay_eval->splines.first; + spline_orig != NULL; + spline_orig = spline_orig->next, spline_eval = spline_eval->next) { int i; - MaskSplinePoint *cur_point; + MaskSplinePoint *cur_point_eval; - for (i = 0, cur_point = use_deform ? spline->points_deform : spline->points; - i < spline->tot_point; - i++, cur_point++) { - float *diff_points; + for (i = 0, cur_point_eval = use_deform ? spline_eval->points_deform : spline_eval->points; + i < spline_eval->tot_point; + i++, cur_point_eval++) { unsigned int tot_diff_point; - - diff_points = BKE_mask_point_segment_diff( - spline, cur_point, width, height, &tot_diff_point); + float *diff_points = BKE_mask_point_segment_diff( + spline_eval, cur_point_eval, width, height, &tot_diff_point); if (diff_points) { int j, tot_point; @@ -104,7 +110,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, if (feather) { feather_points = BKE_mask_point_segment_feather_diff( - spline, cur_point, width, height, &tot_feather_point); + spline_eval, cur_point_eval, width, height, &tot_feather_point); points = feather_points; tot_point = tot_feather_point; @@ -130,19 +136,19 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]); } - point_masklay = masklay; - point_spline = spline; - point = use_deform ? &spline->points[(cur_point - spline->points_deform)] : - cur_point; + point_masklay = masklay_orig; + point_spline = spline_orig; + point = use_deform ? + &spline_orig->points[(cur_point_eval - spline_eval->points_deform)] : + &spline_orig->points[(cur_point_eval - spline_eval->points)]; dist_best_sq = dist_sq; u = (float)j / tot_point; } } - if (feather_points) { + if (feather_points != NULL) { MEM_freeN(feather_points); } - MEM_freeN(diff_points); } } @@ -580,7 +586,6 @@ static bool add_vertex_new(const bContext *C, Mask *mask, MaskLayer *masklay, co static int add_vertex_exec(bContext *C, wmOperator *op) { - Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; @@ -626,8 +631,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) BKE_mask_calc_handle_point_auto(spline, point, false); BKE_mask_calc_handle_point_auto(spline, point_other, false); - /* TODO: only update this spline */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); return OPERATOR_FINISHED; @@ -648,8 +652,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) } } - /* TODO: only update this spline */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); return OPERATOR_FINISHED; } @@ -716,7 +719,6 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) if (ED_mask_find_nearest_diff_point( C, mask, co, threshold, true, NULL, true, true, &masklay, &spline, &point, &u, NULL)) { - Scene *scene = CTX_data_scene(C); float w = BKE_mask_point_weight(spline, point, u); float weight_scalar = BKE_mask_point_weight_scalar(spline, point, u); @@ -726,12 +728,10 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) BKE_mask_point_add_uw(point, u, w); - BKE_mask_update_display(mask, scene->r.cfra); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); - DEG_id_tag_update(&mask->id, 0); - return OPERATOR_FINISHED; } @@ -786,7 +786,6 @@ static int create_primitive_from_points( bContext *C, wmOperator *op, const float (*points)[2], int num_points, char handle_type) { ScrArea *sa = CTX_wm_area(C); - Scene *scene = CTX_data_scene(C); Mask *mask; MaskLayer *mask_layer; MaskSpline *new_spline; @@ -848,8 +847,7 @@ static int create_primitive_from_points( } WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); - /* TODO: only update this spline */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 305e3a328ab..33e89b1a7c5 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -52,6 +52,8 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "DEG_depsgraph_query.h" + #include "mask_intern.h" /* own include */ static void mask_spline_color_get(MaskLayer *masklay, @@ -672,7 +674,8 @@ static float *mask_rasterize(Mask *mask, const int width, const int height) /* sets up the opengl context. * width, height are to match the values from ED_mask_get_size() */ void ED_mask_draw_region( - Mask *mask, + Depsgraph *depsgraph, + Mask *mask_, ARegion *ar, const char draw_flag, const char draw_type, @@ -690,6 +693,7 @@ void ED_mask_draw_region( const bContext *C) { struct View2D *v2d = &ar->v2d; + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_->id); /* aspect always scales vertically in movie and image spaces */ const float width = width_i, height = (float)height_i * (aspy / aspx); @@ -735,7 +739,7 @@ void ED_mask_draw_region( if (draw_flag & MASK_DRAWFLAG_OVERLAY) { float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; - float *buffer = mask_rasterize(mask, width, height); + float *buffer = mask_rasterize(mask_eval, width, height); if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) { /* More blending types could be supported in the future. */ @@ -779,7 +783,7 @@ void ED_mask_draw_region( } /* draw! */ - draw_masklays(C, mask, draw_flag, draw_type, width, height); + draw_masklays(C, mask_eval, draw_flag, draw_type, width, height); if (do_draw_cb) { ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 1f825c0bb31..5a7a84dbbc8 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -31,6 +31,7 @@ #include "BKE_mask.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "DNA_scene_types.h" #include "DNA_mask_types.h" @@ -65,7 +66,7 @@ static void mask_point_scaled_handle(/*const*/ MaskSplinePoint *point, } MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, - Mask *mask, + Mask *mask_orig, const float normal_co[2], const float threshold, MaskLayer **masklay_r, @@ -76,7 +77,6 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - MaskLayer *masklay; MaskLayer *point_masklay = NULL; MaskSpline *point_spline = NULL; MaskSplinePoint *point = NULL; @@ -86,29 +86,35 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, eMaskWhichHandle which_handle = MASK_WHICH_HANDLE_NONE; int width, height; + Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C); + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id); + ED_mask_get_size(sa, &width, &height); ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley); co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - MaskSpline *spline; + for (MaskLayer *masklay_orig = mask_orig->masklayers.first, + *masklay_eval = mask_eval->masklayers.first; + masklay_orig != NULL; + masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next) { - if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - for (spline = masklay->splines.first; spline; spline = spline->next) { - MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); - - int i; + for (MaskSpline *spline_orig = masklay_orig->splines.first, + *spline_eval = masklay_eval->splines.first; + spline_orig != NULL; + spline_orig = spline_orig->next, spline_eval = spline_eval->next) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline_eval); - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *cur_point = &spline->points[i]; - MaskSplinePoint *cur_point_deform = &points_array[i]; + for (int i = 0; i < spline_orig->tot_point; i++) { + MaskSplinePoint *cur_point_orig = &spline_orig->points[i]; + MaskSplinePoint *cur_point_deform_eval = &points_array[i]; eMaskWhichHandle cur_which_handle = MASK_WHICH_HANDLE_NONE; - BezTriple *bezt = &cur_point_deform->bezt; + BezTriple *bezt = &cur_point_deform_eval->bezt; float cur_len_sq, vec[2]; vec[0] = bezt->vec[1][0] * scalex; @@ -117,17 +123,17 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, cur_len_sq = len_squared_v2v2(co, vec); if (cur_len_sq < len_sq) { - point_spline = spline; - point_masklay = masklay; - point = cur_point; + point_spline = spline_orig; + point_masklay = masklay_orig; + point = cur_point_orig; len_sq = cur_len_sq; which_handle = MASK_WHICH_HANDLE_NONE; } - if (BKE_mask_point_handles_mode_get(cur_point_deform) == MASK_HANDLE_MODE_STICK) { + if (BKE_mask_point_handles_mode_get(cur_point_deform_eval) == MASK_HANDLE_MODE_STICK) { float handle[2]; mask_point_scaled_handle( - cur_point_deform, MASK_WHICH_HANDLE_STICK, scalex, scaley, handle); + cur_point_deform_eval, MASK_WHICH_HANDLE_STICK, scalex, scaley, handle); cur_len_sq = len_squared_v2v2(co, handle); cur_which_handle = MASK_WHICH_HANDLE_STICK; } @@ -135,9 +141,9 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, float handle_left[2], handle_right[2]; float len_left_sq, len_right_sq; mask_point_scaled_handle( - cur_point_deform, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left); + cur_point_deform_eval, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left); mask_point_scaled_handle( - cur_point_deform, MASK_WHICH_HANDLE_RIGHT, scalex, scaley, handle_right); + cur_point_deform_eval, MASK_WHICH_HANDLE_RIGHT, scalex, scaley, handle_right); len_left_sq = len_squared_v2v2(co, handle_left); len_right_sq = len_squared_v2v2(co, handle_right); @@ -168,9 +174,9 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, } if (cur_len_sq <= len_sq && cur_which_handle != MASK_WHICH_HANDLE_NONE) { - point_masklay = masklay; - point_spline = spline; - point = cur_point; + point_masklay = masklay_orig; + point_spline = spline_orig; + point = cur_point_orig; len_sq = cur_len_sq; which_handle = cur_which_handle; } @@ -214,7 +220,7 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, } bool ED_mask_feather_find_nearest(const bContext *C, - Mask *mask, + Mask *mask_orig, const float normal_co[2], const float threshold, MaskLayer **masklay_r, @@ -226,7 +232,7 @@ bool ED_mask_feather_find_nearest(const bContext *C, ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - MaskLayer *masklay, *point_masklay = NULL; + MaskLayer *point_masklay = NULL; MaskSpline *point_spline = NULL; MaskSplinePoint *point = NULL; MaskSplinePointUW *uw = NULL; @@ -235,32 +241,41 @@ bool ED_mask_feather_find_nearest(const bContext *C, float scalex, scaley; int width, height; + Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C); + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id); + ED_mask_get_size(sa, &width, &height); ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley); co[0] = normal_co[0] * scalex; co[1] = normal_co[1] * scaley; - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - MaskSpline *spline; + for (MaskLayer *masklay_orig = mask_orig->masklayers.first, + *masklay_eval = mask_eval->masklayers.first; + masklay_orig != NULL; + masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next) { - for (spline = masklay->splines.first; spline; spline = spline->next) { + for (MaskSpline *spline_orig = masklay_orig->splines.first, + *spline_eval = masklay_eval->splines.first; + spline_orig != NULL; + spline_orig = spline_orig->next, spline_eval = spline_eval->next) { // MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); int i, tot_feather_point; float(*feather_points)[2], (*fp)[2]; - if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { continue; } - feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point); + feather_points = fp = BKE_mask_spline_feather_points(spline_eval, &tot_feather_point); - for (i = 0; i < spline->tot_point; i++) { + for (i = 0; i < spline_orig->tot_point; i++) { int j; - MaskSplinePoint *cur_point = &spline->points[i]; + MaskSplinePoint *cur_point_orig = &spline_orig->points[i]; + MaskSplinePoint *cur_point_eval = &spline_eval->points[i]; - for (j = 0; j <= cur_point->tot_uw; j++) { + for (j = 0; j <= cur_point_eval->tot_uw; j++) { float cur_len_sq, vec[2]; vec[0] = (*fp)[0] * scalex; @@ -273,12 +288,12 @@ bool ED_mask_feather_find_nearest(const bContext *C, uw = NULL; } else { - uw = &cur_point->uw[j - 1]; + uw = &cur_point_eval->uw[j - 1]; } - point_masklay = masklay; - point_spline = spline; - point = cur_point; + point_masklay = masklay_orig; + point_spline = spline_orig; + point = cur_point_orig; len = cur_len_sq; } @@ -1648,7 +1663,6 @@ static void delete_feather_points(MaskSplinePoint *point) static int delete_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; bool changed = false; @@ -1743,8 +1757,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - /* TODO: only update edited splines */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1801,8 +1814,7 @@ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) } if (changed) { - /* TODO: only update this spline */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -1867,8 +1879,7 @@ static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op) } if (changed) { - /* TODO: only update this spline */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -2094,7 +2105,6 @@ void MASK_OT_hide_view_set(wmOperatorType *ot) static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *masklay; bool changed = false; @@ -2121,8 +2131,7 @@ static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op)) } if (changed) { - /* TODO: only update edited splines */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask); DEG_id_tag_update(&mask->id, 0); @@ -2234,7 +2243,6 @@ void MASK_OT_layer_move(wmOperatorType *ot) static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *mask_layer; @@ -2324,8 +2332,7 @@ static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) } } - /* TODO: only update edited splines */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); @@ -2391,7 +2398,6 @@ static bool paste_splines_poll(bContext *C) static int paste_splines_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); Mask *mask = CTX_data_edit_mask(C); MaskLayer *mask_layer = BKE_mask_layer_active(mask); @@ -2401,8 +2407,7 @@ static int paste_splines_exec(bContext *C, wmOperator *UNUSED(op)) BKE_mask_clipboard_paste_to_layer(CTX_data_main(C), mask_layer); - /* TODO: only update edited splines */ - BKE_mask_update_display(mask, CFRA); + DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index a592f39d24b..717ce9fd72e 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -43,6 +43,8 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "DEG_depsgraph.h" + #include "mask_intern.h" /* own include */ /* -------------------------------------------------------------------- */ @@ -223,6 +225,7 @@ static int select_all_exec(bContext *C, wmOperator *op) ED_mask_select_toggle_all(mask, action); ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -326,6 +329,7 @@ static int select_exec(bContext *C, wmOperator *op) ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -365,6 +369,7 @@ static int select_exec(bContext *C, wmOperator *op) ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -374,6 +379,7 @@ static int select_exec(bContext *C, wmOperator *op) ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -488,6 +494,7 @@ static int box_select_exec(bContext *C, wmOperator *op) if (changed) { ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -592,6 +599,7 @@ static bool do_lasso_select_mask(bContext *C, if (changed) { ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); } @@ -719,6 +727,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) if (changed) { ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -783,6 +792,7 @@ static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE if (changed) { ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -840,6 +850,7 @@ static int mask_select_linked_exec(bContext *C, wmOperator *UNUSED(op)) if (changed) { ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; @@ -940,6 +951,7 @@ static int mask_select_more_less(bContext *C, bool more) } } + DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); return OPERATOR_FINISHED; diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index fdbcc3449b2..d61c340f7a2 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -441,74 +441,6 @@ bool paintface_mouse_select( return true; } -bool do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op) -{ - Object *ob = vc->obact; - Mesh *me; - - me = BKE_mesh_from_object(ob); - if ((me == NULL) || (me->totpoly == 0)) { - return false; - } - - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false); - } - - if (BLI_rcti_is_empty(rect)) { - /* pass */ - } - else { - MPoly *mpoly; - uint *rt, *buf, buf_len; - int a, index; - - char *selar = MEM_callocN(me->totpoly + 1, "selar"); - - ED_view3d_select_id_validate(vc); - buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); - - rt = buf; - - a = buf_len; - while (a--) { - if (*rt) { - index = *rt; - if (index <= me->totpoly) { - selar[index] = 1; - } - } - rt++; - } - - mpoly = me->mpoly; - for (a = 1; a <= me->totpoly; a++, mpoly++) { - if ((mpoly->flag & ME_HIDE) == 0) { - const bool is_select = mpoly->flag & ME_FACE_SEL; - const bool is_inside = (selar[a] != 0); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL); - changed = true; - } - } - } - - MEM_freeN(buf); - MEM_freeN(selar); - -#ifdef __APPLE__ - glReadBuffer(GL_BACK); -#endif - } - - if (changed) { - paintface_flush_flags(vc->C, vc->obact, SELECT); - } - return changed; -} - /* (similar to void paintface_flush_flags(Object *ob)) * copy the vertex flags, most importantly selection from the mesh to the final derived mesh, * use in object mode when selecting vertices (while painting) */ diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index bc60ff9274f..1d173d8e396 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -148,7 +148,7 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event) BisectData *opdata; opdata = MEM_mallocN(sizeof(BisectData), "inset_operator_data"); - gesture->userdata = opdata; + gesture->user_data.data = opdata; opdata->backup_len = objects_len; opdata->backup = MEM_callocN(sizeof(*opdata->backup) * objects_len, __func__); @@ -193,7 +193,7 @@ static void edbm_bisect_exit(bContext *C, BisectData *opdata) static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmGesture *gesture = op->customdata; - BisectData *opdata = gesture->userdata; + BisectData *opdata = gesture->user_data.data; BisectData opdata_back = *opdata; /* annoyance, WM_gesture_straightline_modal, frees */ int ret; @@ -276,7 +276,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op) } wmGesture *gesture = op->customdata; - BisectData *opdata = (gesture != NULL) ? gesture->userdata : NULL; + BisectData *opdata = (gesture != NULL) ? gesture->user_data.data : NULL; /* -------------------------------------------------------------------- */ /* Modal support */ diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c index 269ead7b23f..74700e59e99 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c @@ -295,7 +295,8 @@ static void gizmo_mesh_spin_init_draw_prepare(const bContext *C, wmGizmoGroup *g static void gizmo_mesh_spin_init_invoke_prepare(const bContext *UNUSED(C), wmGizmoGroup *gzgroup, - wmGizmo *gz) + wmGizmo *gz, + const wmEvent *UNUSED(event)) { /* Set the initial ortho axis. */ GizmoGroupData_SpinInit *ggd = gzgroup->customdata; diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index e45c15b3e53..976dbe01a22 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1156,19 +1156,20 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vert, NULL, GPU_BATCH_OWNS_VBO); GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); + GPU_batch_bind(batch); /* draw any snapped verts first */ rgba_uchar_to_float(fcol, kcd->colors.point_a); GPU_batch_uniform_4fv(batch, "color", fcol); GPU_matrix_bind(batch->interface); GPU_point_size(11); - GPU_batch_draw_range_ex(batch, 0, v - 1, false); + GPU_batch_draw_advanced(batch, 0, v - 1, 0, 0); /* now draw the rest */ rgba_uchar_to_float(fcol, kcd->colors.curpoint_a); GPU_batch_uniform_4fv(batch, "color", fcol); GPU_point_size(7); - GPU_batch_draw_range_ex(batch, vs + 1, kcd->totlinehit - (vs + 1), false); + GPU_batch_draw_advanced(batch, vs + 1, kcd->totlinehit - (vs + 1), 0, 0); GPU_batch_program_use_end(batch); GPU_batch_discard(batch); diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index f8ec4334427..6fd0ee83b6c 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -63,6 +63,15 @@ /** \name Path Select Struct & Properties * \{ */ +enum { + EDGE_MODE_SELECT = 0, + EDGE_MODE_TAG_SEAM = 1, + EDGE_MODE_TAG_SHARP = 2, + EDGE_MODE_TAG_CREASE = 3, + EDGE_MODE_TAG_BEVEL = 4, + EDGE_MODE_TAG_FREESTYLE = 5, +}; + struct PathSelectParams { /** ensure the active element is the last selected item (handy for picking) */ bool track_active; @@ -75,6 +84,23 @@ struct PathSelectParams { static void path_select_properties(wmOperatorType *ot) { + static const EnumPropertyItem edge_tag_items[] = { + {EDGE_MODE_SELECT, "SELECT", 0, "Select", ""}, + {EDGE_MODE_TAG_SEAM, "SEAM", 0, "Tag Seam", ""}, + {EDGE_MODE_TAG_SHARP, "SHARP", 0, "Tag Sharp", ""}, + {EDGE_MODE_TAG_CREASE, "CREASE", 0, "Tag Crease", ""}, + {EDGE_MODE_TAG_BEVEL, "BEVEL", 0, "Tag Bevel", ""}, + {EDGE_MODE_TAG_FREESTYLE, "FREESTYLE", 0, "Tag Freestyle Edge Mark", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + RNA_def_enum(ot->srna, + "edge_mode", + edge_tag_items, + EDGE_MODE_SELECT, + "Edge Tag", + "The edge flag to tag when selecting the shortest path"); + RNA_def_boolean(ot->srna, "use_face_step", false, @@ -93,9 +119,24 @@ static void path_select_properties(wmOperatorType *ot) WM_operator_properties_checker_interval(ot, true); } -static void path_select_params_from_op(wmOperator *op, struct PathSelectParams *op_params) +static void path_select_params_from_op(wmOperator *op, + ToolSettings *ts, + struct PathSelectParams *op_params) { - op_params->edge_mode = EDGE_MODE_SELECT; + { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "edge_mode"); + if (RNA_property_is_set(op->ptr, prop)) { + op_params->edge_mode = RNA_property_enum_get(op->ptr, prop); + if (op->flag & OP_IS_INVOKE) { + ts->edge_mode = op_params->edge_mode; + } + } + else { + op_params->edge_mode = ts->edge_mode; + RNA_property_enum_set(op->ptr, prop, op_params->edge_mode); + } + } + op_params->track_active = false; op_params->use_face_step = RNA_boolean_get(op->ptr, "use_face_step"); op_params->use_fill = RNA_boolean_get(op->ptr, "use_fill"); @@ -103,6 +144,21 @@ static void path_select_params_from_op(wmOperator *op, struct PathSelectParams * WM_operator_properties_checker_interval_from_op(op, &op_params->interval_params); } +static bool path_select_poll_property(const bContext *C, + wmOperator *UNUSED(op), + const PropertyRNA *prop) +{ + const char *prop_id = RNA_property_identifier(prop); + if (STREQ(prop_id, "edge_mode")) { + const Scene *scene = CTX_data_scene(C); + ToolSettings *ts = scene->toolsettings; + if ((ts->selectmode & SCE_SELECT_EDGE) == 0) { + return false; + } + } + return true; +} + struct UserData { BMesh *bm; Mesh *me; @@ -319,7 +375,7 @@ static void edgetag_ensure_cd_flag(Mesh *me, const char edge_mode) /* mesh shortest path select, uses prev-selected edge */ /* since you want to create paths with multiple selects, it doesn't have extend option */ -static void mouse_mesh_shortest_path_edge(Scene *UNUSED(scene), +static void mouse_mesh_shortest_path_edge(Scene *scene, Object *obedit, const struct PathSelectParams *op_params, BMEdge *e_act, @@ -421,6 +477,10 @@ static void mouse_mesh_shortest_path_edge(Scene *UNUSED(scene), } EDBM_update_generic(em, false, false); + + if (op_params->edge_mode == EDGE_MODE_TAG_SEAM) { + ED_uvedit_live_unwrap(scene, &obedit, 1); + } } /** \} */ @@ -649,12 +709,14 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE return OPERATOR_FINISHED; } + struct PathSelectParams op_params; + path_select_params_from_op(op, vc.scene->toolsettings, &op_params); + BMElem *ele_src, *ele_dst; if (!(ele_src = edbm_elem_active_elem_or_face_get(em->bm)) || !(ele_dst = edbm_elem_find_nearest(&vc, ele_src->head.htype))) { /* special case, toggle edge tags even when we don't have a path */ - if (((em->selectmode & SCE_SELECT_EDGE) && - (vc.scene->toolsettings->edge_mode != EDGE_MODE_SELECT)) && + if (((em->selectmode & SCE_SELECT_EDGE) && (op_params.edge_mode != EDGE_MODE_SELECT)) && /* check if we only have a destination edge */ ((ele_src == NULL) && (ele_dst = edbm_elem_find_nearest(&vc, BM_EDGE)))) { ele_src = ele_dst; @@ -665,11 +727,7 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE } } - struct PathSelectParams op_params; - - path_select_params_from_op(op, &op_params); op_params.track_active = track_active; - op_params.edge_mode = vc.scene->toolsettings->edge_mode; if (!edbm_shortest_path_pick_ex(vc.scene, vc.obedit, &op_params, ele_src, ele_dst)) { return OPERATOR_PASS_THROUGH; @@ -707,9 +765,8 @@ static int edbm_shortest_path_pick_exec(bContext *C, wmOperator *op) } struct PathSelectParams op_params; - path_select_params_from_op(op, &op_params); + path_select_params_from_op(op, scene->toolsettings, &op_params); op_params.track_active = true; - op_params.edge_mode = scene->toolsettings->edge_mode; if (!edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst)) { return OPERATOR_CANCELLED; @@ -731,6 +788,7 @@ void MESH_OT_shortest_path_pick(wmOperatorType *ot) ot->invoke = edbm_shortest_path_pick_invoke; ot->exec = edbm_shortest_path_pick_exec; ot->poll = ED_operator_editmesh_region_view3d; + ot->poll_property = path_select_poll_property; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -832,7 +890,7 @@ static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op) if (ele_src && ele_dst) { struct PathSelectParams op_params; - path_select_params_from_op(op, &op_params); + path_select_params_from_op(op, scene->toolsettings, &op_params); edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst); @@ -860,6 +918,7 @@ void MESH_OT_shortest_path_select(wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_shortest_path_select_exec; ot->poll = ED_operator_editmesh; + ot->poll_property = path_select_poll_property; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 485d855e18e..6a91fcb8327 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -53,6 +53,7 @@ #include "ED_mesh.h" #include "ED_screen.h" #include "ED_transform.h" +#include "ED_select_buffer_utils.h" #include "ED_select_utils.h" #include "ED_view3d.h" @@ -199,8 +200,19 @@ void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag) * \{ */ struct EDBMBaseOffset { - uint face; - uint edge; + /* For convenience only. */ + union { + uint offset; + uint face_start; + }; + union { + uint face; + uint edge_start; + }; + union { + uint edge; + uint vert_start; + }; uint vert; }; @@ -209,18 +221,21 @@ struct EDBMSelectID_Context { /** Borrow from caller (not freed). */ struct Base **bases; uint bases_len; + /** Total number of items `base_array_index_offsets[bases_len - 1].vert`. */ + uint base_array_index_len; }; static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, char dt) { if (select_mode & SCE_SELECT_FACE) { - if (dt < OB_SOLID) { + if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) { return true; } if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) { return true; } - if (XRAY_FLAG_ENABLED(v3d)) { + if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) { + /* Since we can't deduce face selection when edges aren't visible - show dots. */ return true; } } @@ -234,7 +249,7 @@ static void edbm_select_pick_draw_bases(struct EDBMSelectID_Context *sel_id_ctx, Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id); DRW_framebuffer_select_id_setup(vc->ar, true); - uint offset = 0; + uint offset = 1; for (uint base_index = 0; base_index < sel_id_ctx->bases_len; base_index++) { Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, sel_id_ctx->bases[base_index]->object); @@ -252,9 +267,12 @@ static void edbm_select_pick_draw_bases(struct EDBMSelectID_Context *sel_id_ctx, &base_ofs->edge, &base_ofs->face); + base_ofs->offset = offset; offset = base_ofs->vert; } + sel_id_ctx->base_array_index_len = offset; + DRW_framebuffer_select_id_release(vc->ar); } @@ -262,28 +280,26 @@ BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ctx, const uint sel_id, uint *r_base_index) { - char elem_type; + char elem_type = 0; uint elem_id; - uint prev_offs = 0; uint base_index = 0; for (; base_index < sel_id_ctx->bases_len; base_index++) { struct EDBMBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index]; if (base_ofs->face > sel_id) { - elem_id = sel_id - (prev_offs + 1); + elem_id = sel_id - base_ofs->face_start; elem_type = BM_FACE; break; } if (base_ofs->edge > sel_id) { - elem_id = sel_id - base_ofs->face; + elem_id = sel_id - base_ofs->edge_start; elem_type = BM_EDGE; break; } if (base_ofs->vert > sel_id) { - elem_id = sel_id - base_ofs->edge; + elem_id = sel_id - base_ofs->vert_start; elem_type = BM_VERT; break; } - prev_offs = base_ofs->vert; } if (r_base_index) { @@ -306,9 +322,32 @@ BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ctx, } } +uint EDBM_select_id_context_offset_for_object_elem(const struct EDBMSelectID_Context *sel_id_ctx, + int base_index, + char htype) +{ + struct EDBMBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index]; + if (htype == BM_VERT) { + return base_ofs->vert_start - 1; + } + if (htype == BM_EDGE) { + return base_ofs->edge_start - 1; + } + if (htype == BM_FACE) { + return base_ofs->face_start - 1; + } + BLI_assert(0); + return 0; +} + +uint EDBM_select_id_context_elem_len(const struct EDBMSelectID_Context *sel_id_ctx) +{ + return sel_id_ctx->base_array_index_len; +} + struct EDBMSelectID_Context *EDBM_select_id_context_create(ViewContext *vc, Base **bases, - uint bases_len, + const uint bases_len, short select_mode) { struct EDBMSelectID_Context *sel_id_ctx = MEM_mallocN(sizeof(*sel_id_ctx), __func__); @@ -328,192 +367,6 @@ void EDBM_select_id_context_destroy(struct EDBMSelectID_Context *sel_id_ctx) MEM_freeN(sel_id_ctx); } -/* 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 */ -static BLI_bitmap *selbuf = NULL; - -static BLI_bitmap *edbm_backbuf_alloc(const int size) -{ - return BLI_BITMAP_NEW(size, "selbuf"); -} - -/* reads rect, and builds selection array for quick lookup */ -/* returns if all is OK */ -bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) -{ - uint *buf, *dr, buf_len; - - if (vc->obedit == NULL || XRAY_FLAG_ENABLED(vc->v3d)) { - 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; - } - - dr = buf; - - /* build selection lookup */ - selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); - - while (buf_len--) { - if (*dr > 0 && *dr <= bm_vertoffs) { - BLI_BITMAP_ENABLE(selbuf, *dr); - } - dr++; - } - MEM_freeN(buf); - return true; -} - -bool EDBM_backbuf_check(unsigned int index) -{ - /* odd logic, if selbuf is NULL we assume no zbuf-selection is enabled - * and just ignore the depth buffer, this is error prone since its possible - * code doesn't set the depth buffer by accident, but leave for now. - Campbell */ - if (selbuf == NULL) { - return true; - } - - if (index > 0 && index <= bm_vertoffs) { - return BLI_BITMAP_TEST_BOOL(selbuf, index); - } - - return false; -} - -void EDBM_backbuf_free(void) -{ - if (selbuf) { - MEM_freeN(selbuf); - } - selbuf = NULL; -} - -struct LassoMaskData { - unsigned int *px; - int width; -}; - -static void edbm_mask_lasso_px_cb(int x, int x_end, int y, void *user_data) -{ - struct LassoMaskData *data = user_data; - unsigned int *px = &data->px[(y * data->width) + x]; - do { - *px = true; - px++; - } while (++x != x_end); -} - -/* mcords is a polygon mask - * - grab backbuffer, - * - draw with black in backbuffer, - * - grab again and compare - * returns 'OK' - */ -bool EDBM_backbuf_border_mask_init(ViewContext *vc, - const int mcords[][2], - short tot, - short xmin, - short ymin, - short xmax, - short ymax) -{ - uint *buf, *dr, *dr_mask, *dr_mask_arr, buf_len; - struct LassoMaskData lasso_mask_data; - - /* method in use for face selecting too */ - if (vc->obedit == NULL) { - if (!BKE_paint_select_elem_test(vc->obact)) { - return false; - } - } - else if (XRAY_FLAG_ENABLED(vc->v3d)) { - 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; - } - - dr = buf; - - dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf_len, __func__); - lasso_mask_data.px = dr_mask; - lasso_mask_data.width = (xmax - xmin) + 1; - - BLI_bitmap_draw_2d_poly_v2i_n( - xmin, ymin, xmax + 1, ymax + 1, mcords, tot, edbm_mask_lasso_px_cb, &lasso_mask_data); - - /* build selection lookup */ - selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); - - while (buf_len--) { - if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) { - BLI_BITMAP_ENABLE(selbuf, *dr); - } - dr++; - dr_mask++; - } - MEM_freeN(buf); - MEM_freeN(dr_mask_arr); - - return true; -} - -/* circle shaped sample area */ -bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) -{ - uint *buf, *dr; - short xmin, ymin, xmax, ymax, xc, yc; - int radsq; - - /* method in use for face selecting too */ - if (vc->obedit == NULL) { - if (!BKE_paint_select_elem_test(vc->obact)) { - return false; - } - } - else if (XRAY_FLAG_ENABLED(vc->v3d)) { - return false; - } - - xmin = xs - 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; - } - - dr = buf; - - /* build selection lookup */ - selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); - radsq = rads * rads; - for (yc = -rads; yc <= rads; yc++) { - for (xc = -rads; xc <= rads; xc++, dr++) { - if (xc * xc + yc * yc < radsq) { - if (*dr > 0 && *dr <= bm_vertoffs) { - BLI_BITMAP_ENABLE(selbuf, *dr); - } - } - } - } - - MEM_freeN(buf); - return true; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -625,7 +478,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create( vc, bases, bases_len, select_mode); - index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px); + index = ED_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px); if (index) { eve = (BMVert *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index); @@ -652,7 +505,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, } else { struct NearestVertUserData data = {{0}}; - const struct NearestVertUserData_Hit *hit; + const struct NearestVertUserData_Hit *hit = NULL; const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT; BMesh *prev_select_bm = NULL; @@ -697,6 +550,10 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, } } + if (hit == NULL) { + return NULL; + } + prev_select.index = hit->index; prev_select.elem = hit->vert; prev_select.bm = prev_select_bm; @@ -850,7 +707,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create( vc, bases, bases_len, select_mode); - index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px); + index = ED_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px); if (index) { eed = (BMEdge *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index); @@ -899,7 +756,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, } else { struct NearestEdgeUserData data = {{0}}; - const struct NearestEdgeUserData_Hit *hit; + const struct NearestEdgeUserData_Hit *hit = NULL; /* interpolate along the edge before doing a clipping plane test */ const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB; BMesh *prev_select_bm = NULL; @@ -946,6 +803,10 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, } } + if (hit == NULL) { + return NULL; + } + if (r_dist_center) { *r_dist_center = hit->dist_center; } @@ -1059,7 +920,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create( vc, bases, bases_len, select_mode); - index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]); + index = ED_select_buffer_sample_point(vc->mval); if (index) { efa = (BMFace *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index); @@ -1108,7 +969,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, } else { struct NearestFaceUserData data = {{0}}; - const struct NearestFaceUserData_Hit *hit; + const struct NearestFaceUserData_Hit *hit = NULL; const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT; BMesh *prev_select_bm = NULL; @@ -1153,6 +1014,10 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, } } + if (hit == NULL) { + return NULL; + } + if (r_dist_center) { *r_dist_center = hit->dist; } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 331be744932..60c6994eb2e 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -7688,6 +7688,7 @@ static int point_normals_init(bContext *C, wmOperator *op, const wmEvent *UNUSED BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; + BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); @@ -8077,7 +8078,7 @@ void MESH_OT_point_normals(struct wmOperatorType *ot) ot->exec = edbm_point_normals_exec; ot->invoke = edbm_point_normals_invoke; ot->modal = edbm_point_normals_modal; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; ot->ui = edbm_point_normals_ui; ot->cancel = point_normals_free; @@ -8243,6 +8244,7 @@ static int normals_split_merge(bContext *C, const bool do_merge) BMEdge *e; BMIter eiter; + BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm) : NULL; @@ -8288,7 +8290,7 @@ void MESH_OT_merge_normals(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_merge_normals_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -8308,7 +8310,7 @@ void MESH_OT_split_normals(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_split_normals_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -8346,6 +8348,7 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op) BMLoop *l, *l_curr, *l_first; BMIter fiter; + BKE_editmesh_ensure_autosmooth(em); bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL; BKE_editmesh_lnorspace_update(em); @@ -8506,7 +8509,7 @@ void MESH_OT_average_normals(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_average_normals_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; ot->ui = edbm_average_normals_ui; /* flags */ @@ -8569,6 +8572,7 @@ static int edbm_normals_tools_exec(bContext *C, wmOperator *op) const int mode = RNA_enum_get(op->ptr, "mode"); const bool absolute = RNA_boolean_get(op->ptr, "absolute"); + BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; @@ -8725,7 +8729,7 @@ void MESH_OT_normals_tools(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_normals_tools_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; ot->ui = edbm_normals_tools_ui; /* flags */ @@ -8765,6 +8769,7 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op) const bool keep_sharp = RNA_boolean_get(op->ptr, "keep_sharp"); + BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * bm->totvert, __func__); @@ -8830,6 +8835,7 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op) MEM_freeN(vnors); EDBM_update_generic(em, true, false); } + MEM_freeN(objects); return OPERATOR_FINISHED; } @@ -8843,7 +8849,7 @@ void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_set_normals_from_faces_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -8860,6 +8866,7 @@ static int edbm_smoothen_normals_exec(bContext *C, wmOperator *op) BMLoop *l; BMIter fiter, liter; + BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); @@ -8935,7 +8942,7 @@ void MESH_OT_smoothen_normals(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_smoothen_normals_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -9018,7 +9025,7 @@ void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_mod_weighted_strength_exec; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index e29cfa6b6e0..41736fb9a14 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -61,6 +61,7 @@ #include "DEG_depsgraph_query.h" #include "ED_mesh.h" +#include "ED_select_buffer_utils.h" #include "ED_object.h" #include "ED_view3d.h" @@ -1114,11 +1115,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, 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 */ - *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totpoly + 1, &dist_px); + *r_index = ED_select_buffer_find_nearest_to_point(mval, 1, me->totpoly + 1, &dist_px); } else { /* sample only on the exact position */ - *r_index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]); + *r_index = ED_select_buffer_sample_point(mval); } if ((*r_index) == 0 || (*r_index) > (unsigned int)me->totpoly) { @@ -1295,11 +1296,11 @@ bool ED_mesh_pick_vert( 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 */ - *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totvert + 1, &dist_px); + *r_index = ED_select_buffer_find_nearest_to_point(mval, 1, me->totvert + 1, &dist_px); } else { /* sample only on the exact position */ - *r_index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]); + *r_index = ED_select_buffer_sample_point(mval); } if ((*r_index) == 0 || (*r_index) > (uint)me->totvert) { diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 293b3a57fdb..dc2a353bd86 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1962,7 +1962,7 @@ static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Objec if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { /* We need 'for render' ON here, to enable computing bevel dipslist if needed. * Also makes sense anyway, we would not want e.g. to loose hidden parts etc. */ - BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false, NULL); + BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false); } else if (ob->type == OB_MBALL) { BKE_displist_make_mball(depsgraph, scene, ob); @@ -1970,13 +1970,30 @@ static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Objec } } -static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob) +static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Object *ob) { - convert_ensure_curve_cache(depsgraph, scene, ob); - BKE_mesh_from_nurbs(bmain, ob); /* also does users */ + Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); + Curve *curve = ob->data; + Mesh *mesh = BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object_eval, true); + BKE_object_free_modifiers(ob, 0); + /* Replace curve used by the object itself. */ + ob->data = mesh; + ob->type = OB_MESH; + id_us_min(&curve->id); + id_us_plus(&mesh->id); + /* Change objects which are using same curve. + * A bit annoying, but: + * - It's possible to have multiple curve objects selected which are sharing the same curve + * datablock. We don't want mesh to be created for every of those objects. + * - This is how conversion worked for a long long time. */ + LISTBASE_FOREACH (Object *, other_object, &bmain->objects) { + if (other_object->data == curve) { + other_object->type = OB_MESH; - if (ob->type == OB_MESH) { - BKE_object_free_modifiers(ob, 0); + id_us_min((ID *)other_object->data); + other_object->data = ob->data; + id_us_plus((ID *)other_object->data); + } } } @@ -2052,7 +2069,8 @@ static int convert_exec(bContext *C, wmOperator *op) FOREACH_SCENE_OBJECT_END; } - ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases"); + ListBase selected_editable_bases; + CTX_data_selected_editable_bases(C, &selected_editable_bases); /* Ensure we get all meshes calculated with a sufficient data-mask, * needed since re-evaluating single modifiers causes bugs if they depend @@ -2232,7 +2250,7 @@ static int convert_exec(bContext *C, wmOperator *op) BKE_curve_curve_dimension_update(cu); if (target == OB_MESH) { - curvetomesh(bmain, depsgraph, scene, newob); + curvetomesh(bmain, depsgraph, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); @@ -2256,7 +2274,7 @@ static int convert_exec(bContext *C, wmOperator *op) newob = ob; } - curvetomesh(bmain, depsgraph, scene, newob); + curvetomesh(bmain, depsgraph, newob); /* meshes doesn't use displist */ BKE_object_free_curve_cache(newob); diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index f87342a14ad..2f5a4b44412 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -707,7 +707,7 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re /* create new mesh with edit mode changes and modifiers applied */ static Mesh *bake_mesh_new_from_object(Object *object) { - Mesh *me = BKE_object_to_mesh(object); + Mesh *me = BKE_object_to_mesh(NULL, object, false); if (me->flag & ME_AUTOSMOOTH) { BKE_mesh_split_faces(me, true); @@ -946,7 +946,7 @@ static int bake(Render *re, md = md_next; } - me_cage = BKE_object_to_mesh(ob_low_eval); + me_cage = BKE_object_to_mesh(NULL, ob_low_eval, false); RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer); } @@ -965,7 +965,7 @@ static int bake(Render *re, highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter); highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER; highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER); - highpoly[i].me = BKE_object_to_mesh(highpoly[i].ob_eval); + highpoly[i].me = BKE_object_to_mesh(NULL, highpoly[i].ob_eval, false); /* lowpoly to highpoly transformation matrix */ copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat); @@ -1088,7 +1088,7 @@ static int bake(Render *re, } /* Evaluate modifiers again. */ - me_nores = BKE_object_to_mesh(ob_low_eval); + me_nores = BKE_object_to_mesh(NULL, ob_low_eval, false); RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer); RE_bake_normal_world_to_tangent(pixel_array_low, diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index e555f0d940d..8d3a636671a 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -108,7 +108,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object * BKE_displist_make_mball(depsgraph, scene_eval, ob_eval); } else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false, NULL); + BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false); } } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index e15d85a7953..6df012cdc80 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -697,7 +697,7 @@ bool ED_object_parent_set(ReportList *reports, cu->flag |= CU_PATH | CU_FOLLOW; cu_eval->flag |= CU_PATH | CU_FOLLOW; /* force creation of path data */ - BKE_displist_make_curveTypes(depsgraph, scene, par, false, false, NULL); + BKE_displist_make_curveTypes(depsgraph, scene, par, false, false); } else { cu->flag |= CU_FOLLOW; diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 8836d913475..00f5dffb3cc 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1335,6 +1335,11 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) BKE_object_batch_cache_dirty_tag(tob); DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); } + /* special support for dupligroups */ + else if (tob->instance_collection && tob->instance_collection->id.tag & LIB_TAG_DOIT) { + DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM); + DEG_id_tag_update(&tob->instance_collection->id, ID_RECALC_COPY_ON_WRITE); + } } if (tot_change) { diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 342c6269419..20229b63258 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -114,7 +114,6 @@ typedef struct OGLRender { GPUOffScreen *ofs; int ofs_samples; - bool ofs_full_samples; int sizex, sizey; int write_still; @@ -356,9 +355,6 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R ImBuf *ibuf_view; const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL; - unsigned int draw_flags = V3D_OFSDRAW_NONE; - draw_flags |= (oglrender->ofs_full_samples) ? V3D_OFSDRAW_USE_FULL_SAMPLE : 0; - if (view_context) { ibuf_view = ED_view3d_draw_offscreen_imbuf(depsgraph, scene, @@ -368,7 +364,6 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R sizex, sizey, IB_rectfloat, - draw_flags, alpha_mode, oglrender->ofs_samples, viewname, @@ -381,7 +376,6 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R } } else { - draw_flags |= V3D_OFSDRAW_SHOW_ANNOTATION; ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(depsgraph, scene, NULL, @@ -390,7 +384,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R oglrender->sizex, oglrender->sizey, IB_rectfloat, - draw_flags, + V3D_OFSDRAW_SHOW_ANNOTATION, alpha_mode, oglrender->ofs_samples, viewname, @@ -532,6 +526,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) const bool is_animation = RNA_boolean_get(op->ptr, "animation"); const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer"); const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); + const int samples = U.ogl_multisamples; char err_out[256] = "unknown"; if (G.background) { @@ -576,7 +571,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) /* corrects render size with actual size, not every card supports non-power-of-two dimensions */ DRW_opengl_context_enable(); /* Offscreen creation needs to be done in DRW context. */ - ofs = GPU_offscreen_create(sizex, sizey, 0, true, true, err_out); + ofs = GPU_offscreen_create(sizex, sizey, samples, true, true, err_out); DRW_opengl_context_disable(); if (!ofs) { @@ -597,6 +592,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) oglrender->view_layer = CTX_data_view_layer(C); oglrender->depsgraph = CTX_data_depsgraph(C); oglrender->cfrao = scene->r.cfra; + oglrender->ofs_samples = samples; oglrender->write_still = is_write_still && !is_animation; oglrender->is_animation = is_animation; diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 8819b7a541d..f7a1d7187f1 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -595,7 +595,7 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op)) id_us_min(&ma->id); RNA_id_pointer_create(&ma->id, &idptr); - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } @@ -644,7 +644,7 @@ static int new_texture_exec(bContext *C, wmOperator *UNUSED(op)) id_us_min(&tex->id); RNA_id_pointer_create(&tex->id, &idptr); - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } @@ -695,7 +695,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op)) id_us_min(&wo->id); RNA_id_pointer_create(&wo->id, &idptr); - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index c2f9beb5d78..83058f2bc95 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1612,9 +1612,9 @@ static void ed_default_handlers( keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0); WM_event_add_keymap_handler_poll(handlers, keymap, event_in_markers_region); - /* time-scrubbing */ - keymap = WM_keymap_ensure(wm->defaultconf, "Scrubbing", 0, 0); - WM_event_add_keymap_handler_poll(handlers, keymap, ED_event_in_scrubbing_region); + /* time-scrub */ + keymap = WM_keymap_ensure(wm->defaultconf, "Time Scrub", 0, 0); + WM_event_add_keymap_handler_poll(handlers, keymap, ED_time_scrub_event_in_region); /* frame changing and timeline operators (for time spaces) */ keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0); @@ -2292,7 +2292,7 @@ static void ed_panel_draw(const bContext *C, } } - UI_panel_end(block, w, h); + UI_panel_end(block, w, h, open); } /** diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index c60469e092f..6a5df8a3776 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -69,15 +69,10 @@ const char *screen_context_dir[] = { "scene", "view_layer", "visible_objects", - "visible_bases", "selectable_objects", - "selectable_bases", "selected_objects", - "selected_bases", "editable_objects", - "editable_bases", "selected_editable_objects", - "selected_editable_bases", "objects_in_mode", "objects_in_mode_unique_data", "visible_bones", @@ -89,7 +84,6 @@ const char *screen_context_dir[] = { "selected_pose_bones_from_active_object", "active_bone", "active_pose_bone", - "active_base", "active_object", "object", "edit_object", @@ -179,52 +173,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); return 1; } - else if (CTX_data_equals(member, "visible_bases")) { - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (BASE_VISIBLE(v3d, base)) { - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selectable_bases")) { - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (BASE_SELECTABLE(v3d, base)) { - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selected_bases")) { - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (BASE_SELECTED(v3d, base)) { - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "selected_editable_bases")) { - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (BASE_SELECTED_EDITABLE(v3d, base)) { - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } - else if (CTX_data_equals(member, "editable_bases")) { - /* Visible + Editable, but not necessarily selected */ - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (BASE_EDITABLE(v3d, base)) { - CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base); - } - } - CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); - return 1; - } else if (CTX_data_equals(member, "objects_in_mode")) { if (obact && (obact->mode != OB_MODE_OBJECT)) { FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) { @@ -455,13 +403,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult return 1; } } - else if (CTX_data_equals(member, "active_base")) { - if (view_layer->basact) { - CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact); - } - - return 1; - } else if (CTX_data_equals(member, "active_object")) { if (obact) { CTX_data_id_pointer_set(result, &obact->id); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 07a87982890..3a90532aa56 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -675,6 +675,12 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) bool do_draw = false; for (ar = area_iter->regionbase.first; ar; ar = ar->next) { + + /* call old area's deactivate if assigned */ + if (ar == old_ar && area_iter->type->deactivate) { + area_iter->type->deactivate(area_iter); + } + if (ar == old_ar || ar == scr->active_region) { do_draw = true; } diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c index 0ec989db12b..08b9d010f79 100644 --- a/source/blender/editors/screen/screen_user_menu.c +++ b/source/blender/editors/screen/screen_user_menu.c @@ -194,6 +194,10 @@ void ED_screen_user_menu_item_remove(ListBase *lb, bUserMenuItem *umi) static void screen_user_menu_draw(const bContext *C, Menu *menu) { + /* Enable when we have the ability to edit menus. */ + const bool show_missing = false; + char label[512]; + uint um_array_len; bUserMenu **um_array = ED_screen_user_menus_find(C, &um_array_len); bool is_empty = true; @@ -206,15 +210,32 @@ static void screen_user_menu_draw(const bContext *C, Menu *menu) const char *ui_name = umi->ui_name[0] ? umi->ui_name : NULL; if (umi->type == USER_MENU_TYPE_OPERATOR) { bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi; - IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL; - uiItemFullO( - menu->layout, umi_op->op_idname, ui_name, ICON_NONE, prop, umi_op->opcontext, 0, NULL); - is_empty = false; + wmOperatorType *ot = WM_operatortype_find(umi_op->op_idname, false); + if (ot != NULL) { + IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL; + uiItemFullO_ptr(menu->layout, ot, ui_name, ICON_NONE, prop, umi_op->opcontext, 0, NULL); + is_empty = false; + } + else { + if (show_missing) { + SNPRINTF(label, "Missing: %s", umi_op->op_idname); + uiItemL(menu->layout, label, ICON_NONE); + } + } } else if (umi->type == USER_MENU_TYPE_MENU) { bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi; - uiItemM(menu->layout, umi_mt->mt_idname, ui_name, ICON_NONE); - is_empty = false; + MenuType *mt = WM_menutype_find(umi_mt->mt_idname, false); + if (mt != NULL) { + uiItemM_ptr(menu->layout, mt, ui_name, ICON_NONE); + is_empty = false; + } + else { + if (show_missing) { + SNPRINTF(label, "Missing: %s", umi_mt->mt_idname); + uiItemL(menu->layout, label, ICON_NONE); + } + } } else if (umi->type == USER_MENU_TYPE_PROP) { bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi; @@ -252,9 +273,10 @@ static void screen_user_menu_draw(const bContext *C, Menu *menu) } } if (!ok) { - char label[512]; - SNPRINTF(label, "Missing: %s.%s", umi_pr->context_data_path, umi_pr->prop_id); - uiItemL(menu->layout, label, ICON_NONE); + if (show_missing) { + SNPRINTF(label, "Missing: %s.%s", umi_pr->context_data_path, umi_pr->prop_id); + uiItemL(menu->layout, label, ICON_NONE); + } } } else if (umi->type == USER_MENU_TYPE_SEP) { diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index d7553d18d3b..303c3fac363 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -6188,7 +6188,6 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) w, h, IB_rect, - V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL, diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 84b4a130183..c8ad1b5781d 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -71,6 +71,7 @@ #include "BLI_sys_types.h" #include "ED_mesh.h" /* for face mask functions */ +#include "ED_select_buffer_utils.h" #include "WM_api.h" #include "WM_types.h" @@ -390,7 +391,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]); + *r_index = ED_select_buffer_sample_point(mval); if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) { return 0; 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 c904bf2005b..b6a6c897606 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -695,7 +695,7 @@ static void gradientVertInit__mapFunc(void *userData, static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmGesture *gesture = op->customdata; - WPGradient_vertStoreBase *vert_cache = gesture->userdata; + WPGradient_vertStoreBase *vert_cache = gesture->user_data.data; int ret = WM_gesture_straightline_modal(C, op, event); if (ret & OPERATOR_RUNNING_MODAL) { @@ -751,15 +751,15 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) WPGradient_userData data = {NULL}; if (is_interactive) { - if (gesture->userdata == NULL) { - gesture->userdata = MEM_mallocN(sizeof(WPGradient_vertStoreBase) + - (sizeof(WPGradient_vertStore) * me->totvert), - __func__); - gesture->userdata_free = false; + if (gesture->user_data.data == NULL) { + gesture->user_data.data = MEM_mallocN(sizeof(WPGradient_vertStoreBase) + + (sizeof(WPGradient_vertStore) * me->totvert), + __func__); + gesture->user_data.use_free = false; data.is_init = true; wpaint_prev_create( - &((WPGradient_vertStoreBase *)gesture->userdata)->wpp, me->dvert, me->totvert); + &((WPGradient_vertStoreBase *)gesture->user_data.data)->wpp, me->dvert, me->totvert); /* on init only, convert face -> vert sel */ if (me->editflag & ME_EDIT_PAINT_FACE_SEL) { @@ -767,7 +767,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) } } - vert_cache = gesture->userdata; + vert_cache = gesture->user_data.data; } else { if (ED_wpaint_ensure_data(C, op->reports, 0, NULL) == false) { diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 692681cecb7..381173999c4 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -136,7 +136,7 @@ static int sound_open_exec(bContext *C, wmOperator *op) id_us_min(&sound->id); RNA_id_pointer_create(&sound->id, &idptr); - RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL); RNA_property_update(C, &pprop->ptr, pprop->prop); } diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index d3e5c011579..bc7f8a0f79d 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -155,7 +155,7 @@ static void actedit_change_action(bContext *C, bAction *act) RNA_id_pointer_create((ID *)act, &idptr); /* set the new pointer, and force a refresh */ - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } @@ -261,7 +261,7 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op)) * NOTE: we can't use actedit_change_action, as this function is also called from the NLA */ RNA_id_pointer_create(&action->id, &idptr); - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } @@ -619,7 +619,7 @@ void ED_animedit_unlink_action( prop = RNA_struct_find_property(&ptr, "action"); /* clear... */ - RNA_property_pointer_set(NULL, &ptr, prop, PointerRNA_NULL); + RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL, NULL); RNA_property_update(C, &ptr, prop); } } diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 972f19bb643..3c879b03126 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -237,7 +237,7 @@ static void action_main_region_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* scrubbing region */ - ED_scrubbing_draw(ar, scene, saction->flag & SACTION_DRAWTIME, true); + ED_time_scrub_draw(ar, scene, saction->flag & SACTION_DRAWTIME, true); /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); @@ -281,7 +281,7 @@ static void action_channel_region_draw(const bContext *C, ARegion *ar) } /* channel filter next to scrubbing area */ - ED_channel_search_draw(C, ar, ac.ads); + ED_time_scrub_channel_search_draw(C, ar, ac.ads); /* reset view matrix */ UI_view2d_view_restore(C); diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index c985d61a8b8..2496b16ffae 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -808,12 +808,13 @@ void uiTemplateMovieclipInformation(uiLayout *layout, user = userptr->data; col = uiLayoutColumn(layout, false); + uiLayoutSetAlignment(col, UI_LAYOUT_ALIGN_RIGHT); ibuf = BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, MOVIECLIP_CACHE_SKIP); /* Display frame dimensions, channels number and byffer type. */ BKE_movieclip_get_size(clip, user, &width, &height); - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Size %d x %d"), width, height); + ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("%d x %d"), width, height); if (ibuf) { if (ibuf->rect_float) { diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 081515ca4bc..7683823a79f 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 (-UI_SCRUBBING_MARGIN_Y - CHANNEL_HEIGHT_HALF - CHANNEL_SKIP) +#define CHANNEL_FIRST (-UI_TIME_SCRUB_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 e5698ede59a..710a46fdd51 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -245,7 +245,7 @@ static int open_exec(bContext *C, wmOperator *op) id_us_min(&clip->id); RNA_id_pointer_create(&clip->id, &idptr); - RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL); RNA_property_update(C, &pprop->ptr, pprop->prop); } else if (sc) { diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 13d190e6861..4df435270ce 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -926,7 +926,8 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar) ScrArea *sa = CTX_wm_area(C); int mask_width, mask_height; ED_mask_get_size(sa, &mask_width, &mask_height); - ED_mask_draw_region(mask, + ED_mask_draw_region(CTX_data_depsgraph(C), + mask, ar, sc->mask_info.draw_flag, sc->mask_info.draw_type, @@ -1006,8 +1007,8 @@ static void clip_preview_region_init(wmWindowManager *wm, ARegion *ar) 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 Time Scrub", SPACE_CLIP, RGN_TYPE_PREVIEW); + WM_event_add_keymap_handler_poll(&ar->handlers, keymap, ED_time_scrub_event_in_region); keymap = WM_keymap_ensure(wm->defaultconf, "Clip Graph Editor", SPACE_CLIP, 0); WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap); @@ -1047,7 +1048,7 @@ static void graph_region_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* time-scrubbing */ - ED_scrubbing_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true); + ED_time_scrub_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true); /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); @@ -1061,7 +1062,7 @@ static void graph_region_draw(const bContext *C, ARegion *ar) 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, - UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y); + UI_DPI_FAC * ar->sizey - UI_TIME_SCRUB_MARGIN_Y); UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_TEXT); } } @@ -1101,7 +1102,7 @@ static void dopesheet_region_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* time-scrubbing */ - ED_scrubbing_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true); + ED_time_scrub_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true); /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); @@ -1371,7 +1372,7 @@ void ED_spacetype_clip(void) /* regions: properties */ art = MEM_callocN(sizeof(ARegionType), "spacetype clip region properties"); art->regionid = RGN_TYPE_UI; - art->prefsizex = UI_COMPACT_PANEL_WIDTH; + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI; art->init = clip_properties_region_init; art->draw = clip_properties_region_draw; @@ -1382,7 +1383,7 @@ void ED_spacetype_clip(void) /* regions: tools */ art = MEM_callocN(sizeof(ARegionType), "spacetype clip region tools"); art->regionid = RGN_TYPE_TOOLS; - art->prefsizex = UI_COMPACT_PANEL_WIDTH; + art->prefsizex = UI_SIDEBAR_PANEL_WIDTH; art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI; art->listener = clip_props_region_listener; art->init = clip_tools_region_init; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index b51baafbcf5..0425d6da3d8 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1466,6 +1466,7 @@ static int join_tracks_exec(bContext *C, wmOperator *op) } BLI_gset_free(point_tracks, NULL); + DEG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); @@ -1625,6 +1626,7 @@ static int track_copy_color_exec(bContext *C, wmOperator *UNUSED(op)) } } + DEG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); return OPERATOR_FINISHED; @@ -1806,6 +1808,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op) } } + DEG_id_tag_update(&clip->id, 0); BKE_tracking_dopesheet_tag_update(tracking); WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 8329218eea9..b68efdc0ea0 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_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_keyframing.h" @@ -282,10 +283,18 @@ static int graphkeys_viewall(bContext *C, do_sel_only, include_handles); + /* Give some more space at the borders. */ BLI_rctf_scale(&cur_new, 1.1f); - UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx); + /* Take regions into account, that could block the view. */ + float pad_top = UI_TIME_SCRUB_MARGIN_Y; + float pad_bottom = 0; + if (!BLI_listbase_is_empty(ED_context_get_markers(C))) { + pad_bottom = UI_MARKER_MARGIN_Y; + } + BLI_rctf_pad_y(&cur_new, ac.ar->sizey * UI_DPI_FAC, pad_bottom, pad_top); + UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 4e131c653f8..6c5ebf77bf4 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -314,7 +314,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* time-scrubbing */ - ED_scrubbing_draw(ar, scene, display_seconds, false); + ED_time_scrub_draw(ar, scene, display_seconds, false); /* scrollers */ // FIXME: args for scrollers depend on the type of data being shown... @@ -329,7 +329,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, - UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y); + UI_DPI_FAC * ar->sizey - UI_TIME_SCRUB_MARGIN_Y); UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_SCROLL_TEXT); } } @@ -376,7 +376,7 @@ static void graph_channel_region_draw(const bContext *C, ARegion *ar) } /* channel filter next to scrubbing area */ - ED_channel_search_draw(C, ar, ac.ads); + ED_time_scrub_channel_search_draw(C, ar, ac.ads); /* reset view matrix */ UI_view2d_view_restore(C); diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 68af854e367..26512cb232d 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -42,6 +42,7 @@ #include "RE_pipeline.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -62,81 +63,6 @@ #define B_NOP -1 #define MAX_IMAGE_INFO_LEN 128 -/* proto */ - -static void image_info( - Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str, size_t len) -{ - size_t ofs = 0; - - str[0] = 0; - if (ima == NULL) { - return; - } - - if (ibuf == NULL) { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Can't Load Image"), len - ofs); - } - else { - if (ima->source == IMA_SRC_MOVIE) { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs); - if (BKE_image_has_anim(ima)) { - ofs += BLI_snprintf( - str + ofs, - len - ofs, - IFACE_(" %d frs"), - IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN)); - } - } - else { - ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs); - } - - ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(": size %d x %d,"), ibuf->x, ibuf->y); - - if (ibuf->rect_float) { - if (ibuf->channels != 4) { - ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels); - } - else if (ibuf->planes == R_IMF_PLANES_RGBA) { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs); - } - else { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs); - } - } - else { - if (ibuf->planes == R_IMF_PLANES_RGBA) { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs); - } - else { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs); - } - } - if (ibuf->zbuf || ibuf->zbuf_float) { - ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs); - } - - if (ima->source == IMA_SRC_SEQUENCE) { - const char *file = BLI_last_slash(ibuf->name); - if (file == NULL) { - file = ibuf->name; - } - else { - file++; - } - ofs += BLI_snprintf(str + ofs, len - ofs, ", %s", file); - } - } - - /* the frame number, even if we cant */ - if (ima->source == IMA_SRC_SEQUENCE) { - /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */ - const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL); - ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(", Frame: %d"), framenr); - } -} - /* gets active viewer user */ struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree) { @@ -822,6 +748,22 @@ static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg)) RNA_property_update(C, &cb->ptr, cb->prop); } +static bool image_has_alpha(Image *ima, ImageUser *iuser) +{ + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); + if (ibuf == NULL) { + return false; + } + + int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions); + char valid_channels = BKE_imtype_valid_channels(imtype, false); + bool has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0; + + BKE_image_release_ibuf(ima, ibuf, NULL); + + return has_alpha; +} + void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, @@ -830,24 +772,11 @@ void uiTemplateImage(uiLayout *layout, bool compact, bool multiview) { - PropertyRNA *prop; - PointerRNA imaptr; - RNAUpdateCb *cb; - Image *ima; - ImageUser *iuser; - Scene *scene = CTX_data_scene(C); - SpaceImage *space_image = CTX_wm_space_image(C); - uiLayout *row, *split, *col; - uiBlock *block; - char str[MAX_IMAGE_INFO_LEN]; - - void *lock; - if (!ptr->data) { return; } - prop = RNA_struct_find_property(ptr, propname); + PropertyRNA *prop = RNA_struct_find_property(ptr, propname); if (!prop) { printf( "%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname); @@ -862,22 +791,19 @@ void uiTemplateImage(uiLayout *layout, return; } - block = uiLayoutGetBlock(layout); + uiBlock *block = uiLayoutGetBlock(layout); - imaptr = RNA_property_pointer_get(ptr, prop); - ima = imaptr.data; - iuser = userptr->data; + PointerRNA imaptr = RNA_property_pointer_get(ptr, prop); + Image *ima = imaptr.data; + ImageUser *iuser = userptr->data; + Scene *scene = CTX_data_scene(C); BKE_image_user_frame_calc(iuser, (int)scene->r.cfra); - cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); - cb->ptr = *ptr; - cb->prop = prop; - cb->iuser = iuser; - uiLayoutSetContextPointer(layout, "edit_image", &imaptr); uiLayoutSetContextPointer(layout, "edit_image_user", userptr); + SpaceImage *space_image = CTX_wm_space_image(C); if (!compact && (space_image == NULL || iuser != &space_image->iuser)) { uiTemplateID(layout, C, @@ -888,164 +814,178 @@ void uiTemplateImage(uiLayout *layout, NULL, UI_TEMPLATE_ID_FILTER_ALL, false); + + if (ima != NULL) { + uiItemS(layout); + } } - if (ima) { - UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL); + if (ima == NULL) { + return; + } - if (ima->source == IMA_SRC_VIEWER) { - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); - image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN); - BKE_image_release_ibuf(ima, ibuf, lock); + if (ima->source == IMA_SRC_VIEWER) { + /* Viewer images. */ + uiTemplateImageInfo(layout, C, ima, iuser); - uiItemL(layout, ima->id.name + 2, ICON_NONE); - uiItemL(layout, str, ICON_NONE); + if (ima->type == IMA_TYPE_COMPOSITE) { + } + else if (ima->type == IMA_TYPE_R_RESULT) { + /* browse layer/passes */ + RenderResult *rr; + const float dpi_fac = UI_DPI_FAC; + const int menus_width = 230 * dpi_fac; + + /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */ + rr = BKE_image_acquire_renderresult(scene, ima); + uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot); + BKE_image_release_renderresult(scene, ima); + } - if (ima->type == IMA_TYPE_COMPOSITE) { - } - else if (ima->type == IMA_TYPE_R_RESULT) { - /* browse layer/passes */ - RenderResult *rr; - const float dpi_fac = UI_DPI_FAC; - const int menus_width = 230 * dpi_fac; - - /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */ - rr = BKE_image_acquire_renderresult(scene, ima); - uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot); - BKE_image_release_renderresult(scene, ima); - } + return; + } + + /* Set custom callback for property updates. */ + RNAUpdateCb *cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); + cb->ptr = *ptr; + cb->prop = prop; + cb->iuser = iuser; + UI_block_funcN_set(block, rna_update_cb, cb, NULL); + + /* Disable editing if image was modified, to avoid losing changes. */ + const bool is_dirty = BKE_image_is_dirty(ima); + if (is_dirty) { + uiLayout *row = uiLayoutRow(layout, true); + uiItemO(row, IFACE_("Save"), ICON_NONE, "image.save"); + uiItemO(row, IFACE_("Discard"), ICON_NONE, "image.reload"); + uiItemS(layout); + } + + layout = uiLayoutColumn(layout, false); + uiLayoutSetEnabled(layout, !is_dirty); + uiLayoutSetPropDecorate(layout, false); + + /* Image source */ + { + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetPropSep(col, true); + uiItemR(col, &imaptr, "source", 0, NULL, ICON_NONE); + } + + /* Filepath */ + const bool is_packed = BKE_image_has_packedfile(ima); + const bool no_filepath = is_packed && !BKE_image_has_filepath(ima); + + if ((ima->source != IMA_SRC_GENERATED) && !no_filepath) { + uiItemS(layout); + + uiLayout *row = uiLayoutRow(layout, true); + if (is_packed) { + uiItemO(row, "", ICON_PACKAGE, "image.unpack"); } else { - /* Disable editing if image was modified, to avoid losing changes. */ - const bool is_dirty = BKE_image_is_dirty(ima); - if (is_dirty) { - row = uiLayoutRow(layout, true); - uiItemO(row, IFACE_("Save"), ICON_NONE, "image.save"); - uiItemO(row, IFACE_("Discard Changes"), ICON_NONE, "image.reload"); - uiItemS(layout); - } + uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack"); + } - layout = uiLayoutColumn(layout, false); - uiLayoutSetEnabled(layout, !is_dirty); + row = uiLayoutRow(row, true); + uiLayoutSetEnabled(row, is_packed == false); + uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE); + uiItemO(row, "", ICON_FILE_REFRESH, "image.reload"); + } - /* Image source */ - uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE); + /* Image layers and Info */ + if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) { + uiItemS(layout); - /* Filepath */ - const bool is_packed = BKE_image_has_packedfile(ima); - const bool no_filepath = is_packed && !BKE_image_has_filepath(ima); + const float dpi_fac = UI_DPI_FAC; + uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL); + } + else if (ima->source == IMA_SRC_GENERATED) { + uiItemS(layout); - if ((ima->source != IMA_SRC_GENERATED) && !no_filepath) { - row = uiLayoutRow(layout, true); - if (is_packed) { - uiItemO(row, "", ICON_PACKAGE, "image.unpack"); - } - else { - uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack"); - } + /* Generated */ + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetPropSep(col, true); - row = uiLayoutRow(row, true); - uiLayoutSetEnabled(row, is_packed == false); - uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE); - uiItemO(row, "", ICON_FILE_REFRESH, "image.reload"); - } + uiLayout *sub = uiLayoutColumn(col, true); + uiItemR(sub, &imaptr, "generated_width", 0, "X", ICON_NONE); + uiItemR(sub, &imaptr, "generated_height", 0, "Y", ICON_NONE); - /* Image layers and Info */ - if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) { - const float dpi_fac = UI_DPI_FAC; - uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL); - } - else if (ima->source != IMA_SRC_GENERATED) { - if (compact == 0) { - uiTemplateImageInfo(layout, C, ima, iuser); - } - } + uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE); - uiItemS(layout); + uiItemS(col); - col = uiLayoutColumn(layout, false); - uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings"); - uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE); + uiItemR(col, &imaptr, "generated_type", UI_ITEM_R_EXPAND, IFACE_("Type"), ICON_NONE); + if (ima->gen_type == IMA_GENTYPE_BLANK) { + uiItemR(col, &imaptr, "generated_color", 0, NULL, ICON_NONE); + } + } + else if (compact == 0) { + uiTemplateImageInfo(layout, C, ima, iuser); + } - uiItemS(layout); + if (BKE_image_is_animated(ima)) { + /* Animation */ + uiItemS(layout); - if (ima->source != IMA_SRC_GENERATED) { - if (compact == 0) { /* background image view doesn't need these */ - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - bool has_alpha = true; - - if (ibuf) { - int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions); - char valid_channels = BKE_imtype_valid_channels(imtype, false); - - has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0; - - BKE_image_release_ibuf(ima, ibuf, NULL); - } - - if (multiview) { - if ((scene->r.scemode & R_MULTIVIEW) != 0) { - uiItemR(layout, &imaptr, "use_multiview", 0, NULL, ICON_NONE); - - if (RNA_boolean_get(&imaptr, "use_multiview")) { - uiTemplateImageViews(layout, &imaptr); - } - } - } - - if (has_alpha) { - col = uiLayoutColumn(layout, false); - uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE); - row = uiLayoutRow(col, false); - uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_alpha")); - uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE); - } - - if (ima->source == IMA_SRC_MOVIE) { - col = uiLayoutColumn(layout, false); - uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE); - } - } - } + uiLayout *col = uiLayoutColumn(layout, true); + uiLayoutSetPropSep(col, true); + + uiLayout *sub = uiLayoutColumn(col, true); + uiLayout *row = uiLayoutRow(sub, true); + uiItemR(row, userptr, "frame_duration", 0, IFACE_("Frames"), ICON_NONE); + uiItemO(row, "", ICON_FILE_REFRESH, "IMAGE_OT_match_movie_length"); + + uiItemR(sub, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE); + uiItemR(sub, userptr, "frame_offset", 0, NULL, ICON_NONE); - if (BKE_image_is_animated(ima)) { - uiItemS(layout); + uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE); + uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE); - split = uiLayoutSplit(layout, 0.0f, false); + if (ima->source == IMA_SRC_MOVIE && compact == 0) { + uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE); + } + } - col = uiLayoutColumn(split, false); + /* Multiview */ + if (multiview && compact == 0) { + if ((scene->r.scemode & R_MULTIVIEW) != 0) { + uiItemS(layout); - BLI_snprintf(str, sizeof(str), IFACE_("(%d) Frames"), iuser->framenr); - uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE); - uiItemR(col, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE); - uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE); + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetPropSep(col, true); + uiItemR(col, &imaptr, "use_multiview", 0, NULL, ICON_NONE); - col = uiLayoutColumn(split, false); - uiItemO(col, NULL, ICON_NONE, "IMAGE_OT_match_movie_length"); - uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE); - uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE); + if (RNA_boolean_get(&imaptr, "use_multiview")) { + uiTemplateImageViews(layout, &imaptr); } - else if (ima->source == IMA_SRC_GENERATED) { - split = uiLayoutSplit(layout, 0.0f, false); + } + } - col = uiLayoutColumn(split, true); - uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE); - uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE); + /* Colorspace and alpha */ + { + uiItemS(layout); - uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE); + uiLayout *col = uiLayoutColumn(layout, false); + uiLayoutSetPropSep(col, true); + uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings"); - uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + if (compact == 0) { + if (ima->source != IMA_SRC_GENERATED) { + if (image_has_alpha(ima, iuser)) { + uiLayout *sub = uiLayoutColumn(col, false); + uiItemR(sub, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE); - if (ima->gen_type == IMA_GENTYPE_BLANK) { - uiItemR(layout, &imaptr, "generated_color", 0, NULL, ICON_NONE); + bool is_data = IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name); + uiLayoutSetActive(sub, !is_data); } } - } - UI_block_funcN_set(block, NULL, NULL, NULL); + uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE); + } } - MEM_freeN(cb); + UI_block_funcN_set(block, NULL, NULL, NULL); } void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_management) @@ -1215,25 +1155,24 @@ void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA { ImageFormatData *imf = imfptr->data; - if (ptr == NULL) { - return; + if (ptr != NULL) { + uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE); + if (!RNA_boolean_get(ptr, "use_multiview")) { + return; + } } - uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE); - - if (RNA_boolean_get(ptr, "use_multiview")) { - if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) { - PropertyRNA *prop; - PointerRNA stereo3d_format_ptr; + if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) { + PropertyRNA *prop; + PointerRNA stereo3d_format_ptr; - prop = RNA_struct_find_property(imfptr, "stereo_3d_format"); - stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop); + prop = RNA_struct_find_property(imfptr, "stereo_3d_format"); + stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop); - uiTemplateViewsFormat(layout, imfptr, &stereo3d_format_ptr); - } - else { - uiTemplateViewsFormat(layout, imfptr, NULL); - } + uiTemplateViewsFormat(layout, imfptr, &stereo3d_format_ptr); + } + else { + uiTemplateViewsFormat(layout, imfptr, NULL); } } @@ -1258,21 +1197,87 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser) { - Scene *scene = CTX_data_scene(C); - ImBuf *ibuf; - char str[MAX_IMAGE_INFO_LEN]; + if (ima == NULL || iuser == NULL) { + return; + } + + /* Acquire image buffer. */ void *lock; + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); - if (!ima || !iuser) { - return; + uiLayout *col = uiLayoutColumn(layout, true); + uiLayoutSetAlignment(col, UI_LAYOUT_ALIGN_RIGHT); + + if (ibuf == NULL) { + uiItemL(col, IFACE_("Can't Load Image"), ICON_NONE); } + else { + char str[MAX_IMAGE_INFO_LEN] = {0}; + const int len = MAX_IMAGE_INFO_LEN; + int ofs = 0; - ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); + ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d x %d, "), ibuf->x, ibuf->y); + + if (ibuf->rect_float) { + if (ibuf->channels != 4) { + ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels); + } + else if (ibuf->planes == R_IMF_PLANES_RGBA) { + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs); + } + else { + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs); + } + } + else { + if (ibuf->planes == R_IMF_PLANES_RGBA) { + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs); + } + else { + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs); + } + } + if (ibuf->zbuf || ibuf->zbuf_float) { + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs); + } + + uiItemL(col, str, ICON_NONE); + } + + /* Frame number, even if we can't load the image. */ + if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { + /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */ + Scene *scene = CTX_data_scene(C); + const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL); + char str[MAX_IMAGE_INFO_LEN]; + int duration = 0; + + if (ima->source == IMA_SRC_MOVIE && BKE_image_has_anim(ima)) { + struct anim *anim = ((ImageAnim *)ima->anims.first)->anim; + if (anim) { + duration = IMB_anim_get_duration(anim, IMB_TC_RECORD_RUN); + } + } + + if (duration > 0) { + /* Movie duration */ + BLI_snprintf(str, MAX_IMAGE_INFO_LEN, IFACE_("Frame %d / %d"), framenr, duration); + } + else if (ima->source == IMA_SRC_SEQUENCE && ibuf) { + /* Image sequence frame number + filename */ + const char *filename = BLI_last_slash(ibuf->name); + filename = (filename == NULL) ? ibuf->name : filename + 1; + BLI_snprintf(str, MAX_IMAGE_INFO_LEN, IFACE_("Frame %d: %s"), framenr, filename); + } + else { + /* Frame number */ + BLI_snprintf(str, MAX_IMAGE_INFO_LEN, IFACE_("Frame %d"), framenr); + } + + uiItemL(col, str, ICON_NONE); + } - BKE_image_user_frame_calc(iuser, (int)scene->r.cfra); - image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN); BKE_image_release_ibuf(ima, ibuf, lock); - uiItemL(layout, str, ICON_NONE); } #undef MAX_IMAGE_INFO_LEN @@ -1304,6 +1309,7 @@ void image_buttons_register(ARegionType *art) strcpy(pt->label, N_("Metadata")); strcpy(pt->category, "Image"); strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->order = 10; pt->poll = metadata_panel_context_poll; pt->draw = metadata_panel_context_draw; pt->flag |= PNL_DEFAULT_CLOSED; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 07c2d216a93..8121c577706 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1320,7 +1320,7 @@ static int image_open_exec(bContext *C, wmOperator *op) PointerRNA imaptr; RNA_id_pointer_create(&ima->id, &imaptr); - RNA_property_pointer_set(NULL, &iod->pprop.ptr, iod->pprop.prop, imaptr); + RNA_property_pointer_set(&iod->pprop.ptr, iod->pprop.prop, imaptr, NULL); RNA_property_update(C, &iod->pprop.ptr, iod->pprop.prop); } @@ -1869,8 +1869,7 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS Scene *scene = CTX_data_scene(C); ImageSaveOptions opts; PropertyRNA *prop; - const bool save_as_render = ((ima->source == IMA_SRC_VIEWER) || - (ima->flag & IMA_VIEW_AS_RENDER)); + const bool save_as_render = (ima->source == IMA_SRC_VIEWER); if (RNA_struct_property_is_set(op->ptr, "filepath")) { return image_save_as_exec(C, op); @@ -2474,7 +2473,7 @@ static int image_new_exec(bContext *C, wmOperator *op) PointerRNA imaptr; RNA_id_pointer_create(&ima->id, &imaptr); - RNA_property_pointer_set(NULL, &data->pprop.ptr, data->pprop.prop, imaptr); + RNA_property_pointer_set(&data->pprop.ptr, data->pprop.prop, imaptr, NULL); RNA_property_update(C, &data->pprop.ptr, data->pprop.prop); } else if (sima) { diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index a8be93ad213..73baf1540f7 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -658,7 +658,8 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) BLI_thread_unlock(LOCK_DRAW_IMAGE); } - ED_mask_draw_region(mask, + ED_mask_draw_region(depsgraph, + mask, ar, sima->mask_info.draw_flag, sima->mask_info.draw_type, diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index 4b7dfe5d653..3bdd2804efc 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -205,7 +205,7 @@ static void nla_channel_region_draw(const bContext *C, ARegion *ar) } /* channel filter next to scrubbing area */ - ED_channel_search_draw(C, ar, ac.ads); + ED_time_scrub_channel_search_draw(C, ar, ac.ads); /* reset view matrix */ UI_view2d_view_restore(C); @@ -290,7 +290,7 @@ 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); + ED_time_scrub_draw(ar, scene, snla->flag & SNLA_DRAWTIME, true); /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index bf6ec961a5d..e39e024e44a 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -713,6 +713,11 @@ static void node_buts_image_user(uiLayout *layout, 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); + + /* Avoid losing changes image is painted. */ + if (BKE_image_is_dirty(imaptr->data)) { + uiLayoutSetEnabled(split, false); + } } static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index e677c649fb4..01a30f677a3 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -521,7 +521,7 @@ static int new_node_tree_exec(bContext *C, wmOperator *op) id_us_min(&ntree->id); RNA_id_pointer_create(&ntree->id, &idptr); - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } else if (snode) { diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index a8331c26ce6..aab328249fe 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -495,17 +495,7 @@ static int node_mouse_select(bContext *C, } } - /* In case we do two-steps selection, we do not want to select the node if some valid socket - * is below the mouse, as that would prevent draging from sockets (NODE_OT_link) - * to be properly triggered. See T64660. */ - if (wait_to_deselect_others) { - if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN) || - node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) { - ret_value = OPERATOR_CANCELLED; - } - } - - if (sock == NULL) { + if (!sock) { /* find the closest visible node */ node = node_under_mouse_select(snode->edittree, (int)cursor[0], (int)cursor[1]); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 6a7795393c9..aed7af3911f 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -2802,7 +2802,11 @@ static void outliner_draw_tree_element(bContext *C, BKE_view_layer_base_find(view_layer, ob); const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0); - if (ob == obact || is_selected) { + if (ob == obact) { + active = OL_DRAWSEL_ACTIVE; + } + + if (is_selected) { if (ob == obact) { /* active selected object */ UI_GetThemeColor3ubv(TH_ACTIVE_OBJECT, text_color); diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 90180c4ea47..c32b2b051f8 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -88,6 +88,11 @@ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { + /* stop highlighting if out of area */ + if (!ED_screen_area_active(C)) { + return OPERATOR_PASS_THROUGH; + } + /* Drag and drop does own highlighting. */ wmWindowManager *wm = CTX_wm_manager(C); if (wm->drags.first) { diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index c6fcf1d8cf7..bee615108f9 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -450,32 +450,6 @@ static eOLDrawState tree_element_active_material(bContext *C, return OL_DRAWSEL_NONE; } -static eOLDrawState tree_element_active_light(bContext *UNUSED(C), - Scene *UNUSED(scene), - ViewLayer *view_layer, - SpaceOutliner *soops, - TreeElement *te, - const eOLSetState set) -{ - Object *ob; - - /* we search for the object parent */ - ob = (Object *)outliner_search_back(soops, te, ID_OB); - if (ob == NULL || ob != OBACT(view_layer)) { - /* just paranoia */ - return OL_DRAWSEL_NONE; - } - - if (set != OL_SETSEL_NONE) { - // XXX extern_set_butspace(F5KEY, 0); - } - else { - return OL_DRAWSEL_NORMAL; - } - - return OL_DRAWSEL_NONE; -} - static eOLDrawState tree_element_active_camera(bContext *UNUSED(C), Scene *scene, ViewLayer *UNUSED(sl), @@ -1041,8 +1015,6 @@ eOLDrawState tree_element_active(bContext *C, return tree_element_active_material(C, scene, view_layer, soops, te, set); case ID_WO: return tree_element_active_world(C, scene, view_layer, soops, te, set); - case ID_LA: - return tree_element_active_light(C, scene, view_layer, soops, te, set); case ID_TXT: return tree_element_active_text(C, scene, view_layer, soops, te, set); case ID_CA: @@ -1160,7 +1132,7 @@ static void do_outliner_item_activate_tree_element(bContext *C, WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), (Scene *)tselem->id); } } - else if (te->idcode == ID_GR) { + else if ((te->idcode == ID_GR) && (soops->outlinevis != SO_VIEW_LAYER)) { Collection *gr = (Collection *)tselem->id; if (extend) { diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 80424f021e2..6da2e913003 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1808,7 +1808,7 @@ static void outliner_collections_children_sort(ListBase *lb) } for (te = lb->first; te; te = te->next) { - outliner_sort(&te->subtree); + outliner_collections_children_sort(&te->subtree); } } diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 4c591a61f67..091efc56c09 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -303,6 +303,7 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED( soutliner->spacetype = SPACE_OUTLINER; soutliner->filter_id_type = ID_GR; soutliner->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE; + soutliner->outlinevis = SO_VIEW_LAYER; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for outliner"); @@ -384,6 +385,14 @@ static void outliner_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, } } +static void outliner_deactivate(struct ScrArea *sa) +{ + /* Remove hover highlights */ + SpaceOutliner *soops = sa->spacedata.first; + outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED, false); + ED_region_tag_redraw(BKE_area_find_region_type(sa, RGN_TYPE_WINDOW)); +} + /* only called once, from space_api/spacetypes.c */ void ED_spacetype_outliner(void) { @@ -401,6 +410,7 @@ void ED_spacetype_outliner(void) st->keymap = outliner_keymap; st->dropboxes = outliner_dropboxes; st->id_remap = outliner_id_remap; + st->deactivate = outliner_deactivate; /* regions: main window */ art = MEM_callocN(sizeof(ARegionType), "spacetype outliner region"); diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index b5bb79fb430..e8f18eeebc7 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -149,7 +149,7 @@ static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type) int proximity = INT_MAX; if (!ed || !ed->seqbasep) { - return 1; + return 2; } for (seq = ed->seqbasep->first; seq; seq = seq->next) { @@ -161,9 +161,9 @@ static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type) } if (tgt) { - return tgt->machine; + return tgt->machine + 1; } - return 1; + return 2; } static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, int flag, int type) @@ -173,7 +173,7 @@ static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, i int cfra = (int)CFRA; /* effect strips don't need a channel initialized from the mouse */ - if (!(flag & SEQPROP_NOCHAN)) { + if (!(flag & SEQPROP_NOCHAN) && RNA_struct_property_is_set(op->ptr, "channel") == 0) { RNA_int_set(op->ptr, "channel", sequencer_generic_invoke_xy_guess_channel(C, type)); } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 805ec26950a..a59cc36f28e 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1121,8 +1121,7 @@ static void sequencer_display_size(Scene *scene, float r_viewrect[2]) r_viewrect[0] = (float)scene->r.xsch; r_viewrect[1] = (float)scene->r.ysch; - /* Aspect ratio seems to have no effect on output image*/ - /* r_viewrect[0] *= scene->r.xasp / scene->r.yasp; */ + r_viewrect[0] *= scene->r.xasp / scene->r.yasp; } static void sequencer_draw_gpencil(const bContext *C) @@ -1822,7 +1821,7 @@ typedef struct CacheDrawData { /* Called as a callback */ static bool draw_cache_view_cb( - void *userdata, struct Sequence *seq, int cfra, int cache_type, float UNUSED(cost)) + void *userdata, struct Sequence *seq, int nfra, int cache_type, float UNUSED(cost)) { CacheDrawData *drawdata = userdata; const bContext *C = drawdata->C; @@ -1902,6 +1901,7 @@ static bool draw_cache_view_cb( } } + int cfra = seq->start + nfra; immUniformColor4f(color[0], color[1], color[2], color[3]); immRectf(pos, cfra, stripe_bot, cfra + 1, stripe_top); @@ -2087,7 +2087,7 @@ void draw_timeline_seq(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); /* scrubbing region */ - ED_scrubbing_draw(ar, scene, !(sseq->flag & SEQ_DRAWFRAMES), true); + ED_time_scrub_draw(ar, scene, !(sseq->flag & SEQ_DRAWFRAMES), true); /* scrollers */ scrollers = UI_view2d_scrollers_calc(v2d, NULL); @@ -2101,7 +2101,7 @@ void draw_timeline_seq(const bContext *C, ARegion *ar) 0, 15 * UI_DPI_FAC, 15 * UI_DPI_FAC, - UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y); + UI_DPI_FAC * ar->sizey - UI_TIME_SCRUB_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 a3030153e6c..a998ae7a7b3 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -2680,7 +2680,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op) while (seq) { next = seq->next; if (seq != seqm && (seq->flag & SELECT)) { - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_dependent(scene, seq); channel_max = max_ii(seq->machine, channel_max); BLI_remlink(ed->seqbasep, seq); BLI_addtail(&seqm->seqbase, seq); @@ -2755,7 +2755,7 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op)) } for (seq = last_seq->seqbase.first; seq != NULL; seq = seq->next) { - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_dependent(scene, seq); } BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase); @@ -3518,8 +3518,8 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op) BKE_sound_add_scene_sound_defaults(scene, seq_other); } - BKE_sequence_invalidate_cache(scene, seq_act); - BKE_sequence_invalidate_cache(scene, seq_other); + BKE_sequence_invalidate_cache_raw(scene, seq_act); + BKE_sequence_invalidate_cache_raw(scene, seq_other); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c index e00d33853a3..f262c6518aa 100644 --- a/source/blender/editors/space_sequencer/sequencer_modifier.c +++ b/source/blender/editors/space_sequencer/sequencer_modifier.c @@ -64,7 +64,7 @@ static int strip_modifier_add_exec(bContext *C, wmOperator *op) BKE_sequence_modifier_new(seq, NULL, type); - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -115,7 +115,7 @@ static int strip_modifier_remove_exec(bContext *C, wmOperator *op) BLI_remlink(&seq->modifiers, smd); BKE_sequence_modifier_free(smd); - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -175,7 +175,7 @@ static int strip_modifier_move_exec(bContext *C, wmOperator *op) } } - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -249,7 +249,7 @@ static int strip_modifier_copy_exec(bContext *C, wmOperator *op) } SEQ_END; - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index e16029395bd..593dd86477a 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -108,6 +108,8 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event) UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy); + fx /= scene->r.xasp / scene->r.yasp; + fx += (float)scene->r.xsch / 2.0f; fy += (float)scene->r.ysch / 2.0f; fx *= (float)ibuf->x / (float)scene->r.xsch; diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 7a02b1850ae..6ab44ded046 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -729,6 +729,7 @@ static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *ar) keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0); WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap); + UI_panel_category_active_set_default(ar, "Strip"); ED_region_panels_init(wm, ar); } diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index a9dd2a59d1e..2593571d9a3 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -247,7 +247,7 @@ static int text_new_exec(bContext *C, wmOperator *UNUSED(op)) if (prop) { RNA_id_pointer_create(&text->id, &idptr); - RNA_property_pointer_set(NULL, &ptr, prop, idptr); + RNA_property_pointer_set(&ptr, prop, idptr, NULL); RNA_property_update(C, &ptr, prop); } else if (st) { @@ -326,7 +326,7 @@ static int text_open_exec(bContext *C, wmOperator *op) if (pprop->prop) { RNA_id_pointer_create(&text->id, &idptr); - RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL); RNA_property_update(C, &pprop->ptr, pprop->prop); } else if (st) { diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c index a67e6c27acb..04ef2ed8118 100644 --- a/source/blender/editors/space_userpref/userpref_ops.c +++ b/source/blender/editors/space_userpref/userpref_ops.c @@ -48,7 +48,7 @@ static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op)) UI_theme_init_default(); UI_style_init_default(); WM_event_add_notifier(C, NC_WINDOW, NULL); - + U.runtime.is_dirty = true; return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index afc3b80fe3e..2ce67bfbe4c 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -105,7 +105,8 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph, ARegion *ar, float viewmat[4][4], float winmat[4][4], - const rcti *rect) + const rcti *rect, + bool offscreen) { RegionView3D *rv3d = ar->regiondata; @@ -138,7 +139,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph, /* calculate GLSL view dependent values */ /* store window coordinates scaling/offset */ - if (rv3d->persp == RV3D_CAMOB && v3d->camera) { + if (!offscreen && rv3d->persp == RV3D_CAMOB && v3d->camera) { rctf cameraborder; ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &cameraborder, false); rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder); @@ -184,7 +185,22 @@ static void view3d_main_region_setup_view(Depsgraph *depsgraph, { RegionView3D *rv3d = ar->regiondata; - ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect); + ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect, false); + + /* set for opengl */ + GPU_matrix_projection_set(rv3d->winmat); + GPU_matrix_set(rv3d->viewmat); +} + +static void view3d_main_region_setup_offscreen(Depsgraph *depsgraph, + Scene *scene, + View3D *v3d, + ARegion *ar, + float viewmat[4][4], + float winmat[4][4]) +{ + RegionView3D *rv3d = ar->regiondata; + ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, NULL, true); /* set for opengl */ GPU_matrix_projection_set(rv3d->winmat); @@ -1480,14 +1496,14 @@ static void view3d_stereo3d_setup_offscreen(Depsgraph *depsgraph, const bool is_left = STREQ(viewname, STEREO_LEFT_NAME); BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); - view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL); + view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat); } else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ float viewmat[4][4]; Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); - view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL); + view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat); } } @@ -1545,7 +1561,7 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph, view3d_stereo3d_setup_offscreen(depsgraph, scene, v3d, ar, winmat, viewname); } else { - view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL); + view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat); } /* main drawing call */ @@ -1579,7 +1595,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, int sizex, int sizey, uint flag, - uint draw_flags, int alpha_mode, int samples, const char *viewname, @@ -1589,7 +1604,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, { RegionView3D *rv3d = ar->regiondata; const bool draw_sky = (alpha_mode == R_ADDSKY); - const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE); /* view state */ bool is_ortho = false; @@ -1611,7 +1625,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, if (own_ofs) { /* bind */ - ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, true, false, err_out); + ofs = GPU_offscreen_create(sizex, sizey, samples, true, false, err_out); if (ofs == NULL) { DRW_opengl_context_disable(); return NULL; @@ -1667,120 +1681,28 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, } } - if ((samples && use_full_sample) == 0) { - const bool do_color_management = (ibuf->rect_float == NULL); - /* Single-pass render, common case */ - ED_view3d_draw_offscreen(depsgraph, - scene, - drawtype, - v3d, - ar, - sizex, - sizey, - NULL, - winmat, - draw_sky, - !is_ortho, - viewname, - do_color_management, - ofs, - NULL); - - if (ibuf->rect_float) { - GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float); - } - else if (ibuf->rect) { - GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect); - } - } - else { - /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling. - * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */ - static float jit_ofs[32][2]; - float winmat_jitter[4][4]; - float *rect_temp = (ibuf->rect_float) ? - ibuf->rect_float : - MEM_mallocN(sizex * sizey * sizeof(float[4]), "rect_temp"); - float *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(float[4]), "accum_buffer"); - GPUViewport *viewport = GPU_viewport_create_from_offscreen(ofs); - - BLI_jitter_init(jit_ofs, samples); - - /* first sample buffer, also initializes 'rv3d->persmat' */ - ED_view3d_draw_offscreen(depsgraph, - scene, - drawtype, - v3d, - ar, - sizex, - sizey, - NULL, - winmat, - draw_sky, - !is_ortho, - viewname, - false, - ofs, - viewport); - GPU_offscreen_read_pixels(ofs, GL_FLOAT, accum_buffer); - - /* skip the first sample */ - for (int j = 1; j < samples; j++) { - copy_m4_m4(winmat_jitter, winmat); - window_translate_m4(winmat_jitter, - rv3d->persmat, - (jit_ofs[j][0] * 2.0f) / sizex, - (jit_ofs[j][1] * 2.0f) / sizey); - - ED_view3d_draw_offscreen(depsgraph, - scene, - drawtype, - v3d, - ar, - sizex, - sizey, - NULL, - winmat_jitter, - draw_sky, - !is_ortho, - viewname, - false, - ofs, - viewport); - GPU_offscreen_read_pixels(ofs, GL_FLOAT, rect_temp); - - uint i = sizex * sizey * 4; - while (i--) { - accum_buffer[i] += rect_temp[i]; - } - } - - { - /* don't free data owned by 'ofs' */ - GPU_viewport_clear_from_offscreen(viewport); - GPU_viewport_free(viewport); - } + const bool do_color_management = (ibuf->rect_float == NULL); + ED_view3d_draw_offscreen(depsgraph, + scene, + drawtype, + v3d, + ar, + sizex, + sizey, + NULL, + winmat, + draw_sky, + !is_ortho, + viewname, + do_color_management, + ofs, + NULL); - if (ibuf->rect_float == NULL) { - MEM_freeN(rect_temp); - } - - if (ibuf->rect_float) { - float *rect_float = ibuf->rect_float; - uint i = sizex * sizey * 4; - while (i--) { - rect_float[i] = accum_buffer[i] / samples; - } - } - else { - uchar *rect_ub = (uchar *)ibuf->rect; - uint i = sizex * sizey * 4; - while (i--) { - rect_ub[i] = (uchar)(255.0f * accum_buffer[i] / samples); - } - } - - MEM_freeN(accum_buffer); + if (ibuf->rect_float) { + GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float); + } + else if (ibuf->rect) { + GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect); } /* unbind */ @@ -1889,7 +1811,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph, width, height, flag, - draw_flags, alpha_mode, samples, viewname, diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index e0dbe1f6543..755852a2e18 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -152,13 +152,11 @@ void ED_view3d_clipping_enable(void) /* *********************** backdraw for selection *************** */ -static void validate_object_select_id(struct Depsgraph *depsgraph, - Scene *scene, - ARegion *ar, - View3D *v3d, - Object *obact, - Object *obedit, - short select_mode) +/** + * \note Only use in object mode. + */ +static void validate_object_select_id( + struct Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d, Object *obact) { RegionView3D *rv3d = ar->regiondata; Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); @@ -178,9 +176,6 @@ static void validate_object_select_id(struct Depsgraph *depsgraph, else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) { /* do nothing */ } - else if ((obedit && (obedit->mode & OB_MODE_EDIT)) && !XRAY_FLAG_ENABLED(v3d)) { - /* do nothing */ - } else { v3d->flag &= ~V3D_INVALID_BACKBUF; return; @@ -190,34 +185,18 @@ static void validate_object_select_id(struct Depsgraph *depsgraph, return; } -#if 0 - if (test) { - if (qtest()) { - addafterqueue(ar->win, BACKBUFDRAW, 1); - return; - } - } -#endif - -#if 0 /* v3d->zbuf deprecated */ - if (v3d->shading.type > OB_WIRE) { - v3d->zbuf = true; - } -#endif - - G.f |= G_FLAG_BACKBUFSEL; - if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { + uint dummy_vert_ofs, dummy_edge_ofs, dummy_face_ofs; DRW_framebuffer_select_id_setup(ar, true); DRW_draw_select_id_object(scene_eval, rv3d, obact_eval, - select_mode, + scene->toolsettings->selectmode, false, - 0, - &bm_vertoffs, - &bm_wireoffs, - &bm_solidoffs); + 1, + &dummy_vert_ofs, + &dummy_edge_ofs, + &dummy_face_ofs); DRW_framebuffer_select_id_release(ar); } @@ -225,8 +204,6 @@ static void validate_object_select_id(struct Depsgraph *depsgraph, /* TODO: Create a flag in `DRW_manager` because the drawing is no longer * made on the backbuffer in this case. */ v3d->flag &= ~V3D_INVALID_BACKBUF; - - G.f &= ~G_FLAG_BACKBUFSEL; } /* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow. @@ -251,21 +228,15 @@ static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void GPU_framebuffer_free(tmp_fb); } -void ED_view3d_select_id_validate_with_select_mode(ViewContext *vc, short select_mode) +void ED_view3d_select_id_validate(ViewContext *vc) { /* TODO: Create a flag in `DRW_manager` because the drawing is no longer * made on the backbuffer in this case. */ if (vc->v3d->flag & V3D_INVALID_BACKBUF) { - validate_object_select_id( - vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit, select_mode); + validate_object_select_id(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact); } } -void ED_view3d_select_id_validate(ViewContext *vc) -{ - ED_view3d_select_id_validate_with_select_mode(vc, -1); -} - void ED_view3d_backbuf_depth_validate(ViewContext *vc) { if (vc->v3d->flag & V3D_INVALID_BACKBUF) { @@ -281,7 +252,7 @@ void ED_view3d_backbuf_depth_validate(ViewContext *vc) } } -uint *ED_view3d_select_id_read_rect(ViewContext *UNUSED(vc), const rcti *clip, uint *r_buf_len) +uint *ED_view3d_select_id_read_rect(const rcti *clip, uint *r_buf_len) { uint width = BLI_rcti_size_x(clip); uint height = BLI_rcti_size_y(clip); @@ -306,25 +277,8 @@ int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); } -/* samples a single pixel (copied from vpaint) */ -uint ED_view3d_select_id_sample(ViewContext *vc, int x, int y) -{ - if (x >= vc->ar->winx || y >= vc->ar->winy) { - return 0; - } - - uint buf_len; - uint *buf = ED_view3d_select_id_read(vc, x, y, x, y, &buf_len); - BLI_assert(0 != buf_len); - uint ret = buf[0]; - MEM_freeN(buf); - - return ret; -} - /* reads full rect, converts indices */ -uint *ED_view3d_select_id_read( - ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len) +uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_buf_len) { if (UNLIKELY((xmin > xmax) || (ymin > ymax))) { return NULL; @@ -338,7 +292,7 @@ uint *ED_view3d_select_id_read( }; uint buf_len; - uint *buf = ED_view3d_select_id_read_rect(vc, &rect, &buf_len); + uint *buf = ED_view3d_select_id_read_rect(&rect, &buf_len); if (r_buf_len) { *r_buf_len = buf_len; @@ -347,85 +301,6 @@ uint *ED_view3d_select_id_read( return buf; } -/* smart function to sample a rect spiralling outside, nice for backbuf selection */ -uint ED_view3d_select_id_read_nearest(struct ViewContext *UNUSED(vc), - const int mval[2], - const uint id_min, - const uint id_max, - uint *r_dist) -{ - /* Create region around mouse cursor. This must be square and have an odd - * width, the spiraling algorithm does not work with arbitrary rectangles. */ - rcti rect; - BLI_rcti_init_pt_radius(&rect, mval, *r_dist); - rect.xmax += 1; - rect.ymax += 1; - - int width = BLI_rcti_size_x(&rect); - int height = width; - BLI_assert(width == height); - - /* Read from selection framebuffer. */ - uint *buf = MEM_mallocN(width * height * sizeof(*buf), __func__); - DRW_framebuffer_select_id_read(&rect, buf); - - /* Spiral, starting from center of buffer. */ - int spiral_offset = height * (int)(width / 2) + (height / 2); - int spiral_direction = 0; - - uint index = 0; - - for (int nr = 1; nr <= height; nr++) { - for (int a = 0; a < 2; a++) { - for (int b = 0; b < nr; b++) { - /* Find hit within the specified range. */ - uint hit_id = buf[spiral_offset]; - - if (hit_id && hit_id >= id_min && hit_id < id_max) { - /* Get x/y from spiral offset. */ - int hit_x = spiral_offset % width; - int hit_y = spiral_offset / width; - - int center_x = width / 2; - int center_y = height / 2; - - /* Manhatten distance in keeping with other screen-based selection. */ - *r_dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y)); - - /* Indices start at 1 here. */ - index = (hit_id - id_min) + 1; - goto exit; - } - - /* Next spiral step. */ - if (spiral_direction == 0) { - spiral_offset += 1; /* right */ - } - else if (spiral_direction == 1) { - spiral_offset -= width; /* down */ - } - else if (spiral_direction == 2) { - spiral_offset -= 1; /* left */ - } - else { - spiral_offset += width; /* up */ - } - - /* Stop if we are outside the buffer. */ - if (spiral_offset < 0 || spiral_offset >= width * height) { - goto exit; - } - } - - spiral_direction = (spiral_direction + 1) % 4; - } - } - -exit: - MEM_freeN(buf); - return index; -} - /* ************************************************************* */ static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser) diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c index 5af6fd8b04b..d39be3d8e20 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c @@ -131,7 +131,7 @@ static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *UNUSE return true; } -static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) +static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup) { struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__); @@ -227,6 +227,9 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup * } /* When dragging an axis, use this instead. */ + wmWindowManager *wm = CTX_wm_manager(C); + gz->keymap = WM_keymap_ensure( + wm->defaultconf, "Generic Gizmo Click Drag", SPACE_EMPTY, RGN_TYPE_WINDOW); gz->drag_part = 0; } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 419ec87eec8..b3b4910c525 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -41,6 +41,7 @@ #include "MEM_guardedalloc.h" #include "BLI_array.h" +#include "BLI_bitmap.h" #include "BLI_math.h" #include "BLI_lasso_2d.h" #include "BLI_rect.h" @@ -88,6 +89,7 @@ #include "ED_mesh.h" #include "ED_object.h" #include "ED_screen.h" +#include "ED_select_buffer_utils.h" #include "ED_select_utils.h" #include "ED_sculpt.h" #include "ED_mball.h" @@ -179,20 +181,96 @@ static bool object_deselect_all_except(ViewLayer *view_layer, Base *b) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Internal Edit-Mesh Select Buffer Wrapper + * + * Avoid duplicate code when using edit-mode selection, + * actual logic is handled outside of this function. + * + * \note Currently this #EDBMSelectID_Context which is mesh specific + * however the logic could also be used for non-meshes too. + * + * \{ */ + +struct EditSelectBuf_Cache { + Base **bases; + uint bases_len; + struct EDBMSelectID_Context *sel_id_ctx; + BLI_bitmap *select_bitmap; +}; + +static void editselect_buf_cache_init(struct EditSelectBuf_Cache *esel, ViewContext *vc) +{ + if (vc->obedit) { + esel->bases = BKE_view_layer_array_from_bases_in_edit_mode( + vc->view_layer, vc->v3d, &esel->bases_len); + } + else { + /* Use for paint modes, currently only a single object at a time. */ + if (vc->obact) { + esel->bases = MEM_mallocN(sizeof(esel->bases), __func__); + esel->bases[0] = BKE_view_layer_base_find(vc->view_layer, vc->obact); + esel->bases_len = 1; + } + else { + esel->bases = NULL; + esel->bases_len = 0; + } + } + esel->sel_id_ctx = EDBM_select_id_context_create( + vc, esel->bases, esel->bases_len, vc->scene->toolsettings->selectmode); + for (int i = 0; i < esel->bases_len; i++) { + esel->bases[i]->object->runtime.select_id = i; + } +} + +static void editselect_buf_cache_free(struct EditSelectBuf_Cache *esel) +{ + if (esel->sel_id_ctx) { + EDBM_select_id_context_destroy(esel->sel_id_ctx); + } + MEM_SAFE_FREE(esel->select_bitmap); + MEM_SAFE_FREE(esel->bases); +} + +static void editselect_buf_cache_free_voidp(void *esel_voidp) +{ + editselect_buf_cache_free(esel_voidp); + MEM_freeN(esel_voidp); +} + +static void editselect_buf_cache_init_with_generic_userdata(wmGenericUserData *wm_userdata, + ViewContext *vc) +{ + struct EditSelectBuf_Cache *esel = MEM_callocN(sizeof(*esel), __func__); + wm_userdata->data = esel; + wm_userdata->free_fn = editselect_buf_cache_free_voidp; + wm_userdata->use_free = true; + editselect_buf_cache_init(esel, vc); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Internal Edit-Mesh Utilities * \{ */ -static bool edbm_backbuf_check_and_select_verts(BMEditMesh *em, const eSelectOp sel_op) +static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel, + Object *ob, + BMEditMesh *em, + const eSelectOp sel_op) { BMVert *eve; BMIter iter; - uint index = bm_wireoffs; bool changed = false; + const BLI_bitmap *select_bitmap = esel->select_bitmap; + uint index = EDBM_select_id_context_offset_for_object_elem( + esel->sel_id_ctx, ob->runtime.select_id, BM_VERT); + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); - const bool is_inside = EDBM_backbuf_check(index); + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_vert_select_set(em->bm, eve, sel_op_result); @@ -204,17 +282,23 @@ static bool edbm_backbuf_check_and_select_verts(BMEditMesh *em, const eSelectOp return changed; } -static bool edbm_backbuf_check_and_select_edges(BMEditMesh *em, const eSelectOp sel_op) +static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel, + Object *ob, + BMEditMesh *em, + const eSelectOp sel_op) { BMEdge *eed; BMIter iter; - uint index = bm_solidoffs; bool changed = false; + const BLI_bitmap *select_bitmap = esel->select_bitmap; + uint index = EDBM_select_id_context_offset_for_object_elem( + esel->sel_id_ctx, ob->runtime.select_id, BM_EDGE); + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = EDBM_backbuf_check(index); + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_edge_select_set(em->bm, eed, sel_op_result); @@ -226,17 +310,23 @@ static bool edbm_backbuf_check_and_select_edges(BMEditMesh *em, const eSelectOp return changed; } -static bool edbm_backbuf_check_and_select_faces(BMEditMesh *em, const eSelectOp sel_op) +static bool edbm_backbuf_check_and_select_faces(struct EditSelectBuf_Cache *esel, + Object *ob, + BMEditMesh *em, + const eSelectOp sel_op) { BMFace *efa; BMIter iter; - uint index = 1; bool changed = false; + const BLI_bitmap *select_bitmap = esel->select_bitmap; + uint index = EDBM_select_id_context_offset_for_object_elem( + esel->sel_id_ctx, ob->runtime.select_id, BM_FACE); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); - const bool is_inside = EDBM_backbuf_check(index); + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_face_select_set(em->bm, efa, sel_op_result); @@ -249,17 +339,21 @@ static bool edbm_backbuf_check_and_select_faces(BMEditMesh *em, const eSelectOp } /* object mode, edbm_ prefix is confusing here, rename? */ -static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp sel_op) +static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, + struct EditSelectBuf_Cache *esel, + const eSelectOp sel_op) { MVert *mv = me->mvert; uint index; bool changed = false; + const BLI_bitmap *select_bitmap = esel->select_bitmap; + if (mv) { - for (index = 1; index <= me->totvert; index++, mv++) { + for (index = 0; index < me->totvert; index++, mv++) { if (!(mv->flag & ME_HIDE)) { const bool is_select = mv->flag & SELECT; - const bool is_inside = EDBM_backbuf_check(index); + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); @@ -272,17 +366,21 @@ static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp } /* object mode, edbm_ prefix is confusing here, rename? */ -static bool edbm_backbuf_check_and_select_tfaces(Mesh *me, const eSelectOp sel_op) +static bool edbm_backbuf_check_and_select_faces_obmode(Mesh *me, + struct EditSelectBuf_Cache *esel, + const eSelectOp sel_op) { MPoly *mpoly = me->mpoly; uint index; bool changed = false; + const BLI_bitmap *select_bitmap = esel->select_bitmap; + if (mpoly) { - for (index = 1; index <= me->totpoly; index++, mpoly++) { + for (index = 0; index < me->totpoly; index++, mpoly++) { if (!(mpoly->flag & ME_HIDE)) { const bool is_select = mpoly->flag & ME_FACE_SEL; - const bool is_inside = EDBM_backbuf_check(index); + const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL); @@ -621,14 +719,26 @@ static void do_lasso_select_mesh__doSelectVert(void *userData, data->is_changed = true; } } -static void do_lasso_select_mesh__doSelectEdge_pass0( - void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) -{ - LassoSelectUserData *data = userData; +struct LassoSelectUserData_ForMeshEdge { + LassoSelectUserData *data; + struct EditSelectBuf_Cache *esel; + uint backbuf_offset; +}; +static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data, + BMEdge *eed, + const float screen_co_a[2], + const float screen_co_b[2], + int index) +{ + struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data; + LassoSelectUserData *data = data_for_edge->data; + const bool is_visible = (data_for_edge->esel ? + BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, + data_for_edge->backbuf_offset + index) : + true); const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = - (EDBM_backbuf_check(bm_solidoffs + index) && - edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) && + (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) && BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) && BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); @@ -638,15 +748,24 @@ static void do_lasso_select_mesh__doSelectEdge_pass0( data->is_changed = true; } } -static void do_lasso_select_mesh__doSelectEdge_pass1( - void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) +static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data, + BMEdge *eed, + const float screen_co_a[2], + const float screen_co_b[2], + int index) { - LassoSelectUserData *data = userData; + struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data; + LassoSelectUserData *data = data_for_edge->data; + const bool is_visible = (data_for_edge->esel ? + BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, + data_for_edge->backbuf_offset + index) : + true); const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = - (EDBM_backbuf_check(bm_solidoffs + index) && - BLI_lasso_is_edge_inside( - data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), IS_CLIPPED)); + const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcords, + data->moves, + UNPACK2(screen_co_a), + UNPACK2(screen_co_b), + IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); @@ -672,6 +791,7 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, } static bool do_lasso_select_mesh(ViewContext *vc, + wmGenericUserData *wm_userdata, const int mcords[][2], short moves, const eSelectOp sel_op) @@ -679,7 +799,6 @@ static bool do_lasso_select_mesh(ViewContext *vc, LassoSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; rcti rect; - int bbsel; /* set editmesh */ vc->em = BKE_editmesh_from_object(vc->obedit); @@ -699,12 +818,22 @@ static bool do_lasso_select_mesh(ViewContext *vc, ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); GPU_matrix_set(vc->rv3d->viewmat); - bbsel = EDBM_backbuf_border_mask_init( - vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + + const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); + + struct EditSelectBuf_Cache *esel = wm_userdata->data; + if (use_zbuf) { + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect); + } + } if (ts->selectmode & SCE_SELECT_VERTEX) { - if (bbsel) { - data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op); + if (use_zbuf) { + data.is_changed |= edbm_backbuf_check_and_select_verts(esel, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenVert( @@ -712,18 +841,26 @@ static bool do_lasso_select_mesh(ViewContext *vc, } } if (ts->selectmode & SCE_SELECT_EDGE) { - /* Does both bbsel and non-bbsel versions (need screen cos for both) */ + /* Does both use_zbuf and non-use_zbuf versions (need screen cos for both) */ + struct LassoSelectUserData_ForMeshEdge data_for_edge = { + .data = &data, + .esel = use_zbuf ? esel : NULL, + .backbuf_offset = use_zbuf ? + EDBM_select_id_context_offset_for_object_elem( + esel->sel_id_ctx, vc->obedit->runtime.select_id, BM_EDGE) : + 0, + }; mesh_foreachScreenEdge( - vc, do_lasso_select_mesh__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR); + vc, do_lasso_select_mesh__doSelectEdge_pass0, &data_for_edge, V3D_PROJ_TEST_CLIP_NEAR); if (data.is_done == false) { mesh_foreachScreenEdge( - vc, do_lasso_select_mesh__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR); + vc, do_lasso_select_mesh__doSelectEdge_pass1, &data_for_edge, V3D_PROJ_TEST_CLIP_NEAR); } } if (ts->selectmode & SCE_SELECT_FACE) { - if (bbsel) { - data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op); + if (use_zbuf) { + data.is_changed |= edbm_backbuf_check_and_select_faces(esel, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenFace( @@ -731,8 +868,6 @@ static bool do_lasso_select_mesh(ViewContext *vc, } } - EDBM_backbuf_free(); - if (data.is_changed) { EDBM_selectmode_flush(vc->em); } @@ -973,6 +1108,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, } } static bool do_lasso_select_paintvert(ViewContext *vc, + wmGenericUserData *wm_userdata, const int mcords[][2], short moves, const eSelectOp sel_op) @@ -994,14 +1130,20 @@ static bool do_lasso_select_paintvert(ViewContext *vc, BLI_lasso_boundbox(&rect, mcords, moves); + struct EditSelectBuf_Cache *esel = wm_userdata->data; if (use_zbuf) { - bm_vertoffs = me->totvert + 1; /* max index array */ - - EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - - changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op); + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect); + } + } - EDBM_backbuf_free(); + if (use_zbuf) { + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); + } } else { LassoSelectUserData data; @@ -1023,9 +1165,11 @@ static bool do_lasso_select_paintvert(ViewContext *vc, paintvert_flush_flags(ob); paintvert_tag_select_update(vc->C, ob); } + return changed; } static bool do_lasso_select_paintface(ViewContext *vc, + wmGenericUserData *wm_userdata, const int mcords[][2], short moves, const eSelectOp sel_op) @@ -1038,19 +1182,25 @@ static bool do_lasso_select_paintface(ViewContext *vc, return false; } - bm_vertoffs = me->totpoly + 1; /* max index array */ - - BLI_lasso_boundbox(&rect, mcords, moves); - EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { /* flush selection at the end */ changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); } - changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op); - EDBM_backbuf_free(); + BLI_lasso_boundbox(&rect, mcords, moves); + + struct EditSelectBuf_Cache *esel = wm_userdata->data; + if (esel == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect); + } + + if (esel->select_bitmap) { + changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); + } if (changed) { paintface_flush_flags(vc->C, ob, SELECT); @@ -1098,12 +1248,15 @@ static bool view3d_lasso_select( Object *ob = CTX_data_active_object(C); bool changed_multi = false; + wmGenericUserData wm_userdata_buf = {0}; + wmGenericUserData *wm_userdata = &wm_userdata_buf; + if (vc->obedit == NULL) { /* Object Mode */ if (BKE_paint_select_face_test(ob)) { - changed_multi |= do_lasso_select_paintface(vc, mcords, moves, sel_op); + changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcords, moves, sel_op); } else if (BKE_paint_select_vert_test(ob)) { - changed_multi |= do_lasso_select_paintvert(vc, mcords, moves, sel_op); + changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcords, moves, sel_op); } else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { @@ -1120,14 +1273,13 @@ static bool view3d_lasso_select( } } else { /* Edit Mode */ - FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, vc->v3d, ob->type, ob->mode, ob_iter) { ED_view3d_viewcontext_init_object(vc, ob_iter); bool changed = false; switch (vc->obedit->type) { case OB_MESH: - changed = do_lasso_select_mesh(vc, mcords, moves, sel_op); + changed = do_lasso_select_mesh(vc, wm_userdata, mcords, moves, sel_op); break; case OB_CURVE: case OB_SURF: @@ -1155,6 +1307,9 @@ static bool view3d_lasso_select( } FOREACH_OBJECT_IN_MODE_END; } + + WM_generic_user_data_free(wm_userdata); + return changed_multi; } @@ -2336,9 +2491,13 @@ static void do_paintvert_box_select__doSelectVert(void *userData, data->is_changed = true; } } -static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op) +static bool do_paintvert_box_select(ViewContext *vc, + wmGenericUserData *wm_userdata, + const rcti *rect, + const eSelectOp sel_op) { const bool use_zbuf = !XRAY_ENABLED(vc->v3d); + Mesh *me; me = vc->obact->data; @@ -2355,48 +2514,16 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSe /* pass */ } else if (use_zbuf) { - MVert *mvert; - uint *rt, *buf, buf_len; - int a, index; - char *selar; - - selar = MEM_callocN(me->totvert + 1, "selar"); - - ED_view3d_select_id_validate(vc); - buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); - - rt = buf; - - a = buf_len; - while (a--) { - if (*rt) { - index = *rt; - if (index <= me->totvert) { - selar[index] = 1; - } - } - rt++; + struct EditSelectBuf_Cache *esel = wm_userdata->data; + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect); } - - mvert = me->mvert; - for (a = 1; a <= me->totvert; a++, mvert++) { - if ((mvert->flag & ME_HIDE) == 0) { - const bool is_select = mvert->flag & SELECT; - const bool is_inside = (selar[a] != 0); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mvert->flag, sel_op_result, SELECT); - changed = true; - } - } + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); } - - MEM_freeN(buf); - MEM_freeN(selar); - -#ifdef __APPLE__ - glReadBuffer(GL_BACK); -#endif } else { BoxSelectUserData data; @@ -2420,6 +2547,46 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSe return changed; } +static bool do_paintface_box_select(ViewContext *vc, + wmGenericUserData *wm_userdata, + const rcti *rect, + int sel_op) +{ + Object *ob = vc->obact; + Mesh *me; + + me = BKE_mesh_from_object(ob); + if ((me == NULL) || (me->totpoly == 0)) { + return false; + } + + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + changed |= paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false); + } + + if (BLI_rcti_is_empty(rect)) { + /* pass */ + } + else { + struct EditSelectBuf_Cache *esel = wm_userdata->data; + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect); + } + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); + } + } + + if (changed) { + paintface_flush_flags(vc->C, vc->obact, SELECT); + } + return changed; +} + static void do_nurbs_box_select__doSelect(void *userData, Nurb *UNUSED(nu), BPoint *bp, @@ -2520,12 +2687,22 @@ static void do_mesh_box_select__doSelectVert(void *userData, data->is_changed = true; } } +struct BoxSelectUserData_ForMeshEdge { + BoxSelectUserData *data; + struct EditSelectBuf_Cache *esel; + uint backbuf_offset; +}; static void do_mesh_box_select__doSelectEdge_pass0( void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { - BoxSelectUserData *data = userData; + struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData; + BoxSelectUserData *data = data_for_edge->data; + const bool is_visible = (data_for_edge->esel ? + BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, + data_for_edge->backbuf_offset + index) : + true); const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = (EDBM_backbuf_check(bm_solidoffs + index) && + const bool is_inside = (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { @@ -2537,10 +2714,14 @@ static void do_mesh_box_select__doSelectEdge_pass0( static void do_mesh_box_select__doSelectEdge_pass1( void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) { - BoxSelectUserData *data = userData; + struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData; + BoxSelectUserData *data = data_for_edge->data; + const bool is_visible = (data_for_edge->esel ? + BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, + data_for_edge->backbuf_offset + index) : + true); const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = (EDBM_backbuf_check(bm_solidoffs + index) && - edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); + const bool is_inside = (is_visible && edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); @@ -2561,11 +2742,13 @@ static void do_mesh_box_select__doSelectFace(void *userData, data->is_changed = true; } } -static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op) +static bool do_mesh_box_select(ViewContext *vc, + wmGenericUserData *wm_userdata, + const rcti *rect, + const eSelectOp sel_op) { BoxSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; - int bbsel; view3d_userdata_boxselect_init(&data, vc, rect, sel_op); @@ -2580,11 +2763,22 @@ static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); GPU_matrix_set(vc->rv3d->viewmat); - bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + + const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); + + struct EditSelectBuf_Cache *esel = wm_userdata->data; + if (use_zbuf) { + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect); + } + } if (ts->selectmode & SCE_SELECT_VERTEX) { - if (bbsel) { - data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op); + if (use_zbuf) { + data.is_changed |= edbm_backbuf_check_and_select_verts(esel, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenVert( @@ -2592,18 +2786,26 @@ static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_ } } if (ts->selectmode & SCE_SELECT_EDGE) { - /* Does both bbsel and non-bbsel versions (need screen cos for both) */ + /* Does both use_zbuf and non-use_zbuf versions (need screen cos for both) */ + struct BoxSelectUserData_ForMeshEdge cb_data = { + .data = &data, + .esel = use_zbuf ? esel : NULL, + .backbuf_offset = use_zbuf ? + EDBM_select_id_context_offset_for_object_elem( + esel->sel_id_ctx, vc->obedit->runtime.select_id, BM_EDGE) : + 0, + }; mesh_foreachScreenEdge( - vc, do_mesh_box_select__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR); + vc, do_mesh_box_select__doSelectEdge_pass0, &cb_data, V3D_PROJ_TEST_CLIP_NEAR); if (data.is_done == false) { mesh_foreachScreenEdge( - vc, do_mesh_box_select__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR); + vc, do_mesh_box_select__doSelectEdge_pass1, &cb_data, V3D_PROJ_TEST_CLIP_NEAR); } } if (ts->selectmode & SCE_SELECT_FACE) { - if (bbsel) { - data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op); + if (use_zbuf) { + data.is_changed |= edbm_backbuf_check_and_select_faces(esel, vc->obedit, vc->em, sel_op); } else { mesh_foreachScreenFace( @@ -2611,8 +2813,6 @@ static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_ } } - EDBM_backbuf_free(); - if (data.is_changed) { EDBM_selectmode_flush(vc->em); } @@ -2930,6 +3130,9 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) rcti rect; bool changed_multi = false; + wmGenericUserData wm_userdata_buf = {0}; + wmGenericUserData *wm_userdata = &wm_userdata_buf; + view3d_operator_needs_opengl(C); BKE_object_update_select_id(CTX_data_main(C)); @@ -2940,7 +3143,6 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) WM_operator_properties_border_to_rcti(op, &rect); if (vc.obedit) { - FOREACH_OBJECT_IN_MODE_BEGIN ( vc.view_layer, vc.v3d, vc.obedit->type, vc.obedit->mode, ob_iter) { ED_view3d_viewcontext_init_object(&vc, ob_iter); @@ -2949,7 +3151,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) switch (vc.obedit->type) { case OB_MESH: vc.em = BKE_editmesh_from_object(vc.obedit); - changed = do_mesh_box_select(&vc, &rect, sel_op); + changed = do_mesh_box_select(&vc, wm_userdata, &rect, sel_op); if (changed) { DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); @@ -2999,10 +3201,10 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) C, &vc, &rect, sel_op == SEL_OP_ADD ? true : false); } else if (vc.obact && BKE_paint_select_face_test(vc.obact)) { - changed_multi = do_paintface_box_select(&vc, &rect, sel_op); + changed_multi = do_paintface_box_select(&vc, wm_userdata, &rect, sel_op); } else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) { - changed_multi = do_paintvert_box_select(&vc, &rect, sel_op); + changed_multi = do_paintvert_box_select(&vc, wm_userdata, &rect, sel_op); } else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) { changed_multi = PE_box_select(C, &rect, sel_op); @@ -3015,6 +3217,8 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) } } + WM_generic_user_data_free(wm_userdata); + if (changed_multi) { return OPERATOR_FINISHED; } @@ -3120,10 +3324,13 @@ static void mesh_circle_doSelectFace(void *userData, } } -static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval[2], float rad) +static bool mesh_circle_select(ViewContext *vc, + wmGenericUserData *wm_userdata, + eSelectOp sel_op, + const int mval[2], + float rad) { ToolSettings *ts = vc->scene->toolsettings; - int bbsel; CircleSelectUserData data; vc->em = BKE_editmesh_from_object(vc->obedit); @@ -3136,14 +3343,30 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval } const bool select = (sel_op != SEL_OP_SUB); - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); + + if (use_zbuf) { + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + } + } + struct EditSelectBuf_Cache *esel = wm_userdata->data; + + if (use_zbuf) { + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f)); + } + if (ts->selectmode & SCE_SELECT_VERTEX) { - if (bbsel) { - changed |= edbm_backbuf_check_and_select_verts(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + if (use_zbuf) { + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_verts( + esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + } } else { mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); @@ -3151,8 +3374,11 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval } if (ts->selectmode & SCE_SELECT_EDGE) { - if (bbsel) { - changed |= edbm_backbuf_check_and_select_edges(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + if (use_zbuf) { + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_edges( + esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + } } else { mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); @@ -3160,17 +3386,25 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval } if (ts->selectmode & SCE_SELECT_FACE) { - if (bbsel) { - changed |= edbm_backbuf_check_and_select_faces(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + if (use_zbuf) { + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_faces( + esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + } } else { mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } - changed |= data.is_changed; + if (use_zbuf) { + if (esel->select_bitmap != NULL) { + MEM_freeN(esel->select_bitmap); + esel->select_bitmap = NULL; + } + } - EDBM_backbuf_free(); + changed |= data.is_changed; if (changed) { EDBM_selectmode_flush(vc->em); @@ -3179,6 +3413,7 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval } static bool paint_facesel_circle_select(ViewContext *vc, + wmGenericUserData *wm_userdata, const eSelectOp sel_op, const int mval[2], float rad) @@ -3186,7 +3421,6 @@ static bool paint_facesel_circle_select(ViewContext *vc, BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); Object *ob = vc->obact; Mesh *me = ob->data; - bool bbsel; bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { @@ -3194,13 +3428,21 @@ static bool paint_facesel_circle_select(ViewContext *vc, changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); } - bm_vertoffs = me->totpoly + 1; /* max index array */ + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + } - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); - if (bbsel) { - changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op); - EDBM_backbuf_free(); + { + struct EditSelectBuf_Cache *esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f)); + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); + MEM_freeN(esel->select_bitmap); + esel->select_bitmap = NULL; + } } + if (changed) { paintface_flush_flags(vc->C, ob, SELECT); } @@ -3220,6 +3462,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, } } static bool paint_vertsel_circle_select(ViewContext *vc, + wmGenericUserData *wm_userdata, const eSelectOp sel_op, const int mval[2], float rad) @@ -3228,7 +3471,6 @@ static bool paint_vertsel_circle_select(ViewContext *vc, const bool use_zbuf = !XRAY_ENABLED(vc->v3d); Object *ob = vc->obact; Mesh *me = ob->data; - bool bbsel; /* CircleSelectUserData data = {NULL}; */ /* UNUSED */ bool changed = false; @@ -3240,12 +3482,19 @@ static bool paint_vertsel_circle_select(ViewContext *vc, const bool select = (sel_op != SEL_OP_SUB); if (use_zbuf) { - bm_vertoffs = me->totvert + 1; /* max index array */ + if (wm_userdata->data == NULL) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); + } + } - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); - if (bbsel) { - changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op); - EDBM_backbuf_free(); + if (use_zbuf) { + struct EditSelectBuf_Cache *esel = wm_userdata->data; + const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx); + esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f)); + if (esel->select_bitmap != NULL) { + changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); + MEM_freeN(esel->select_bitmap); + esel->select_bitmap = NULL; } } else { @@ -3593,27 +3842,40 @@ static bool mball_circle_select(ViewContext *vc, /** Callbacks for circle selection in Editmode */ static bool obedit_circle_select(ViewContext *vc, + wmGenericUserData *wm_userdata, const eSelectOp sel_op, const int mval[2], float rad) { + bool changed = false; BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); switch (vc->obedit->type) { case OB_MESH: - return mesh_circle_select(vc, sel_op, mval, rad); + changed = mesh_circle_select(vc, wm_userdata, sel_op, mval, rad); + break; case OB_CURVE: case OB_SURF: - return nurbscurve_circle_select(vc, sel_op, mval, rad); + changed = nurbscurve_circle_select(vc, sel_op, mval, rad); + break; case OB_LATTICE: - return lattice_circle_select(vc, sel_op, mval, rad); + changed = lattice_circle_select(vc, sel_op, mval, rad); + break; case OB_ARMATURE: - return armature_circle_select(vc, sel_op, mval, rad); + changed = armature_circle_select(vc, sel_op, mval, rad); + break; case OB_MBALL: - return mball_circle_select(vc, sel_op, mval, rad); + changed = mball_circle_select(vc, sel_op, mval, rad); + break; default: BLI_assert(0); - return false; + break; } + + if (changed) { + DEG_id_tag_update(vc->obact->data, ID_RECALC_SELECT); + WM_main_add_notifier(NC_GEOM | ND_SELECT, vc->obact->data); + } + return changed; } static bool object_circle_select(ViewContext *vc, @@ -3662,8 +3924,13 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) const int radius = RNA_int_get(op->ptr, "radius"); const int mval[2] = {RNA_int_get(op->ptr, "x"), RNA_int_get(op->ptr, "y")}; + /* Allow each selection type to allocate their own data thats used between executions. */ + wmGesture *gesture = op->customdata; /* NULL when non-modal. */ + wmGenericUserData wm_userdata_buf = {0}; + wmGenericUserData *wm_userdata = gesture ? &gesture->user_data : &wm_userdata_buf; + const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"), - WM_gesture_is_modal_first(op->customdata)); + WM_gesture_is_modal_first(gesture)); ED_view3d_viewcontext_init(C, &vc); @@ -3672,7 +3939,9 @@ 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)); + if (obedit == NULL) { + 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); @@ -3681,16 +3950,13 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) obedit = vc.obedit; if (obedit) { - if (obedit_circle_select(&vc, sel_op, mval, (float)radius)) { - DEG_id_tag_update(obact->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); - } + obedit_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius); } else if (BKE_paint_select_face_test(obact)) { - paint_facesel_circle_select(&vc, sel_op, mval, (float)radius); + paint_facesel_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius); } else if (BKE_paint_select_vert_test(obact)) { - paint_vertsel_circle_select(&vc, sel_op, mval, (float)radius); + paint_vertsel_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius); } else if (obact->mode & OB_MODE_POSE) { pose_circle_select(&vc, sel_op, mval, (float)radius); @@ -3717,6 +3983,11 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) } } + /* Otherwise this is freed by the gesture. */ + if (wm_userdata == &wm_userdata_buf) { + WM_generic_user_data_free(wm_userdata); + } + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 2454358b687..5865efa0ffa 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -428,7 +428,7 @@ void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *ar) * can use them without redrawing first */ Depsgraph *depsgraph = CTX_data_depsgraph(C); Scene *scene = CTX_data_scene(C); - ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL); + ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL, false); } } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 09f198ff14c..c3acd604ee1 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4835,6 +4835,7 @@ static void initNormalRotation(TransInfo *t) BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; + BKE_editmesh_ensure_autosmooth(em); BKE_editmesh_lnorspace_update(em); storeCustomLNorValue(tc, bm); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 758551be0b5..6a9c6856a03 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1177,12 +1177,7 @@ static void recalcData_sequencer(TransInfo *t) Sequence *seq = tdsq->seq; if (seq != seq_prev) { - if (BKE_sequence_tx_fullupdate_test(seq)) { - BKE_sequence_invalidate_cache(t->scene, seq); - } - else { - BKE_sequence_invalidate_cache(t->scene, seq); - } + BKE_sequence_invalidate_cache_composite(t->scene, seq); } seq_prev = seq; diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index e43379dc358..68885a72092 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -1661,7 +1661,12 @@ static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *gzgroup) else if (tref && STREQ(tref->idname, "builtin.scale")) { ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_SCALE; } + else if (tref && STREQ(tref->idname, "builtin.transform")) { + ggd->twtype = V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE | + V3D_GIZMO_SHOW_OBJECT_SCALE; + } else { + /* This is also correct logic for 'builtin.transform', no special check needed. */ /* Setup all gizmos, they can be toggled via 'ToolSettings.gizmo_flag' */ ggd->twtype = V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE | V3D_GIZMO_SHOW_OBJECT_SCALE; @@ -1852,7 +1857,10 @@ static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *gzgr } } -static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C, wmGizmoGroup *gzgroup, wmGizmo *gz) +static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C, + wmGizmoGroup *gzgroup, + wmGizmo *gz, + const wmEvent *UNUSED(event)) { GizmoGroup *ggd = gzgroup->customdata; @@ -1971,12 +1979,12 @@ static bool WIDGETGROUP_gizmo_poll_tool(const struct bContext *C, struct wmGizmo return true; } -/* Expose as multiple gizmos so tools use one, persistant context another. +/* Expose as multiple gizmos so tools use one, persistent context another. * Needed because they use different options which isn't so simple to dynamically update. */ void VIEW3D_GGT_xform_gizmo(wmGizmoGroupType *gzgt) { - gzgt->name = "Transform Gizmo"; + gzgt->name = "3D View: Transform Gizmo"; gzgt->idname = "VIEW3D_GGT_xform_gizmo"; gzgt->flag = WM_GIZMOGROUPTYPE_3D; @@ -1990,12 +1998,26 @@ void VIEW3D_GGT_xform_gizmo(wmGizmoGroupType *gzgt) gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe; gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare; gzgt->invoke_prepare = WIDGETGROUP_gizmo_invoke_prepare; + + static const EnumPropertyItem rna_enum_gizmo_items[] = { + {V3D_GIZMO_SHOW_OBJECT_TRANSLATE, "TRANSLATE", 0, "Move", ""}, + {V3D_GIZMO_SHOW_OBJECT_ROTATE, "ROTATE", 0, "Rotate", ""}, + {V3D_GIZMO_SHOW_OBJECT_SCALE, "SCALE", 0, "Scale", ""}, + {0, "NONE", 0, "None", ""}, + {0, NULL, 0, NULL, NULL}, + }; + RNA_def_enum(gzgt->srna, + "drag_action", + rna_enum_gizmo_items, + V3D_GIZMO_SHOW_OBJECT_TRANSLATE, + "Drag Action", + ""); } /** Only poll, flag & gzmap_params differ. */ void VIEW3D_GGT_xform_gizmo_context(wmGizmoGroupType *gzgt) { - gzgt->name = "Transform Gizmo Context"; + gzgt->name = "3D View: Transform Gizmo Context"; gzgt->idname = "VIEW3D_GGT_xform_gizmo_context"; gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_PERSISTENT; diff --git a/source/blender/editors/transform/transform_gizmo_extrude_3d.c b/source/blender/editors/transform/transform_gizmo_extrude_3d.c index 47a584561f9..24ef92b3153 100644 --- a/source/blender/editors/transform/transform_gizmo_extrude_3d.c +++ b/source/blender/editors/transform/transform_gizmo_extrude_3d.c @@ -385,7 +385,8 @@ static void gizmo_mesh_extrude_draw_prepare(const bContext *C, wmGizmoGroup *gzg static void gizmo_mesh_extrude_invoke_prepare(const bContext *UNUSED(C), wmGizmoGroup *gzgroup, - wmGizmo *gz) + wmGizmo *gz, + const wmEvent *UNUSED(event)) { GizmoExtrudeGroup *ggd = gzgroup->customdata; if (ELEM(gz, ggd->adjust[0], ggd->adjust[1])) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 8606cd19c96..f028f2dc506 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -1170,7 +1170,7 @@ static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot) ot->exec = transform_exec; ot->modal = transform_modal; ot->cancel = transform_cancel; - ot->poll = ED_operator_editmesh_auto_smooth; + ot->poll = ED_operator_editmesh; RNA_def_float_rotation( ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); @@ -1210,6 +1210,60 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot) P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER); } +static int transform_from_gizmo_invoke(bContext *C, + wmOperator *UNUSED(op), + const wmEvent *UNUSED(event)) +{ + bToolRef *tref = WM_toolsystem_ref_from_context(C); + if (tref) { + ARegion *ar = CTX_wm_region(C); + wmGizmoMap *gzmap = ar->gizmo_map; + wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, "VIEW3D_GGT_xform_gizmo") : NULL; + if (gzgroup != NULL) { + PointerRNA gzg_ptr; + WM_toolsystem_ref_properties_ensure_from_gizmo_group(tref, gzgroup->type, &gzg_ptr); + const int drag_action = RNA_enum_get(&gzg_ptr, "drag_action"); + const char *op_id = NULL; + switch (drag_action) { + case V3D_GIZMO_SHOW_OBJECT_TRANSLATE: + op_id = "TRANSFORM_OT_translate"; + break; + case V3D_GIZMO_SHOW_OBJECT_ROTATE: + op_id = "TRANSFORM_OT_rotate"; + break; + case V3D_GIZMO_SHOW_OBJECT_SCALE: + op_id = "TRANSFORM_OT_resize"; + break; + default: + break; + } + if (op_id) { + wmOperatorType *ot = WM_operatortype_find(op_id, true); + PointerRNA op_ptr; + WM_operator_properties_create_ptr(&op_ptr, ot); + RNA_boolean_set(&op_ptr, "release_confirm", true); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr); + WM_operator_properties_free(&op_ptr); + return OPERATOR_FINISHED; + } + } + } + return OPERATOR_PASS_THROUGH; +} + +/* Use with 'TRANSFORM_GGT_gizmo'. */ +static void TRANSFORM_OT_from_gizmo(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Transform From Gizmo"; + ot->description = "Transform selected items by mode type"; + ot->idname = "TRANSFORM_OT_from_gizmo"; + ot->flag = 0; + + /* api callbacks */ + ot->invoke = transform_from_gizmo_invoke; +} + void transform_operatortypes(void) { TransformModeItem *tmode; @@ -1223,6 +1277,8 @@ void transform_operatortypes(void) WM_operatortype_append(TRANSFORM_OT_select_orientation); WM_operatortype_append(TRANSFORM_OT_create_orientation); WM_operatortype_append(TRANSFORM_OT_delete_orientation); + + WM_operatortype_append(TRANSFORM_OT_from_gizmo); } void ED_keymap_transform(wmKeyConfig *keyconf) diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index 49b5cada04a..ccbe12b4a93 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -569,7 +569,7 @@ static const EnumPropertyItem *rna_undo_itemf(bContext *C, int *totitem) item_tmp.identifier = us->name; item_tmp.name = IFACE_(us->name); if (us == wm->undo_stack->step_active) { - item_tmp.icon = ICON_HIDE_OFF; + item_tmp.icon = ICON_LAYER_ACTIVE; } else { item_tmp.icon = ICON_NONE; diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index 0564cb07897..c09237d825d 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -41,6 +41,7 @@ set(SRC ed_util.c gizmo_utils.c numinput.c + select_buffer_utils.c select_utils.c # general includes @@ -79,6 +80,7 @@ set(SRC ../include/ED_screen.h ../include/ED_screen_types.h ../include/ED_sculpt.h + ../include/ED_select_buffer_utils.h ../include/ED_select_utils.h ../include/ED_sequencer.h ../include/ED_sound.h diff --git a/source/blender/editors/util/select_buffer_utils.c b/source/blender/editors/util/select_buffer_utils.c new file mode 100644 index 00000000000..130f6819e34 --- /dev/null +++ b/source/blender/editors/util/select_buffer_utils.c @@ -0,0 +1,303 @@ +/* + * 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. + */ + +/** \file + * \ingroup edutil + * + * Generic utilities for handling buffer selection where selection ID's are drawn onto + * an off screen buffer. + * + * All coordinates are relative to the current region. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_bitmap.h" +#include "BLI_bitmap_draw_2d.h" +#include "BLI_rect.h" +#include "BLI_utildefines.h" + +#include "ED_select_buffer_utils.h" + +/* Only for #ED_view3d_select_id_read, + * note that this file shouldn't have 3D view specific logic in it, we could have a more general + * way to read from selection buffers that doesn't depend on the view3d API. */ +#include "ED_view3d.h" + +/* -------------------------------------------------------------------- */ +/** \name Select Bitmap from ID's + * + * Given a buffer of select ID's, fill in a booleans (true/false) per index. + * #BLI_bitmap is used for memory effeciency. + * + * \{ */ + +/** + * \param bitmap_len: Number of indices in the selection id buffer. + * \param rect: The rectangle to sample indices from (min/max inclusive). + * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. + */ +uint *ED_select_buffer_bitmap_from_rect(const uint bitmap_len, const rcti *rect) +{ + uint buf_len; + const uint *buf = ED_view3d_select_id_read( + rect->xmin, rect->ymin, rect->xmax, rect->ymax, &buf_len); + if (buf == NULL) { + return NULL; + } + + const uint *buf_iter = buf; + + BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); + + while (buf_len--) { + const uint index = *buf_iter - 1; + if (index < bitmap_len) { + BLI_BITMAP_ENABLE(bitmap_buf, index); + } + buf_iter++; + } + MEM_freeN((void *)buf); + return bitmap_buf; +} + +/** + * \param bitmap_len: Number of indices in the selection id buffer. + * \param center: Circle center. + * \param radius: Circle radius. + * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. + */ +uint *ED_select_buffer_bitmap_from_circle(const uint bitmap_len, + const int center[2], + const int radius) +{ + if (bitmap_len == 0) { + return NULL; + } + + const int xmin = center[0] - radius; + const int xmax = center[0] + radius; + const int ymin = center[1] - radius; + const int ymax = center[1] + radius; + + const uint *buf = ED_view3d_select_id_read(xmin, ymin, xmax, ymax, NULL); + if (buf == NULL) { + return NULL; + } + + const uint *buf_iter = buf; + + BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); + const int radius_sq = radius * radius; + for (int yc = -radius; yc <= radius; yc++) { + for (int xc = -radius; xc <= radius; xc++, buf_iter++) { + if (xc * xc + yc * yc < radius_sq) { + /* Intentionally wrap to max value if this is zero. */ + const uint index = *buf_iter - 1; + if (index < bitmap_len) { + BLI_BITMAP_ENABLE(bitmap_buf, index); + } + } + } + } + MEM_freeN((void *)buf); + return bitmap_buf; +} + +struct PolyMaskData { + BLI_bitmap *px; + int width; +}; + +static void ed_select_buffer_mask_px_cb(int x, int x_end, int y, void *user_data) +{ + struct PolyMaskData *data = user_data; + BLI_bitmap *px = data->px; + int i = (y * data->width) + x; + do { + BLI_BITMAP_ENABLE(px, i); + i++; + } while (++x != x_end); +} + +/** + * \param bitmap_len: Number of indices in the selection id buffer. + * \param center: Circle center. + * \param radius: Circle radius. + * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure. + */ +uint *ED_select_buffer_bitmap_from_poly(const uint bitmap_len, + const int poly[][2], + const int poly_len, + const rcti *rect) + +{ + if (bitmap_len == 0) { + return NULL; + } + + struct PolyMaskData poly_mask_data; + uint buf_len; + const uint *buf = ED_view3d_select_id_read( + rect->xmin, rect->ymin, rect->xmax, rect->ymax, &buf_len); + if (buf == NULL) { + return NULL; + } + + BLI_bitmap *buf_mask = BLI_BITMAP_NEW(buf_len, __func__); + poly_mask_data.px = buf_mask; + poly_mask_data.width = (rect->xmax - rect->xmin) + 1; + + BLI_bitmap_draw_2d_poly_v2i_n(rect->xmin, + rect->ymin, + rect->xmax + 1, + rect->ymax + 1, + poly, + poly_len, + ed_select_buffer_mask_px_cb, + &poly_mask_data); + + /* Build selection lookup. */ + const uint *buf_iter = buf; + BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__); + int i = 0; + while (buf_len--) { + const uint index = *buf_iter - 1; + if (index < bitmap_len && BLI_BITMAP_TEST(buf_mask, i)) { + BLI_BITMAP_ENABLE(bitmap_buf, index); + } + buf_iter++; + i++; + } + MEM_freeN((void *)buf); + MEM_freeN(buf_mask); + + return bitmap_buf; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Find Single Select ID's + * + * Given a buffer of select ID's, find the a single select id. + * + * \{ */ + +/** + * Samples a single pixel. + */ +uint ED_select_buffer_sample_point(const int center[2]) +{ + uint buf_len; + uint *buf = ED_view3d_select_id_read(center[0], center[1], center[0], center[1], &buf_len); + BLI_assert(0 != buf_len); + uint ret = buf[0]; + MEM_freeN(buf); + return ret; +} + +/** + * Find the selection id closest to \a center. + * \param dist[in,out]: Use to initalize the distance, + * when found, this value is set to the distance of the selection thats returned. + */ +uint ED_select_buffer_find_nearest_to_point(const int center[2], + const uint id_min, + const uint id_max, + uint *dist) +{ + /* Smart function to sample a rect spiralling outside, nice for selection ID. */ + + /* Create region around center (typically the mouse cursor). + * This must be square and have an odd width, + * the spiraling algorithm does not work with arbitrary rectangles. */ + rcti rect; + BLI_rcti_init_pt_radius(&rect, center, *dist); + rect.xmax += 1; + rect.ymax += 1; + + int width = BLI_rcti_size_x(&rect); + int height = width; + BLI_assert(width == height); + + /* Read from selection framebuffer. */ + + uint buf_len; + const uint *buf = ED_view3d_select_id_read_rect(&rect, &buf_len); + BLI_assert(width * height == buf_len); + + /* Spiral, starting from center of buffer. */ + int spiral_offset = height * (int)(width / 2) + (height / 2); + int spiral_direction = 0; + + uint index = 0; + + for (int nr = 1; nr <= height; nr++) { + for (int a = 0; a < 2; a++) { + for (int b = 0; b < nr; b++) { + /* Find hit within the specified range. */ + uint hit_id = buf[spiral_offset]; + + if (hit_id && hit_id >= id_min && hit_id < id_max) { + /* Get x/y from spiral offset. */ + int hit_x = spiral_offset % width; + int hit_y = spiral_offset / width; + + int center_x = width / 2; + int center_y = height / 2; + + /* Manhatten distance in keeping with other screen-based selection. */ + *dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y)); + + /* Indices start at 1 here. */ + index = (hit_id - id_min) + 1; + goto exit; + } + + /* Next spiral step. */ + if (spiral_direction == 0) { + spiral_offset += 1; /* right */ + } + else if (spiral_direction == 1) { + spiral_offset -= width; /* down */ + } + else if (spiral_direction == 2) { + spiral_offset -= 1; /* left */ + } + else { + spiral_offset += width; /* up */ + } + + /* Stop if we are outside the buffer. */ + if (spiral_offset < 0 || spiral_offset >= buf_len) { + goto exit; + } + } + + spiral_direction = (spiral_direction + 1) % 4; + } + } + +exit: + MEM_freeN((void *)buf); + return index; +} + +/** \} */ diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 3a5aead3d44..7f9b90f4496 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -246,6 +246,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) bool prev_ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1)); GPU_matrix_bind(geom->interface); + GPU_batch_bind(geom); /* TODO(fclem): If drawcall count becomes a problem in the future * we can use multi draw indirect drawcalls for this. @@ -254,7 +255,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) bool ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1)); if (ma_match != prev_ma_match) { if (ma_match == false) { - GPU_batch_draw_range_ex(geom, draw_start, idx - draw_start, false); + GPU_batch_draw_advanced(geom, draw_start, idx - draw_start, 0, 0); } else { draw_start = idx; @@ -264,7 +265,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph) prev_ma_match = ma_match; } if (prev_ma_match == true) { - GPU_batch_draw_range_ex(geom, draw_start, idx - draw_start, false); + GPU_batch_draw_advanced(geom, draw_start, idx - draw_start, 0, 0); } GPU_batch_program_use_end(geom); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index ee13583e67a..e9d81ef479b 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -99,7 +99,7 @@ NodeGroup *BlenderFileLoader::Load() continue; } - Mesh *mesh = BKE_object_to_mesh(ob); + Mesh *mesh = BKE_object_to_mesh(NULL, ob, false); if (mesh) { insertShapeNode(ob, mesh, ++id); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index dbd770eb5e8..8a3cdd575fe 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -263,6 +263,7 @@ Material *BlenderStrokeRenderer::GetStrokeShader(Main *bmain, } ma->nodetree = ntree; ma->use_nodes = 1; + ma->blend_method = MA_BM_HASHED; bNode *input_attr_color = nodeAddStaticNode(NULL, ntree, SH_NODE_ATTRIBUTE); input_attr_color->locx = 0.0f; diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index 783bfb0b1f0..5b0cab220c0 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -132,7 +132,7 @@ void GPU_batch_program_set_builtin_with_config(GPUBatch *batch, void GPU_batch_program_use_begin(GPUBatch *); /* call before Batch_Uniform (temp hack?) */ void GPU_batch_program_use_end(GPUBatch *); -void GPU_batch_uniform_1ui(GPUBatch *, const char *name, int value); +void GPU_batch_uniform_1ui(GPUBatch *, const char *name, uint value); void GPU_batch_uniform_1i(GPUBatch *, const char *name, int value); void GPU_batch_uniform_1b(GPUBatch *, const char *name, bool value); void GPU_batch_uniform_1f(GPUBatch *, const char *name, float value); @@ -142,14 +142,16 @@ void GPU_batch_uniform_4f(GPUBatch *, const char *name, float x, float y, float void GPU_batch_uniform_2fv(GPUBatch *, const char *name, const float data[2]); void GPU_batch_uniform_3fv(GPUBatch *, const char *name, const float data[3]); void GPU_batch_uniform_4fv(GPUBatch *, const char *name, const float data[4]); -void GPU_batch_uniform_2fv_array(GPUBatch *, const char *name, int len, const float *data); -void GPU_batch_uniform_4fv_array(GPUBatch *, const char *name, int len, const float *data); +void GPU_batch_uniform_2fv_array(GPUBatch *, const char *name, const int len, const float *data); +void GPU_batch_uniform_4fv_array(GPUBatch *, const char *name, const int len, const float *data); void GPU_batch_uniform_mat4(GPUBatch *, const char *name, const float data[4][4]); void GPU_batch_draw(GPUBatch *); +/* Needs to be called before GPU_batch_draw_advanced. */ +void GPU_batch_bind(GPUBatch *); /* This does not bind/unbind shader and does not call GPU_matrix_bind() */ -void GPU_batch_draw_range_ex(GPUBatch *, int v_first, int v_count, bool force_instance); +void GPU_batch_draw_advanced(GPUBatch *, int v_first, int v_count, int i_first, int i_count); /* Does not even need batch */ void GPU_draw_primitive(GPUPrimType, int v_count); diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h index fc7d9e22ea3..d3a9a18b392 100644 --- a/source/blender/gpu/GPU_shader_interface.h +++ b/source/blender/gpu/GPU_shader_interface.h @@ -44,9 +44,9 @@ typedef enum { GPU_UNIFORM_PROJECTION_INV, /* mat4 ProjectionMatrixInverse */ GPU_UNIFORM_VIEWPROJECTION_INV, /* mat4 ViewProjectionMatrixInverse */ - GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */ - GPU_UNIFORM_CAMERATEXCO, /* vec4 CameraTexCoFactors */ - GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */ + GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */ + GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */ + GPU_UNIFORM_CLIPPLANES, /* vec4 WorldClipPlanes[] */ GPU_UNIFORM_COLOR, /* vec4 color */ GPU_UNIFORM_CALLID, /* int callId */ diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index e61cfe363df..e7600279d6f 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -39,8 +39,10 @@ typedef struct GPUViewport GPUViewport; typedef struct ViewportMemoryPool { struct BLI_memblock *calls; struct BLI_memblock *states; + struct BLI_memblock *cullstates; struct BLI_memblock *shgroups; struct BLI_memblock *uniforms; + struct BLI_memblock *views; struct BLI_memblock *passes; struct BLI_memblock *images; } ViewportMemoryPool; diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c index 45697befe50..d1cfd5c337d 100644 --- a/source/blender/gpu/intern/gpu_batch.c +++ b/source/blender/gpu/intern/gpu_batch.c @@ -56,7 +56,7 @@ void GPU_batch_vao_cache_clear(GPUBatch *batch) (GPUShaderInterface *)batch->dynamic_vaos.interfaces[i], batch); } } - MEM_freeN(batch->dynamic_vaos.interfaces); + MEM_freeN((void *)batch->dynamic_vaos.interfaces); MEM_freeN(batch->dynamic_vaos.vao_ids); } else { @@ -285,7 +285,7 @@ static GLuint batch_vao_get(GPUBatch *batch) /* Not enough place, realloc the array. */ i = batch->dynamic_vaos.count; batch->dynamic_vaos.count += GPU_BATCH_VAO_DYN_ALLOC_COUNT; - batch->dynamic_vaos.interfaces = MEM_recallocN(batch->dynamic_vaos.interfaces, + batch->dynamic_vaos.interfaces = MEM_recallocN((void *)batch->dynamic_vaos.interfaces, sizeof(GPUShaderInterface *) * batch->dynamic_vaos.count); batch->dynamic_vaos.vao_ids = MEM_recallocN(batch->dynamic_vaos.vao_ids, @@ -461,7 +461,7 @@ void GPU_batch_program_use_end(GPUBatch *batch) const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name); #endif -void GPU_batch_uniform_1ui(GPUBatch *batch, const char *name, int value) +void GPU_batch_uniform_1ui(GPUBatch *batch, const char *name, uint value) { GET_UNIFORM glUniform1ui(uniform->location, value); @@ -577,10 +577,14 @@ static void *elem_offset(const GPUIndexBuf *el, int v_first) else if (el->index_type == GPU_INDEX_U16) { return (GLushort *)0 + v_first; } - else { #endif - return (GLuint *)0 + v_first; - } + return (GLuint *)0 + v_first; +} + +/* Use when drawing with GPU_batch_draw_advanced */ +void GPU_batch_bind(GPUBatch *batch) +{ + glBindVertexArray(batch->vao_id); } void GPU_batch_draw(GPUBatch *batch) @@ -592,103 +596,76 @@ void GPU_batch_draw(GPUBatch *batch) GPU_batch_program_use_begin(batch); GPU_matrix_bind(batch->interface); // external call. - GPU_batch_draw_range_ex(batch, 0, 0, false); + GPU_batch_bind(batch); + GPU_batch_draw_advanced(batch, 0, 0, 0, 0); GPU_batch_program_use_end(batch); } -void GPU_batch_draw_range_ex(GPUBatch *batch, int v_first, int v_count, bool force_instance) +void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_first, int i_count) { #if TRUST_NO_ONE - assert(!(force_instance && (batch->inst == NULL)) || - v_count > 0); // we cannot infer length if force_instance + BLI_assert(batch->program_in_use); + /* TODO could assert that VAO is bound. */ #endif - const bool do_instance = (force_instance || batch->inst); - - // If using offset drawing, use the default VAO and redo bindings. - if (v_first != 0 && do_instance) { - glBindVertexArray(GPU_vao_default()); - batch_update_program_bindings(batch, v_first); + if (v_count == 0) { + v_count = (batch->elem) ? batch->elem->index_len : batch->verts[0]->vertex_len; } - else { - glBindVertexArray(batch->vao_id); + if (i_count == 0) { + i_count = (batch->inst) ? batch->inst->vertex_len : 1; } - if (do_instance) { - /* Infer length if vertex count is not given */ - if (v_count == 0) { - v_count = batch->inst->vertex_len; + if (!GLEW_ARB_base_instance) { + if (i_first > 0 && i_count > 0) { + /* If using offset drawing with instancing, we must + * use the default VAO and redo bindings. */ + glBindVertexArray(GPU_vao_default()); + batch_update_program_bindings(batch, i_first); } + else { + /* Previous call could have bind the default vao + * see above. */ + glBindVertexArray(batch->vao_id); + } + } - if (batch->elem) { - const GPUIndexBuf *el = batch->elem; - - if (el->use_prim_restart) { - primitive_restart_enable(el); - } + if (batch->elem) { + const GPUIndexBuf *el = batch->elem; #if GPU_TRACK_INDEX_RANGE - glDrawElementsInstancedBaseVertex( - batch->gl_prim_type, el->index_len, el->gl_index_type, 0, v_count, el->base_index); + GLenum index_type = el->gl_index_type; + GLint base_index = el->base_index; #else - glDrawElementsInstanced(batch->gl_prim_type, el->index_len, GL_UNSIGNED_INT, 0, v_count); + GLenum index_type = GL_UNSIGNED_INT; + GLint base_index = 0; #endif - if (el->use_prim_restart) { - primitive_restart_disable(); - } + void *v_first_ofs = elem_offset(el, v_first); + + if (el->use_prim_restart) { + primitive_restart_enable(el); + } + + if (GLEW_ARB_base_instance) { + glDrawElementsInstancedBaseVertexBaseInstance( + batch->gl_prim_type, v_count, index_type, v_first_ofs, i_count, base_index, i_first); } else { - glDrawArraysInstanced(batch->gl_prim_type, 0, batch->verts[0]->vertex_len, v_count); + glDrawElementsInstancedBaseVertex( + batch->gl_prim_type, v_count, index_type, v_first_ofs, i_count, base_index); + } + + if (el->use_prim_restart) { + primitive_restart_disable(); } } else { - /* Infer length if vertex count is not given */ - if (v_count == 0) { - v_count = (batch->elem) ? batch->elem->index_len : batch->verts[0]->vertex_len; - } - - if (batch->elem) { - const GPUIndexBuf *el = batch->elem; - - if (el->use_prim_restart) { - primitive_restart_enable(el); - } - - void *v_first_ofs = elem_offset(el, v_first); - -#if GPU_TRACK_INDEX_RANGE - if (el->base_index) { - glDrawRangeElementsBaseVertex(batch->gl_prim_type, - el->min_index, - el->max_index, - v_count, - el->gl_index_type, - v_first_ofs, - el->base_index); - } - else { - glDrawRangeElements(batch->gl_prim_type, - el->min_index, - el->max_index, - v_count, - el->gl_index_type, - v_first_ofs); - } -#else - glDrawElements(batch->gl_prim_type, v_count, GL_UNSIGNED_INT, v_first_ofs); -#endif - if (el->use_prim_restart) { - primitive_restart_disable(); - } + if (GLEW_ARB_base_instance) { + glDrawArraysInstancedBaseInstance(batch->gl_prim_type, v_first, v_count, i_count, i_first); } else { - glDrawArrays(batch->gl_prim_type, v_first, v_count); + glDrawArraysInstanced(batch->gl_prim_type, v_first, v_count, i_count); } } - - /* Performance hog if you are drawing with the same vao multiple time. - * Only activate for debugging. */ - // glBindVertexArray(0); } /* just draw some vertices and let shader place them where we want. */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 2220eef4034..638729d027c 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -757,7 +757,7 @@ void GPU_create_gl_tex_compressed(unsigned int *bind, int textarget, Image *ima, if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf, use_srgb) == 0) { glDeleteTextures(1, (GLuint *)bind); - GPU_create_gl_tex(bind, ibuf->rect, NULL, ibuf->x, ibuf->x, textarget, mipmap, use_srgb, ima); + GPU_create_gl_tex(bind, ibuf->rect, NULL, ibuf->x, ibuf->y, textarget, mipmap, use_srgb, ima); } glBindTexture(textarget, 0); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index fde60fd387d..007a13a06ef 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -620,7 +620,7 @@ void GPU_material_flag_set(GPUMaterial *mat, eGPUMatFlag flag) bool GPU_material_flag_get(GPUMaterial *mat, eGPUMatFlag flag) { - return (mat->flag & flag); + return (mat->flag & flag) != 0; } GPUMaterial *GPU_material_from_nodetree_find(ListBase *gpumaterials, @@ -684,7 +684,10 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene, if (mat->outlink) { /* HACK: this is only for eevee. We add the define here after the nodetree evaluation. */ if (GPU_material_flag_get(mat, GPU_MATFLAG_SSS)) { - defines = BLI_string_joinN(defines, "#define USE_SSS\n"); + defines = BLI_string_joinN(defines, + "#ifndef USE_ALPHA_BLEND\n" + "# define USE_SSS\n" + "#endif\n"); } /* Prune the unused nodes and extract attributes before compiling so the * generated VBOs are ready to accept the future shader. */ diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c index 010087e5536..119aed2f5ed 100644 --- a/source/blender/gpu/intern/gpu_select.c +++ b/source/blender/gpu/intern/gpu_select.c @@ -229,12 +229,18 @@ void GPU_select_buffer_stride_realign(const rcti *src, const rcti *dst, uint *r_ const int dst_x = BLI_rcti_size_x(dst); const int dst_y = BLI_rcti_size_y(dst); - int last_px_written = dst_x * dst_y - 1; int last_px_id = src_x * (y + dst_y - 1) + (x + dst_x - 1); - const int skip = src_x - dst_x; - memset(&r_buf[last_px_id + 1], 0, (src_x * src_y - (last_px_id + 1)) * sizeof(*r_buf)); + if (last_px_id < 0) { + /* Nothing to write. */ + BLI_assert(last_px_id == -1); + return; + } + + int last_px_written = dst_x * dst_y - 1; + const int skip = src_x - dst_x; + while (true) { for (int i = dst_x; i--;) { r_buf[last_px_id--] = r_buf[last_px_written--]; diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c index 97dbb80d736..e7483e45312 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.c +++ b/source/blender/gpu/intern/gpu_shader_interface.c @@ -61,8 +61,8 @@ static const char *BuiltinUniform_name(GPUUniformBuiltin u) [GPU_UNIFORM_VIEWPROJECTION_INV] = "ViewProjectionMatrixInverse", [GPU_UNIFORM_NORMAL] = "NormalMatrix", - [GPU_UNIFORM_CAMERATEXCO] = "CameraTexCoFactors", [GPU_UNIFORM_ORCO] = "OrcoTexCoFactors", + [GPU_UNIFORM_CLIPPLANES] = "WorldClipPlanes", [GPU_UNIFORM_COLOR] = "color", [GPU_UNIFORM_CALLID] = "callId", diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index b825819ceb4..4fd439f4203 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -625,12 +625,18 @@ void GPU_viewport_free(GPUViewport *viewport) if (viewport->vmempool.states != NULL) { BLI_memblock_destroy(viewport->vmempool.states, NULL); } + if (viewport->vmempool.cullstates != NULL) { + BLI_memblock_destroy(viewport->vmempool.cullstates, NULL); + } if (viewport->vmempool.shgroups != NULL) { BLI_memblock_destroy(viewport->vmempool.shgroups, NULL); } if (viewport->vmempool.uniforms != NULL) { BLI_memblock_destroy(viewport->vmempool.uniforms, NULL); } + if (viewport->vmempool.views != NULL) { + BLI_memblock_destroy(viewport->vmempool.views, NULL); + } if (viewport->vmempool.passes != NULL) { BLI_memblock_destroy(viewport->vmempool.passes, NULL); } diff --git a/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl b/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl index e34b86ac1ce..46cf2fe09a2 100644 --- a/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl +++ b/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl @@ -1,15 +1,24 @@ #ifdef USE_WORLD_CLIP_PLANES # if defined(GPU_VERTEX_SHADER) || defined(GPU_GEOMETRY_SHADER) + uniform vec4 WorldClipPlanes[6]; -void world_clip_planes_calc_clip_distance(vec3 wpos) -{ - gl_ClipDistance[0] = dot(WorldClipPlanes[0].xyz, wpos) + WorldClipPlanes[0].w; - gl_ClipDistance[1] = dot(WorldClipPlanes[1].xyz, wpos) + WorldClipPlanes[1].w; - gl_ClipDistance[2] = dot(WorldClipPlanes[2].xyz, wpos) + WorldClipPlanes[2].w; - gl_ClipDistance[3] = dot(WorldClipPlanes[3].xyz, wpos) + WorldClipPlanes[3].w; - gl_ClipDistance[4] = dot(WorldClipPlanes[4].xyz, wpos) + WorldClipPlanes[4].w; - gl_ClipDistance[5] = dot(WorldClipPlanes[5].xyz, wpos) + WorldClipPlanes[5].w; -} + +# define _world_clip_planes_calc_clip_distance(wpos, _clipplanes) \ + { \ + vec4 pos = vec4(wpos, 1.0); \ + gl_ClipDistance[0] = dot(_clipplanes[0], pos); \ + gl_ClipDistance[1] = dot(_clipplanes[1], pos); \ + gl_ClipDistance[2] = dot(_clipplanes[2], pos); \ + gl_ClipDistance[3] = dot(_clipplanes[3], pos); \ + gl_ClipDistance[4] = dot(_clipplanes[4], pos); \ + gl_ClipDistance[5] = dot(_clipplanes[5], pos); \ + } + +/* HACK Dirty hack to be able to override the definition in common_view_lib.glsl. + * Not doing this would require changing the include order in every shaders. */ +# define world_clip_planes_calc_clip_distance(wpos) \ + _world_clip_planes_calc_clip_distance(wpos, WorldClipPlanes) + # endif # define world_clip_planes_set_clip_distance(c) \ diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index f8df14cf317..8574f33bce6 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -476,13 +476,11 @@ int imb_get_anim_type(const char *name); */ bool IMB_isfloat(struct ImBuf *ibuf); +/* Do byte/float and colorspace conversions need to take alpha into account? */ +bool IMB_alpha_affects_rgb(const struct ImBuf *ibuf); + /* create char buffer, color corrected if necessary, for ImBufs that lack one */ void IMB_rect_from_float(struct ImBuf *ibuf); -/* Create char buffer for part of the image, color corrected if necessary, - * Changed part will be stored in buffer. - * This is expected to be used for texture painting updates */ -void IMB_partial_rect_from_float( - struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h, bool is_data); void IMB_float_from_rect(struct ImBuf *ibuf); void IMB_color_to_bw(struct ImBuf *ibuf); void IMB_saturation(struct ImBuf *ibuf, float sat); @@ -555,7 +553,6 @@ void IMB_buffer_byte_from_byte(unsigned char *rect_to, int height, int stride_to, int stride_from); -void IMB_buffer_float_clamp(float *buf, int width, int height); void IMB_buffer_float_unpremultiply(float *buf, int width, int height); void IMB_buffer_float_premultiply(float *buf, int width, int height); diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 0f2529e261a..61aa1f401a0 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -285,10 +285,12 @@ enum { IB_alphamode_premul = 1 << 12, /** if this flag is set, alpha mode would be guessed from file */ IB_alphamode_detect = 1 << 13, + /* alpha channel is unrelated to RGB and should not affect it */ + IB_alphamode_channel_packed = 1 << 14, /** ignore alpha on load and substitute it with 1.0f */ - IB_ignore_alpha = 1 << 14, - IB_thumbnail = 1 << 15, - IB_multiview = 1 << 16, + IB_alphamode_ignore = 1 << 15, + IB_thumbnail = 1 << 16, + IB_multiview = 1 << 17, }; /** \} */ diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index ba0f10446a1..583a3be8168 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -747,6 +747,16 @@ void colormanagement_exit(void) /*********************** Internal functions *************************/ +static bool colormanage_compatible_look(ColorManagedLook *look, const char *view_name) +{ + if (look->is_noop) { + return true; + } + + /* Skip looks only relevant to specific view transforms. */ + return (look->view[0] == 0 || (view_name && STREQ(look->view, view_name))); +} + void colormanage_cache_free(ImBuf *ibuf) { if (ibuf->display_buffer_flags) { @@ -840,7 +850,7 @@ static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *loo OCIO_displayTransformSetView(dt, view_transform); OCIO_displayTransformSetDisplay(dt, display); - if (look_descr->is_noop == false) { + if (look_descr->is_noop == false && colormanage_compatible_look(look_descr, view_transform)) { OCIO_displayTransformSetLooksOverrideEnabled(dt, true); OCIO_displayTransformSetLooksOverride(dt, look); } @@ -989,9 +999,9 @@ static OCIO_ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedD void IMB_colormanagement_init_default_view_settings( ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { - /* First, try use "Default" view transform of the requested device. */ + /* First, try use "Standard" view transform of the requested device. */ ColorManagedView *default_view = colormanage_view_get_named_for_display( - display_settings->display_device, "Default"); + display_settings->display_device, "Standard"); /* If that fails, we fall back to the default view transform of the display * as per OCIO configuration. */ if (default_view == NULL) { @@ -1057,13 +1067,19 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) if (ibuf->rect_float) { const char *to_colorspace = global_role_scene_linear; + const bool predivide = IMB_alpha_affects_rgb(ibuf); if (ibuf->rect) { imb_freerectImBuf(ibuf); } - IMB_colormanagement_transform( - ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, true); + IMB_colormanagement_transform(ibuf->rect_float, + ibuf->x, + ibuf->y, + ibuf->channels, + from_colorspace, + to_colorspace, + predivide); } } @@ -1405,6 +1421,7 @@ typedef struct DisplayBufferThread { int channels; float dither; bool is_data; + bool predivide; const char *byte_colorspace; const char *float_colorspace; @@ -1469,6 +1486,7 @@ static void display_buffer_init_handle(void *handle_v, handle->channels = channels; handle->dither = dither; handle->is_data = is_data; + handle->predivide = IMB_alpha_affects_rgb(ibuf); handle->byte_colorspace = init_data->byte_colorspace; handle->float_colorspace = init_data->float_colorspace; @@ -1486,6 +1504,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, bool is_data = handle->is_data; bool is_data_display = handle->cm_processor->is_data_result; + bool predivide = handle->predivide; if (!handle->buffer) { unsigned char *byte_buffer = handle->byte_buffer; @@ -1534,7 +1553,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, if (!is_data && !is_data_display) { IMB_colormanagement_transform( - linear_buffer, width, height, channels, from_colorspace, to_colorspace, true); + linear_buffer, width, height, channels, from_colorspace, to_colorspace, predivide); } *is_straight_alpha = false; @@ -1590,13 +1609,13 @@ static void *do_display_buffer_apply_thread(void *handle_v) } } else { - bool is_straight_alpha, predivide; + bool is_straight_alpha; float *linear_buffer = MEM_mallocN(((size_t)channels) * width * height * sizeof(float), "color conversion linear buffer"); display_buffer_apply_get_linear_buffer(handle, height, linear_buffer, &is_straight_alpha); - predivide = is_straight_alpha == false; + bool predivide = handle->predivide && (is_straight_alpha == false); if (is_data) { /* special case for data buffers - no color space conversions, @@ -2178,6 +2197,7 @@ void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer, /* TODO(brecht): make this multithreaded, or at least process in batches. */ const unsigned char *in_buffer = (unsigned char *)ibuf->rect; + const bool use_premultiply = IMB_alpha_affects_rgb(ibuf); for (int y = 0; y < height; y++) { const size_t in_offset = (offset_y + y) * ibuf->x + offset_x; @@ -2192,11 +2212,13 @@ void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer, rgba_uchar_to_float(pixel, in); OCIO_processorApplyRGB(processor, pixel); linearrgb_to_srgb_v3_v3(pixel, pixel); - mul_v3_fl(pixel, pixel[3]); + if (use_premultiply) { + mul_v3_fl(pixel, pixel[3]); + } rgba_float_to_uchar(out, pixel); } } - else { + else if (use_premultiply) { /* Premultiply only. */ for (int x = 0; x < width; x++, in += 4, out += 4) { out[0] = (in[0] * in[3]) >> 8; @@ -2205,6 +2227,15 @@ void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer, out[3] = in[3]; } } + else { + /* Copy only. */ + for (int x = 0; x < width; x++, in += 4, out += 4) { + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + } + } } } @@ -3194,17 +3225,9 @@ void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, const char *view_name) { ColorManagedLook *look; - const char *view_filter = NULL; - - /* Test if this view transform is limited to specific looks. */ - for (look = global_looks.first; look; look = look->next) { - if (STREQ(look->view, view_name)) { - view_filter = view_name; - } - } for (look = global_looks.first; look; look = look->next) { - if (!look->is_noop && view_filter && !STREQ(look->view, view_filter)) { + if (!colormanage_compatible_look(look, view_name)) { continue; } diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index e4845e56c46..aa49453d68c 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -96,6 +96,12 @@ MINLINE void float_to_byte_dither_v4( b[3] = unit_float_to_uchar_clamp(f[3]); } +/* Test if colorspace conversions of pixels in buffer need to take into account alpha. */ +bool IMB_alpha_affects_rgb(const ImBuf *ibuf) +{ + return (ibuf->flags & IB_alphamode_channel_packed) == 0; +} + /* float to byte pixels, output 4-channel RGBA */ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, @@ -728,16 +734,19 @@ void IMB_rect_from_float(ImBuf *ibuf) buffer = MEM_dupallocN(ibuf->rect_float); /* first make float buffer in byte space */ + const bool predivide = IMB_alpha_affects_rgb(ibuf); IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, - true); + predivide); /* convert from float's premul alpha to byte's straight alpha */ - IMB_unpremultiply_rect_float(buffer, ibuf->channels, ibuf->x, ibuf->y); + if (IMB_alpha_affects_rgb(ibuf)) { + IMB_unpremultiply_rect_float(buffer, ibuf->channels, ibuf->x, ibuf->y); + } /* convert float to byte */ IMB_buffer_byte_from_float((unsigned char *)ibuf->rect, @@ -758,118 +767,6 @@ void IMB_rect_from_float(ImBuf *ibuf) ibuf->userflags &= ~IB_RECT_INVALID; } -typedef struct PartialThreadData { - ImBuf *ibuf; - float *buffer; - uchar *rect_byte; - const float *rect_float; - int width; - bool is_data; -} PartialThreadData; - -static void partial_rect_from_float_slice(float *buffer, - uchar *rect_byte, - ImBuf *ibuf, - const float *rect_float, - const int w, - const int h, - const bool is_data) -{ - const int profile_from = IB_PROFILE_LINEAR_RGB; - if (is_data) { - /* exception for non-color data, just copy float */ - IMB_buffer_float_from_float(buffer, - rect_float, - ibuf->channels, - IB_PROFILE_LINEAR_RGB, - IB_PROFILE_LINEAR_RGB, - 0, - w, - h, - w, - ibuf->x); - - /* and do color space conversion to byte */ - IMB_buffer_byte_from_float(rect_byte, - rect_float, - 4, - ibuf->dither, - IB_PROFILE_SRGB, - profile_from, - true, - w, - h, - ibuf->x, - w); - } - else { - IMB_buffer_float_from_float( - buffer, rect_float, ibuf->channels, IB_PROFILE_SRGB, profile_from, true, w, h, w, ibuf->x); - - IMB_buffer_float_unpremultiply(buffer, w, h); - /* XXX: need to convert to image buffer's rect space */ - IMB_buffer_byte_from_float( - rect_byte, buffer, 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, w, h, ibuf->x, w); - } -} - -static void partial_rect_from_float_thread_do(void *data_v, int start_scanline, int num_scanlines) -{ - PartialThreadData *data = (PartialThreadData *)data_v; - ImBuf *ibuf = data->ibuf; - size_t global_offset = ((size_t)ibuf->x) * start_scanline; - size_t local_offset = ((size_t)data->width) * start_scanline; - partial_rect_from_float_slice(data->buffer + local_offset * ibuf->channels, - data->rect_byte + global_offset * 4, - ibuf, - data->rect_float + global_offset * ibuf->channels, - data->width, - num_scanlines, - data->is_data); -} - -/** - * Converts from linear float to sRGB byte for part of the texture, - * buffer will hold the changed part. - */ -void IMB_partial_rect_from_float( - ImBuf *ibuf, float *buffer, int x, int y, int w, int h, bool is_data) -{ - const float *rect_float; - uchar *rect_byte; - - /* verify we have a float buffer */ - if (ibuf->rect_float == NULL || buffer == NULL) { - return; - } - - /* create byte rect if it didn't exist yet */ - if (ibuf->rect == NULL) { - imb_addrectImBuf(ibuf); - } - - /* do conversion */ - rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels; - rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4; - - if (((size_t)w) * h < 64 * 64) { - partial_rect_from_float_slice(buffer, rect_byte, ibuf, rect_float, w, h, is_data); - } - else { - PartialThreadData data; - data.ibuf = ibuf; - data.buffer = buffer; - data.rect_byte = rect_byte; - data.rect_float = rect_float; - data.width = w; - data.is_data = is_data; - IMB_processor_apply_threaded_scanlines(h, partial_rect_from_float_thread_do, &data); - } - - /* ensure user flag is reset */ - ibuf->userflags &= ~IB_RECT_INVALID; -} - void IMB_float_from_rect(ImBuf *ibuf) { float *rect_float; @@ -914,7 +811,9 @@ void IMB_float_from_rect(ImBuf *ibuf) rect_float, ibuf->x, ibuf->y, ibuf->channels, ibuf->rect_colorspace, false); /* byte buffer is straight alpha, float should always be premul */ - IMB_premultiply_rect_float(rect_float, ibuf->channels, ibuf->x, ibuf->y); + if (IMB_alpha_affects_rgb(ibuf)) { + IMB_premultiply_rect_float(rect_float, ibuf->channels, ibuf->x, ibuf->y); + } if (ibuf->rect_float == NULL) { ibuf->rect_float = rect_float; @@ -945,14 +844,6 @@ void IMB_color_to_bw(ImBuf *ibuf) } } -void IMB_buffer_float_clamp(float *buf, int width, int height) -{ - size_t i, total = ((size_t)width) * height * 4; - for (i = 0; i < total; i++) { - buf[i] = min_ff(1.0, buf[i]); - } -} - void IMB_buffer_float_unpremultiply(float *buf, int width, int height) { size_t total = ((size_t)width) * height; diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp index 32079e4f290..7a47d0f7787 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp +++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp @@ -25,6 +25,7 @@ #if defined(WIN32) # include "utfconv.h" +# define _USE_MATH_DEFINES #endif // NOTE: Keep first, BLI_path_util conflicts with OIIO's format. diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index e1df5c63093..d9f3c7ec6bb 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -49,8 +49,6 @@ static void imb_handle_alpha(ImBuf *ibuf, char colorspace[IM_MAX_SPACE], char effective_colorspace[IM_MAX_SPACE]) { - int alpha_flags; - if (colorspace) { if (ibuf->rect != NULL && ibuf->rect_float == NULL) { /* byte buffer is never internally converted to some standard space, @@ -62,15 +60,17 @@ static void imb_handle_alpha(ImBuf *ibuf, BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE); } - if (flags & IB_alphamode_detect) { - alpha_flags = ibuf->flags & IB_alphamode_premul; - } - else { - alpha_flags = flags & IB_alphamode_premul; - } + bool is_data = (colorspace && IMB_colormanagement_space_name_is_data(colorspace)); + int alpha_flags = (flags & IB_alphamode_detect) ? ibuf->flags : flags; - if (flags & IB_ignore_alpha) { + if (is_data || (flags & IB_alphamode_channel_packed)) { + /* Don't touch alpha. */ + ibuf->flags |= IB_alphamode_channel_packed; + } + else if (flags & IB_alphamode_ignore) { + /* Make opaque. */ IMB_rectfill_alpha(ibuf, 1.0f); + ibuf->flags |= IB_alphamode_ignore; } else { if (alpha_flags & IB_alphamode_premul) { diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h index 6a9d50ecc2d..dc4f5512b1a 100644 --- a/source/blender/makesdna/DNA_genfile.h +++ b/source/blender/makesdna/DNA_genfile.h @@ -121,4 +121,15 @@ bool DNA_sdna_patch_struct_member(struct SDNA *sdna, void DNA_sdna_alias_data_ensure(struct SDNA *sdna); +/* Alias lookups (using runtime struct member names). */ +int DNA_struct_alias_find_nr_ex(const struct SDNA *sdna, + const char *str, + unsigned int *index_last); +int DNA_struct_alias_find_nr(const struct SDNA *sdna, const char *str); +bool DNA_struct_alias_elem_find(const struct SDNA *sdna, + const char *stype, + const char *vartype, + const char *name); +void DNA_sdna_alias_data_ensure_structs_map(struct SDNA *sdna); + #endif /* __DNA_GENFILE_H__ */ diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 3e42aa17492..6141472125f 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -178,7 +178,7 @@ enum { /** For image user, but these flags are mixed. */ IMA_USER_FRAME_IN_RANGE = (1 << 10), IMA_VIEW_AS_RENDER = (1 << 11), - IMA_IGNORE_ALPHA = (1 << 12), + IMA_FLAG_UNUSED_12 = (1 << 12), /* cleared */ IMA_DEINTERLACE = (1 << 13), IMA_USE_VIEWS = (1 << 14), IMA_FLAG_UNUSED_15 = (1 << 15), /* cleared */ @@ -233,6 +233,8 @@ enum { enum { IMA_ALPHA_STRAIGHT = 0, IMA_ALPHA_PREMUL = 1, + IMA_ALPHA_CHANNEL_PACKED = 2, + IMA_ALPHA_IGNORE = 3, }; #endif diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 3890fc63f3f..342641f00ac 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -161,8 +161,8 @@ typedef enum eNodeSocketDrawShape { /* socket side (input/output) */ typedef enum eNodeSocketInOut { - SOCK_IN = 1, - SOCK_OUT = 2, + SOCK_IN = 1 << 0, + SOCK_OUT = 1 << 1, } eNodeSocketInOut; /* sock->flag, first bit is select */ diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 4287017543b..9bbb6f1656c 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -43,8 +43,8 @@ struct DerivedMesh; struct FluidsimSettings; struct GpencilBatchCache; struct Ipo; -struct Mesh; struct Material; +struct Mesh; struct Object; struct PartDeflect; struct ParticleSystem; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 61fcb0c87d3..6813bc0e3aa 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1443,8 +1443,9 @@ typedef struct ToolSettings { /* Multires */ char multires_subdiv_type; - /* Alt+RMB option */ + /* Edge tagging, store operator settings (no UI access). */ char edge_mode; + char edge_mode_live_unwrap; char _pad1[1]; @@ -1499,7 +1500,7 @@ typedef struct ToolSettings { /* Normal Editing */ float normal_vector[3]; - int face_strength; + char _pad6[4]; } ToolSettings; /* *************************************************************** */ @@ -2158,13 +2159,6 @@ enum { OB_DRAW_GROUPUSER_ALL = 2, }; -/* toolsettings->face_strength */ -enum { - FACE_STRENGTH_WEAK = -16384, - FACE_STRENGTH_MEDIUM = 0, - FACE_STRENGTH_STRONG = 16384, -}; - /* object_vgroup.c */ /* ToolSettings.vgroupsubset */ typedef enum eVGroupSelect { @@ -2316,14 +2310,6 @@ enum { #define UV_SELECT_FACE 4 #define UV_SELECT_ISLAND 8 -/* ToolSettings.edge_mode */ -#define EDGE_MODE_SELECT 0 -#define EDGE_MODE_TAG_SEAM 1 -#define EDGE_MODE_TAG_SHARP 2 -#define EDGE_MODE_TAG_CREASE 3 -#define EDGE_MODE_TAG_BEVEL 4 -#define EDGE_MODE_TAG_FREESTYLE 5 - /* ToolSettings.gpencil_flags */ typedef enum eGPencil_Flags { /* When creating new frames, the last frame gets used as the basis for the new one */ diff --git a/source/blender/makesdna/DNA_sdna_types.h b/source/blender/makesdna/DNA_sdna_types.h index 01e74da4e3b..efa7a308f88 100644 --- a/source/blender/makesdna/DNA_sdna_types.h +++ b/source/blender/makesdna/DNA_sdna_types.h @@ -35,7 +35,7 @@ typedef struct SDNA { bool data_alloc; /** Total number of struct members. */ - int nr_names, nr_names_alloc; + int names_len, names_len_alloc; /** Struct member names. */ const char **names; /** Result of #DNA_elem_array_size (aligned with #names). */ @@ -44,15 +44,14 @@ typedef struct SDNA { /** Size of a pointer in bytes. */ int pointer_size; - /** Number of basic types + struct types. */ - int nr_types; /** Type names. */ const char **types; + /** Number of basic types + struct types. */ + int types_len; + /** Type lengths. */ short *types_size; - /** Number of struct types. */ - int nr_structs; /** * sp = structs[a] is the address of a struct definition * sp[0] is struct type number, sp[1] amount of members @@ -61,6 +60,8 @@ typedef struct SDNA { * type and name numbers respectively. */ short **structs; + /** Number of struct types. */ + int structs_len; /** #GHash for faster lookups, requires WITH_DNA_GHASH to be used for now. */ struct GHash *structs_map; @@ -74,6 +75,8 @@ typedef struct SDNA { const char **names; /** Aligned with #SDNA.types, same pointers when unchanged. */ const char **types; + /** A version of #SDNA.structs_map that uses #SDNA.alias.types for it's keys. */ + struct GHash *structs_map; } alias; } SDNA; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 9cab63dbfeb..fa12de56364 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -283,7 +283,7 @@ 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 time_scrub_background[4]; char _pad5[4]; char nurb_uline[4], nurb_vline[4]; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index d5ac8cc197b..0170b27e15f 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -584,9 +584,8 @@ enum { /** Settings for offscreen rendering */ enum { V3D_OFSDRAW_NONE = (0), - V3D_OFSDRAW_USE_FULL_SAMPLE = (1 << 0), - V3D_OFSDRAW_SHOW_ANNOTATION = (1 << 1), - V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS = (1 << 2), + V3D_OFSDRAW_SHOW_ANNOTATION = (1 << 0), + V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS = (1 << 1), }; #define RV3D_CAMZOOM_MIN -30 diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index ad0765a58de..3cc005535b6 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -39,9 +39,7 @@ #include "BLI_memarena.h" #include "BLI_string.h" -#ifdef WITH_DNA_GHASH -# include "BLI_ghash.h" -#endif +#include "BLI_ghash.h" #include "DNA_genfile.h" #include "DNA_sdna_types.h" // for SDNA ;-) @@ -161,6 +159,11 @@ void DNA_sdna_free(SDNA *sdna) MEM_SAFE_FREE(sdna->alias.names); MEM_SAFE_FREE(sdna->alias.types); +#ifdef WITH_DNA_GHASH + if (sdna->alias.structs_map) { + BLI_ghash_free(sdna->alias.structs_map, NULL, NULL); + } +#endif MEM_freeN(sdna); } @@ -222,49 +225,86 @@ static void printstruct(SDNA *sdna, short strnr) /** * Returns the index of the struct info for the struct with the specified name. */ -int DNA_struct_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last) +static int dna_struct_find_nr_ex_impl( + /* From SDNA struct. */ + const char **types, + const int UNUSED(types_len), + short **const structs, + const int structs_len, +#ifdef WITH_DNA_GHASH + GHash *structs_map, +#endif + /* Regular args. */ + const char *str, + unsigned int *index_last) { - const short *sp = NULL; - - if (*index_last < sdna->nr_structs) { - sp = sdna->structs[*index_last]; - if (strcmp(sdna->types[sp[0]], str) == 0) { + if (*index_last < structs_len) { + const short *sp = structs[*index_last]; + if (STREQ(types[sp[0]], str)) { return *index_last; } } #ifdef WITH_DNA_GHASH { - void **index_p; - int a; - - index_p = BLI_ghash_lookup_p(sdna->structs_map, str); - + void **index_p = BLI_ghash_lookup_p(structs_map, str); if (index_p) { - a = POINTER_AS_INT(*index_p); - *index_last = a; - } - else { - a = -1; + const int index = POINTER_AS_INT(*index_p); + *index_last = index; + return index; } - return a; } #else { - int a; - - for (a = 0; a < sdna->nr_structs; a++) { - - sp = sdna->structs[a]; - - if (strcmp(sdna->types[sp[0]], str) == 0) { - *index_last = a; - return a; + for (int index = 0; index < structs_len; index++) { + const short *sp = structs[index]; + if (STREQ(types[sp[0]], str)) { + *index_last = index; + return index; } } } +#endif return -1; +} + +/** + * Returns the index of the struct info for the struct with the specified name. + */ +int DNA_struct_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last) +{ + return dna_struct_find_nr_ex_impl( + /* Expand SDNA. */ + sdna->types, + sdna->types_len, + sdna->structs, + sdna->structs_len, +#ifdef WITH_DNA_GHASH + sdna->structs_map, #endif + /* Regular args. */ + str, + index_last); +} + +/** \note requires #DNA_sdna_alias_data_ensure_structs_map to be called. */ +int DNA_struct_alias_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last) +{ +#ifdef WITH_DNA_GHASH + BLI_assert(sdna->alias.structs_map != NULL); +#endif + return dna_struct_find_nr_ex_impl( + /* Expand SDNA. */ + sdna->alias.types, + sdna->types_len, + sdna->structs, + sdna->structs_len, +#ifdef WITH_DNA_GHASH + sdna->alias.structs_map, +#endif + /* Regular args. */ + str, + index_last); } int DNA_struct_find_nr(const SDNA *sdna, const char *str) @@ -273,6 +313,13 @@ int DNA_struct_find_nr(const SDNA *sdna, const char *str) return DNA_struct_find_nr_ex(sdna, str, &index_last_dummy); } +/** \note requires #DNA_sdna_alias_data_ensure_structs_map to be called. */ +int DNA_struct_alias_find_nr(const SDNA *sdna, const char *str) +{ + unsigned int index_last_dummy = UINT_MAX; + return DNA_struct_alias_find_nr_ex(sdna, str, &index_last_dummy); +} + /* ************************* END DIV ********************** */ /* ************************* READ DNA ********************** */ @@ -317,14 +364,14 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error if (*data == MAKE_ID('N', 'A', 'M', 'E')) { data++; - sdna->nr_names = *data; + sdna->names_len = *data; if (do_endian_swap) { - BLI_endian_switch_int32(&sdna->nr_names); + BLI_endian_switch_int32(&sdna->names_len); } - sdna->nr_names_alloc = sdna->nr_names; + sdna->names_len_alloc = sdna->names_len; data++; - sdna->names = MEM_callocN(sizeof(void *) * sdna->nr_names, "sdnanames"); + sdna->names = MEM_callocN(sizeof(void *) * sdna->names_len, "sdnanames"); } else { *r_error_message = "NAME error in SDNA file"; @@ -332,7 +379,7 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error } cp = (char *)data; - for (int nr = 0; nr < sdna->nr_names; nr++) { + for (int nr = 0; nr < sdna->names_len; nr++) { sdna->names[nr] = cp; /* "float gravity [3]" was parsed wrong giving both "gravity" and @@ -357,13 +404,13 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error if (*data == MAKE_ID('T', 'Y', 'P', 'E')) { data++; - sdna->nr_types = *data; + sdna->types_len = *data; if (do_endian_swap) { - BLI_endian_switch_int32(&sdna->nr_types); + BLI_endian_switch_int32(&sdna->types_len); } data++; - sdna->types = MEM_callocN(sizeof(void *) * sdna->nr_types, "sdnatypes"); + sdna->types = MEM_callocN(sizeof(void *) * sdna->types_len, "sdnatypes"); } else { *r_error_message = "TYPE error in SDNA file"; @@ -371,7 +418,7 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error } cp = (char *)data; - for (int nr = 0; nr < sdna->nr_types; nr++) { + for (int nr = 0; nr < sdna->types_len; nr++) { /* WARNING! See: DNA_struct_rename_legacy_hack_static_from_alias docs. */ sdna->types[nr] = DNA_struct_rename_legacy_hack_static_from_alias(cp); while (*cp) { @@ -390,17 +437,17 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error sdna->types_size = sp; if (do_endian_swap) { - BLI_endian_switch_int16_array(sp, sdna->nr_types); + BLI_endian_switch_int16_array(sp, sdna->types_len); } - sp += sdna->nr_types; + sp += sdna->types_len; } else { *r_error_message = "TLEN error in SDNA file"; return false; } /* prevent BUS error */ - if (sdna->nr_types & 1) { + if (sdna->types_len & 1) { sp++; } @@ -409,13 +456,13 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error if (*data == MAKE_ID('S', 'T', 'R', 'C')) { data++; - sdna->nr_structs = *data; + sdna->structs_len = *data; if (do_endian_swap) { - BLI_endian_switch_int32(&sdna->nr_structs); + BLI_endian_switch_int32(&sdna->structs_len); } data++; - sdna->structs = MEM_callocN(sizeof(void *) * sdna->nr_structs, "sdnastrcs"); + sdna->structs = MEM_callocN(sizeof(void *) * sdna->structs_len, "sdnastrcs"); } else { *r_error_message = "STRC error in SDNA file"; @@ -423,7 +470,7 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error } sp = (short *)data; - for (int nr = 0; nr < sdna->nr_structs; nr++) { + for (int nr = 0; nr < sdna->structs_len; nr++) { sdna->structs[nr] = sp; if (do_endian_swap) { @@ -449,7 +496,7 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error { /* second part of gravity problem, setting "gravity" type to void */ if (gravity_fix > -1) { - for (int nr = 0; nr < sdna->nr_structs; nr++) { + for (int nr = 0; nr < sdna->structs_len; nr++) { sp = sdna->structs[nr]; if (strcmp(sdna->types[sp[0]], "ClothSimSettings") == 0) { sp[10] = SDNA_TYPE_VOID; @@ -461,9 +508,9 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error #ifdef WITH_DNA_GHASH { /* create a ghash lookup to speed up */ - sdna->structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->nr_structs); + sdna->structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->structs_len); - for (intptr_t nr = 0; nr < sdna->nr_structs; nr++) { + for (intptr_t nr = 0; nr < sdna->structs_len; nr++) { sp = sdna->structs[nr]; BLI_ghash_insert(sdna->structs_map, (void *)sdna->types[sp[0]], POINTER_FROM_INT(nr)); } @@ -495,8 +542,8 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error /* Cache name size. */ { - short *names_array_len = MEM_mallocN(sizeof(*names_array_len) * sdna->nr_names, __func__); - for (int i = 0; i < sdna->nr_names; i++) { + short *names_array_len = MEM_mallocN(sizeof(*names_array_len) * sdna->names_len, __func__); + for (int i = 0; i < sdna->names_len; i++) { names_array_len[i] = DNA_elem_array_size(sdna->names[i]); } sdna->names_array_len = names_array_len; @@ -586,7 +633,7 @@ static void recurs_test_compflags(const SDNA *sdna, char *compflags, int structn sp = sdna->structs[structnr]; typenr = sp[0]; - for (a = 0; a < sdna->nr_structs; a++) { + for (a = 0; a < sdna->structs_len; a++) { if ((a != structnr) && (compflags[a] == SDNA_CMP_EQUAL)) { sp = sdna->structs[a]; elems = sp[1]; @@ -615,19 +662,19 @@ const char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna const char *str1, *str2; char *compflags; - if (oldsdna->nr_structs == 0) { + if (oldsdna->structs_len == 0) { printf("error: file without SDNA\n"); return NULL; } - compflags = MEM_callocN(oldsdna->nr_structs, "compflags"); + compflags = MEM_callocN(oldsdna->structs_len, "compflags"); /* we check all structs in 'oldsdna' and compare them with * the structs in 'newsdna' */ unsigned int newsdna_index_last = 0; - for (a = 0; a < oldsdna->nr_structs; a++) { + for (a = 0; a < oldsdna->structs_len; a++) { sp_old = oldsdna->structs[a]; /* search for type in cur */ @@ -691,14 +738,14 @@ const char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna /* Because structs can be inside structs, we recursively * set flags when a struct is altered */ - for (a = 0; a < oldsdna->nr_structs; a++) { + for (a = 0; a < oldsdna->structs_len; a++) { if (compflags[a] == SDNA_CMP_NOT_EQUAL) { recurs_test_compflags(oldsdna, compflags, a); } } #if 0 - for (a = 0; a < oldsdna->nr_structs; a++) { + for (a = 0; a < oldsdna->structs_len; a++) { if (compflags[a] == SDNA_CMP_NOT_EQUAL) { spold = oldsdna->structs[a]; printf("changed: %s\n", oldsdna->types[spold[0]]); @@ -922,7 +969,14 @@ static int elem_strcmp(const char *name, const char *oname) * \param old: Pointer to struct information in sdna * \return true when existing, false otherwise. */ -static bool elem_exists(const SDNA *sdna, const char *type, const char *name, const short *old) +static bool elem_exists_impl( + /* Expand SDNA. */ + const char **types, + const char **names, + /* Regular args. */ + const char *type, + const char *name, + const short *old) { int a, elemcount; const char *otype, *oname; @@ -931,8 +985,8 @@ static bool elem_exists(const SDNA *sdna, const char *type, const char *name, co elemcount = old[1]; old += 2; for (a = 0; a < elemcount; a++, old += 2) { - otype = sdna->types[old[0]]; - oname = sdna->names[old[1]]; + otype = types[old[0]]; + oname = names[old[1]]; if (elem_strcmp(name, oname) == 0) { /* name equal */ return strcmp(type, otype) == 0; /* type equal */ @@ -941,6 +995,33 @@ static bool elem_exists(const SDNA *sdna, const char *type, const char *name, co return false; } +static bool elem_exists(const SDNA *sdna, const char *type, const char *name, const short *old) +{ + return elem_exists_impl( + /* Expand SDNA. */ + sdna->types, + sdna->names, + /* Regular args. */ + type, + name, + old); +} + +static bool elem_exists_alias(const SDNA *sdna, + const char *type, + const char *name, + const short *old) +{ + return elem_exists_impl( + /* Expand SDNA. */ + sdna->alias.types, + sdna->alias.names, + /* Regular args. */ + type, + name, + old); +} + /** * Returns the address of the data for the specified field within olddata * according to the struct format pointed to by old, or NULL if no such @@ -1397,6 +1478,25 @@ bool DNA_struct_elem_find(const SDNA *sdna, return false; } +/** \note requires #DNA_sdna_alias_data_ensure_structs_map to be called. */ +bool DNA_struct_alias_elem_find(const SDNA *sdna, + const char *stype, + const char *vartype, + const char *name) +{ + const int SDNAnr = DNA_struct_alias_find_nr(sdna, stype); + + if (SDNAnr != -1) { + const short *const spo = sdna->structs[SDNAnr]; + const bool found = elem_exists_alias(sdna, vartype, name, spo); + + if (found) { + return true; + } + } + return false; +} + /** * Returns the size in bytes of a primitive type. */ @@ -1483,14 +1583,15 @@ static bool DNA_sdna_patch_struct_member_nr(SDNA *sdna, strlen(elem_old_full), elem_old_full_offset_start); - if (sdna->nr_names == sdna->nr_names_alloc) { - sdna->nr_names_alloc += 64; - sdna->names = MEM_recallocN(sdna->names, sizeof(*sdna->names) * sdna->nr_names_alloc); + if (sdna->names_len == sdna->names_len_alloc) { + sdna->names_len_alloc += 64; + sdna->names = MEM_recallocN((void *)sdna->names, + sizeof(*sdna->names) * sdna->names_len_alloc); sdna->names_array_len = MEM_recallocN( - (void *)sdna->names_array_len, sizeof(*sdna->names_array_len) * sdna->nr_names_alloc); + (void *)sdna->names_array_len, sizeof(*sdna->names_array_len) * sdna->names_len_alloc); } const short name_nr_prev = sp[1]; - sp[1] = sdna->nr_names++; + sp[1] = sdna->names_len++; sdna->names[sp[1]] = elem_new_full; sdna->names_array_len[sp[1]] = sdna->names_array_len[name_nr_prev]; @@ -1533,14 +1634,14 @@ bool DNA_sdna_patch_struct_member(SDNA *sdna, static void sdna_expand_names(SDNA *sdna) { int names_expand_len = 0; - for (int struct_nr = 0; struct_nr < sdna->nr_structs; struct_nr++) { + for (int struct_nr = 0; struct_nr < sdna->structs_len; struct_nr++) { const short *sp = sdna->structs[struct_nr]; names_expand_len += sp[1]; } const char **names_expand = MEM_mallocN(sizeof(*names_expand) * names_expand_len, __func__); int names_expand_index = 0; - for (int struct_nr = 0; struct_nr < sdna->nr_structs; struct_nr++) { + for (int struct_nr = 0; struct_nr < sdna->structs_len; struct_nr++) { /* We can't edit this memory 'sdna->structs' points to (readonly datatoc file). */ const short *sp = sdna->structs[struct_nr]; short *sp_expand = BLI_memarena_alloc(sdna->mem_arena, sizeof(short[2]) * (1 + sp[1])); @@ -1558,13 +1659,13 @@ static void sdna_expand_names(SDNA *sdna) } MEM_freeN((void *)sdna->names); sdna->names = names_expand; - sdna->nr_names = names_expand_len; + sdna->names_len = names_expand_len; } -static const char *dna_sdna_alias_alias_from_static_elem_full(SDNA *sdna, - GHash *elem_map_alias_from_static, - const char *struct_name_static, - const char *elem_static_full) +static const char *dna_sdna_alias_from_static_elem_full(SDNA *sdna, + GHash *elem_map_alias_from_static, + const char *struct_name_static, + const char *elem_static_full) { const int elem_static_full_len = strlen(elem_static_full); char *elem_static = alloca(elem_static_full_len + 1); @@ -1600,8 +1701,8 @@ void DNA_sdna_alias_data_ensure(SDNA *sdna) DNA_RENAME_ALIAS_FROM_STATIC, &struct_map_alias_from_static, &elem_map_alias_from_static); if (sdna->alias.types == NULL) { - sdna->alias.types = MEM_mallocN(sizeof(*sdna->alias.types) * sdna->nr_types, __func__); - for (int type_nr = 0; type_nr < sdna->nr_types; type_nr++) { + sdna->alias.types = MEM_mallocN(sizeof(*sdna->alias.types) * sdna->types_len, __func__); + for (int type_nr = 0; type_nr < sdna->types_len; type_nr++) { const char *struct_name_static = sdna->types[type_nr]; if (use_legacy_hack) { @@ -1615,8 +1716,8 @@ void DNA_sdna_alias_data_ensure(SDNA *sdna) if (sdna->alias.names == NULL) { sdna_expand_names(sdna); - sdna->alias.names = MEM_mallocN(sizeof(*sdna->alias.names) * sdna->nr_names, __func__); - for (int struct_nr = 0; struct_nr < sdna->nr_structs; struct_nr++) { + sdna->alias.names = MEM_mallocN(sizeof(*sdna->alias.names) * sdna->names_len, __func__); + for (int struct_nr = 0; struct_nr < sdna->structs_len; struct_nr++) { const short *sp = sdna->structs[struct_nr]; const char *struct_name_static = sdna->types[sp[0]]; @@ -1627,7 +1728,7 @@ void DNA_sdna_alias_data_ensure(SDNA *sdna) const int dna_struct_names_len = sp[1]; sp += 2; for (int a = 0; a < dna_struct_names_len; a++, sp += 2) { - const char *elem_alias_full = dna_sdna_alias_alias_from_static_elem_full( + const char *elem_alias_full = dna_sdna_alias_from_static_elem_full( sdna, elem_map_alias_from_static, struct_name_static, sdna->names[sp[1]]); if (elem_alias_full != NULL) { sdna->alias.names[sp[1]] = elem_alias_full; @@ -1642,4 +1743,24 @@ void DNA_sdna_alias_data_ensure(SDNA *sdna) BLI_ghash_free(elem_map_alias_from_static, MEM_freeN, NULL); } +/** + * Separated from #DNA_sdna_alias_data_ensure because it's not needed + * unless we want to lookup aliased struct names (#DNA_struct_alias_find_nr and friends). + */ +void DNA_sdna_alias_data_ensure_structs_map(SDNA *sdna) +{ + DNA_sdna_alias_data_ensure(sdna); +#ifdef WITH_DNA_GHASH + /* create a ghash lookup to speed up */ + struct GHash *structs_map = BLI_ghash_str_new_ex(__func__, sdna->structs_len); + for (intptr_t nr = 0; nr < sdna->structs_len; nr++) { + const short *sp = sdna->structs[nr]; + BLI_ghash_insert(structs_map, (void *)sdna->alias.types[sp[0]], POINTER_FROM_INT(nr)); + } + sdna->alias.structs_map = structs_map; +#else + UNUSED_VARS(sdna); +#endif +} + /** \} */ diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h index 3aa0ff4b28a..0bc35c15e35 100644 --- a/source/blender/makesdna/intern/dna_rename_defs.h +++ b/source/blender/makesdna/intern/dna_rename_defs.h @@ -75,6 +75,7 @@ DNA_STRUCT_RENAME_ELEM(Object, size, scale) DNA_STRUCT_RENAME_ELEM(ParticleSettings, dup_group, instance_collection) DNA_STRUCT_RENAME_ELEM(ParticleSettings, dup_ob, instance_object) DNA_STRUCT_RENAME_ELEM(ParticleSettings, dupliweights, instance_weights) +DNA_STRUCT_RENAME_ELEM(ThemeSpace, scrubbing_background, time_scrub_background) DNA_STRUCT_RENAME_ELEM(View3D, far, clip_end) DNA_STRUCT_RENAME_ELEM(View3D, near, clip_start) DNA_STRUCT_RENAME_ELEM(bPoseChannel, curveInX, curve_in_x) diff --git a/source/blender/makesdna/intern/dna_utils.c b/source/blender/makesdna/intern/dna_utils.c index 425deaf121f..c402b36812b 100644 --- a/source/blender/makesdna/intern/dna_utils.c +++ b/source/blender/makesdna/intern/dna_utils.c @@ -265,7 +265,7 @@ void DNA_alias_maps(enum eDNA_RenameDir version_dir, GHash **r_struct_map, GHash const char **str_pair = MEM_mallocN(sizeof(char *) * 2, __func__); str_pair[0] = BLI_ghash_lookup_default(struct_map_local, data[i][0], (void *)data[i][0]); str_pair[1] = data[i][elem_key]; - BLI_ghash_insert(elem_map, str_pair, (void *)data[i][elem_val]); + BLI_ghash_insert(elem_map, (void *)str_pair, (void *)data[i][elem_val]); } *r_elem_map = elem_map; } diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 2e94c29a825..c0859a7d4ce 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -145,10 +145,10 @@ static const char *includefiles[] = { static MemArena *mem_arena = NULL; -static int maxdata = 500000, maxnr = 50000; -static int nr_names = 0; -static int nr_types = 0; -static int nr_structs = 0; +static int max_data_size = 500000, max_array_len = 50000; +static int names_len = 0; +static int types_len = 0; +static int structs_len = 0; /** At address `names[a]` is string `a`. */ static char **names; /** At address `types[a]` is string `a`. */ @@ -162,7 +162,7 @@ static short *types_size_64; /** At `sp = structs[a]` is the first address of a struct definition: * - `sp[0]` is type number. * - `sp[1]` is the length of the element array (next). - * - `sp[2]` sp[3] is [(type_nr, name_nr), ..] (number of pairs is defined by `sp[1]`), + * - `sp[2]` sp[3] is [(type_index, name_index), ..] (number of pairs is defined by `sp[1]`), */ static short **structs, *structdata; @@ -345,7 +345,6 @@ static bool is_name_legal(const char *name) static int add_type(const char *str, int size) { - int nr; char *cp; /* first do validity check */ @@ -361,14 +360,14 @@ static int add_type(const char *str, int size) str = version_struct_static_from_alias(str); /* search through type array */ - for (nr = 0; nr < nr_types; nr++) { - if (strcmp(str, types[nr]) == 0) { + for (int index = 0; index < types_len; index++) { + if (strcmp(str, types[index]) == 0) { if (size) { - types_size_native[nr] = size; - types_size_32[nr] = size; - types_size_64[nr] = size; + types_size_native[index] = size; + types_size_32[index] = size; + types_size_64[index] = size; } - return nr; + return index; } } @@ -376,18 +375,18 @@ static int add_type(const char *str, int size) const int str_size = strlen(str) + 1; cp = BLI_memarena_alloc(mem_arena, str_size); memcpy(cp, str, str_size); - types[nr_types] = cp; - types_size_native[nr_types] = size; - types_size_32[nr_types] = size; - types_size_64[nr_types] = size; + types[types_len] = cp; + types_size_native[types_len] = size; + types_size_32[types_len] = size; + types_size_64[types_len] = size; - if (nr_types >= maxnr) { + if (types_len >= max_array_len) { printf("too many types\n"); - return nr_types - 1; + return types_len - 1; } - nr_types++; + types_len++; - return nr_types - 1; + return types_len - 1; } /** @@ -514,7 +513,7 @@ static int add_name(const char *str) } /* search name array */ - for (nr = 0; nr < nr_names; nr++) { + for (nr = 0; nr < names_len; nr++) { if (strcmp(name, names[nr]) == 0) { return nr; } @@ -529,15 +528,15 @@ static int add_name(const char *str) const int name_size = strlen(name) + 1; cp = BLI_memarena_alloc(mem_arena, name_size); memcpy(cp, name, name_size); - names[nr_names] = cp; + names[names_len] = cp; - if (nr_names >= maxnr) { + if (names_len >= max_array_len) { printf("too many names\n"); - return nr_names - 1; + return names_len - 1; } - nr_names++; + names_len++; - return nr_names - 1; + return names_len - 1; } static short *add_struct(int namecode) @@ -545,23 +544,23 @@ static short *add_struct(int namecode) int len; short *sp; - if (nr_structs == 0) { + if (structs_len == 0) { structs[0] = structdata; } else { - sp = structs[nr_structs - 1]; + sp = structs[structs_len - 1]; len = sp[1]; - structs[nr_structs] = sp + 2 * len + 2; + structs[structs_len] = sp + 2 * len + 2; } - sp = structs[nr_structs]; + sp = structs[structs_len]; sp[0] = namecode; - if (nr_structs >= maxnr) { + if (structs_len >= max_array_len) { printf("too many structs\n"); return sp; } - nr_structs++; + structs_len++; return sp; } @@ -897,7 +896,7 @@ static bool check_field_alignment( static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char *base_directory) { - int unknown = nr_structs, lastunknown; + int unknown = structs_len, lastunknown; bool dna_error = false; /* Write test to verify sizes are accurate. */ @@ -915,7 +914,7 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char unknown = 0; /* check all structs... */ - for (int a = 0; a < nr_structs; a++) { + for (int a = 0; a < structs_len; a++) { const short *structpoin = structs[a]; const int structtype = structpoin[0]; const char *structname = version_struct_alias_from_static(types[structtype]); @@ -1100,7 +1099,7 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char if (debugSDNA) { fprintf(stderr, "*** Known structs :\n"); - for (int a = 0; a < nr_structs; a++) { + for (int a = 0; a < structs_len; a++) { const short *structpoin = structs[a]; const int structtype = structpoin[0]; @@ -1113,7 +1112,7 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char fprintf(stderr, "*** Unknown structs :\n"); - for (int a = 0; a < nr_structs; a++) { + for (int a = 0; a < structs_len; a++) { const short *structpoin = structs[a]; const int structtype = structpoin[0]; @@ -1151,7 +1150,7 @@ static void dna_write(FILE *file, const void *pntr, const int size) void print_struct_sizes(void) { - int a, unknown = nr_structs, structtype; + int a, unknown = structs_len, structtype; /*int lastunknown;*/ /*UNUSED*/ const short *structpoin; printf("\n\n*** All detected structs:\n"); @@ -1161,7 +1160,7 @@ void print_struct_sizes(void) unknown = 0; /* check all structs... */ - for (a = 0; a < nr_structs; a++) { + for (a = 0; a < structs_len; a++) { structpoin = structs[a]; structtype = structpoin[0]; printf("\t%s\t:%d\n", types[structtype], types_size_native[structtype]); @@ -1191,15 +1190,15 @@ static int make_structDNA(const char *base_directory, mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); /* the longest known struct is 50k, so we assume 100k is sufficient! */ - structdata = MEM_callocN(maxdata, "structdata"); + structdata = MEM_callocN(max_data_size, "structdata"); /* a maximum of 5000 variables, must be sufficient? */ - names = MEM_callocN(sizeof(char *) * maxnr, "names"); - types = MEM_callocN(sizeof(char *) * maxnr, "types"); - types_size_native = MEM_callocN(sizeof(short) * maxnr, "types_size_native"); - types_size_32 = MEM_callocN(sizeof(short) * maxnr, "types_size_32"); - types_size_64 = MEM_callocN(sizeof(short) * maxnr, "types_size_64"); - structs = MEM_callocN(sizeof(short *) * maxnr, "structs"); + names = MEM_callocN(sizeof(char *) * max_array_len, "names"); + types = MEM_callocN(sizeof(char *) * max_array_len, "types"); + types_size_native = MEM_callocN(sizeof(short) * max_array_len, "types_size_native"); + types_size_32 = MEM_callocN(sizeof(short) * max_array_len, "types_size_32"); + types_size_64 = MEM_callocN(sizeof(short) * max_array_len, "types_size_64"); + structs = MEM_callocN(sizeof(short *) * max_array_len, "structs"); /* Build versioning data */ DNA_alias_maps(DNA_RENAME_ALIAS_FROM_STATIC, @@ -1234,7 +1233,7 @@ static int make_structDNA(const char *base_directory, add_type("void", 0); /* SDNA_TYPE_VOID */ /* the defines above shouldn't be output in the padding file... */ - firststruct = nr_types; + firststruct = types_len; /* add all include files defined in the global array */ /* Since the internal file+path name buffer has limited length, I do a */ @@ -1261,19 +1260,19 @@ static int make_structDNA(const char *base_directory, /* short *elem; */ short num_types; - printf("nr_names %d nr_types %d nr_structs %d\n", nr_names, nr_types, nr_structs); - for (a = 0; a < nr_names; a++) { + printf("names_len %d types_len %d structs_len %d\n", names_len, types_len, structs_len); + for (a = 0; a < names_len; a++) { printf(" %s\n", names[a]); } printf("\n"); sp = types_size_native; - for (a = 0; a < nr_types; a++, sp++) { + for (a = 0; a < types_len; a++, sp++) { printf(" %s %d\n", types[a], *sp); } printf("\n"); - for (a = 0; a < nr_structs; a++) { + for (a = 0; a < structs_len; a++) { sp = structs[a]; printf(" struct %s elems: %d size: %d\n", types[sp[0]], sp[1], types_size_native[sp[0]]); num_types = sp[1]; @@ -1289,7 +1288,7 @@ static int make_structDNA(const char *base_directory, DEBUG_PRINTF(0, "Writing file ... "); - if (nr_names == 0 || nr_structs == 0) { + if (names_len == 0 || structs_len == 0) { /* pass */ } else { @@ -1300,11 +1299,11 @@ static int make_structDNA(const char *base_directory, /* write names */ dna_write(file, "NAME", 4); - len = nr_names; + len = names_len; dna_write(file, &len, 4); /* write array */ len = 0; - for (int nr = 0; nr < nr_names; nr++) { + for (int nr = 0; nr < names_len; nr++) { int name_size = strlen(names[nr]) + 1; dna_write(file, names[nr], name_size); len += name_size; @@ -1316,11 +1315,11 @@ static int make_structDNA(const char *base_directory, /* write TYPES */ dna_write(file, "TYPE", 4); - len = nr_types; + len = types_len; dna_write(file, &len, 4); /* write array */ len = 0; - for (int nr = 0; nr < nr_types; nr++) { + for (int nr = 0; nr < types_len; nr++) { int type_size = strlen(types[nr]) + 1; dna_write(file, types[nr], type_size); len += type_size; @@ -1333,19 +1332,19 @@ static int make_structDNA(const char *base_directory, /* WRITE TYPELENGTHS */ dna_write(file, "TLEN", 4); - len = 2 * nr_types; - if (nr_types & 1) { + len = 2 * types_len; + if (types_len & 1) { len += 2; } dna_write(file, types_size_native, len); /* WRITE STRUCTS */ dna_write(file, "STRC", 4); - len = nr_structs; + len = structs_len; dna_write(file, &len, 4); /* calc datablock size */ - sp = structs[nr_structs - 1]; + sp = structs[structs_len - 1]; sp += 2 + 2 * (sp[1]); len = (intptr_t)((char *)sp - (char *)structs[0]); len = (len + 3) & ~3; @@ -1358,7 +1357,7 @@ static int make_structDNA(const char *base_directory, { fprintf(file_offsets, "#define SDNA_TYPE_FROM_STRUCT(id) _SDNA_TYPE_##id\n"); fprintf(file_offsets, "enum {\n"); - for (i = 0; i < nr_structs; i++) { + for (i = 0; i < structs_len; i++) { const short *structpoin = structs[i]; const int structtype = structpoin[0]; fprintf(file_offsets, @@ -1366,7 +1365,7 @@ static int make_structDNA(const char *base_directory, version_struct_alias_from_static(types[structtype]), i); } - fprintf(file_offsets, "\tSDNA_TYPE_MAX = %d,\n", nr_structs); + fprintf(file_offsets, "\tSDNA_TYPE_MAX = %d,\n", structs_len); fprintf(file_offsets, "};\n\n"); } @@ -1374,7 +1373,7 @@ static int make_structDNA(const char *base_directory, * do last because names are stripped. */ { GSet *names_unique = BLI_gset_str_new_ex(__func__, 512); - for (int struct_nr = 0; struct_nr < nr_structs; struct_nr++) { + for (int struct_nr = 0; struct_nr < structs_len; struct_nr++) { sp = structs[struct_nr]; const char *struct_name = types[sp[0]]; const int len = sp[1]; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 40b0b7cc324..47958c2a68e 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -728,6 +728,7 @@ extern StructRNA RNA_View3DOverlay; extern StructRNA RNA_View3DShading; extern StructRNA RNA_ViewLayer; extern StructRNA RNA_VoronoiTexture; +extern StructRNA RNA_WalkNavigation; extern StructRNA RNA_WarpModifier; extern StructRNA RNA_WaveModifier; extern StructRNA RNA_WeightedNormalModifier; @@ -1033,12 +1034,12 @@ void *RNA_property_enum_py_data_get(PropertyRNA *prop); int RNA_property_enum_step( const struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int step); -PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop); -void RNA_property_pointer_set(struct ReportList *reports, - PointerRNA *ptr, +PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) ATTR_NONNULL(1, 2); +void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, - PointerRNA ptr_value); -PointerRNA RNA_property_pointer_get_default(PointerRNA *ptr, PropertyRNA *prop); + PointerRNA ptr_value, + struct ReportList *reports) ATTR_NONNULL(1, 2); +PointerRNA RNA_property_pointer_get_default(PointerRNA *ptr, PropertyRNA *prop) ATTR_NONNULL(1, 2); void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h index 59c03cf34b3..0beb14614ec 100644 --- a/source/blender/makesrna/RNA_define.h +++ b/source/blender/makesrna/RNA_define.h @@ -48,6 +48,7 @@ void RNA_define_free(BlenderRNA *brna); void RNA_free(BlenderRNA *brna); void RNA_define_verify_sdna(bool verify); void RNA_define_animate_sdna(bool animate); +void RNA_define_fallback_property_update(int noteflag, const char *updatefunc); void RNA_init(void); void RNA_exit(void); diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index a3a18be71d1..7768298b2c5 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -567,7 +567,7 @@ static int rna_color_quantize(PropertyRNA *prop, PropertyDefRNA *dp) (IS_DNATYPE_FLOAT_COMPAT(dp->dnatype) == 0)); } -static const char *rna_function_string(void *func) +static const char *rna_function_string(const void *func) { return (func) ? (const char *)func : "NULL"; } @@ -1033,10 +1033,10 @@ static char *rna_def_property_set_func( break; } case PROP_POINTER: { - fprintf(f, "void %s(struct ReportList *reports, PointerRNA *ptr, PointerRNA value)\n", func); + fprintf(f, "void %s(PointerRNA *ptr, PointerRNA value, struct ReportList *reports)\n", func); fprintf(f, "{\n"); if (manualfunc) { - fprintf(f, " %s(reports, ptr, value);\n", manualfunc); + fprintf(f, " %s(ptr, value, reports);\n", manualfunc); } else { rna_print_data_get(f, dp); diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 97d3d03468b..7e6a3e70b9d 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -463,7 +463,7 @@ static ID *rna_ID_override_create(ID *id, Main *bmain) return BKE_override_static_create_from_id(bmain, id); } -static void rna_ID_update_tag(ID *id, ReportList *reports, int flag) +static void rna_ID_update_tag(ID *id, Main *bmain, ReportList *reports, int flag) { /* XXX, new function for this! */ # if 0 @@ -478,6 +478,8 @@ static void rna_ID_update_tag(ID *id, ReportList *reports, int flag) /* pass */ } else { + int allow_flag = 0; + /* ensure flag us correct for the type */ switch (GS(id->name)) { case ID_OB: @@ -485,28 +487,35 @@ static void rna_ID_update_tag(ID *id, ReportList *reports, int flag) * object types supports different flags. Maybe does not worth checking * for this at all. Or maybe let dependency graph to return whether * the tag was valid or not. */ - if (flag & ~(ID_RECALC_ALL)) { - BKE_report(reports, RPT_ERROR, "'Refresh' incompatible with Object ID type"); - return; - } + allow_flag = ID_RECALC_ALL; break; /* Could add particle updates later */ # if 0 case ID_PA: - if (flag & ~(OB_RECALC_ALL | PSYS_RECALC)) { - BKE_report(reports, RPT_ERROR, "'Refresh' incompatible with ParticleSettings ID type"); - return; - } + allow_flag = OB_RECALC_ALL | PSYS_RECALC; break; # endif + case ID_AC: + allow_flag = ID_RECALC_ANIMATION; + break; default: - BKE_report( - reports, RPT_ERROR, "This ID type is not compatible with any 'refresh' options"); - return; + if (id_can_have_animdata(id)) { + allow_flag = ID_RECALC_ANIMATION; + } + } + + if (flag & ~allow_flag) { + StructRNA *srna = ID_code_to_RNA_type(GS(id->name)); + BKE_reportf(reports, + RPT_ERROR, + "%s is not compatible with %s 'refresh' options", + RNA_struct_identifier(srna), + allow_flag ? "the specified" : "any"); + return; } } - DEG_id_tag_update(id, flag); + DEG_id_tag_update_ex(bmain, id, flag); } static void rna_ID_user_clear(ID *id) @@ -1531,7 +1540,7 @@ static void rna_def_ID(BlenderRNA *brna) RNA_def_function_ui_description(func, "Clear animation on this this ID"); func = RNA_def_function(srna, "update_tag", "rna_ID_update_tag"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); RNA_def_function_ui_description(func, "Tag the ID to update its display data, " "e.g. when calling :class:`bpy.types.Scene.update`"); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index b56a031f9df..20358ca80fd 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -3733,10 +3733,10 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) } } -void RNA_property_pointer_set(ReportList *reports, - PointerRNA *ptr, +void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, - PointerRNA ptr_value) + PointerRNA ptr_value, + ReportList *reports) { PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; BLI_assert(RNA_property_type(prop) == PROP_POINTER); @@ -3755,7 +3755,7 @@ void RNA_property_pointer_set(ReportList *reports, /* RNA */ if (pprop->set && !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) && !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data)) { - pprop->set(reports, ptr, ptr_value); + pprop->set(ptr, ptr_value, reports); } /* IDProperty */ else if (prop->flag & PROP_EDITABLE) { @@ -6427,7 +6427,7 @@ void RNA_pointer_set(PointerRNA *ptr, const char *name, PointerRNA ptr_value) PropertyRNA *prop = RNA_struct_find_property(ptr, name); if (prop) { - RNA_property_pointer_set(NULL, ptr, prop, ptr_value); + RNA_property_pointer_set(ptr, prop, ptr_value, NULL); } else { printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name); @@ -7976,7 +7976,7 @@ bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index) case PROP_POINTER: { PointerRNA value = RNA_property_pointer_get_default(ptr, prop); - RNA_property_pointer_set(NULL, ptr, prop, value); + RNA_property_pointer_set(ptr, prop, value, NULL); return true; } diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index e99a1ffe2be..4e98db21089 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -214,9 +214,9 @@ static PointerRNA rna_Action_active_pose_marker_get(PointerRNA *ptr) ptr, &RNA_TimelineMarker, BLI_findlink(&act->markers, act->active_marker - 1)); } -static void rna_Action_active_pose_marker_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Action_active_pose_marker_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bAction *act = (bAction *)ptr->data; act->active_marker = BLI_findindex(&act->markers, value.data) + 1; @@ -341,7 +341,7 @@ static void rna_def_dopesheet(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_INCL_HIDDEN); RNA_def_property_ui_text( prop, "Display Hidden", "Include channels from objects/bone that are not visible"); - RNA_def_property_ui_icon(prop, ICON_GHOST_ENABLED, 0); + RNA_def_property_ui_icon(prop, ICON_OBJECT_HIDDEN, 0); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); prop = RNA_def_property(srna, "use_datablock_sort", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index ba7929521f9..6228414e4f4 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -151,9 +151,9 @@ static int rna_AnimData_action_editable(PointerRNA *ptr, const char **UNUSED(r_i return PROP_EDITABLE; } -static void rna_AnimData_action_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_AnimData_action_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { ID *ownerId = (ID *)ptr->id.data; @@ -463,9 +463,9 @@ static PointerRNA rna_KeyingSet_active_ksPath_get(PointerRNA *ptr) ptr, &RNA_KeyingSetPath, BLI_findlink(&ks->paths, ks->active_path - 1)); } -static void rna_KeyingSet_active_ksPath_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_KeyingSet_active_ksPath_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { KeyingSet *ks = (KeyingSet *)ptr->data; KS_Path *ksp = (KS_Path *)value.data; @@ -616,9 +616,9 @@ static PointerRNA rna_NlaTrack_active_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_NlaTrack, track); } -static void rna_NlaTrack_active_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_NlaTrack_active_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { AnimData *adt = (AnimData *)ptr->data; NlaTrack *track = (NlaTrack *)value.data; diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 3aef22f5f7f..604be10d5ab 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -67,9 +67,9 @@ static void rna_Armature_dependency_update(Main *bmain, Scene *UNUSED(scene), Po WM_main_add_notifier(NC_GEOM | ND_DATA, id); } -static void rna_Armature_act_bone_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Armature_act_bone_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bArmature *arm = (bArmature *)ptr->data; @@ -91,9 +91,9 @@ static void rna_Armature_act_bone_set(struct ReportList *UNUSED(reports), } } -static void rna_Armature_act_edit_bone_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Armature_act_edit_bone_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bArmature *arm = (bArmature *)ptr->data; @@ -399,9 +399,9 @@ static PointerRNA rna_EditBone_parent_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_EditBone, data->parent); } -static void rna_EditBone_parent_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_EditBone_parent_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { EditBone *ebone = (EditBone *)(ptr->data); EditBone *pbone, *parbone = (EditBone *)value.data; @@ -469,9 +469,9 @@ static PointerRNA rna_EditBone_bbone_prev_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_EditBone, data->bbone_prev); } -static void rna_EditBone_bbone_prev_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_EditBone_bbone_prev_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { EditBone *ebone = (EditBone *)(ptr->data); EditBone *hbone = (EditBone *)value.data; @@ -482,9 +482,9 @@ static void rna_EditBone_bbone_prev_set(struct ReportList *UNUSED(reports), } } -static void rna_Bone_bbone_prev_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Bone_bbone_prev_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Bone *bone = (Bone *)ptr->data; Bone *hbone = (Bone *)value.data; @@ -501,9 +501,9 @@ static PointerRNA rna_EditBone_bbone_next_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_EditBone, data->bbone_next); } -static void rna_EditBone_bbone_next_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_EditBone_bbone_next_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { EditBone *ebone = (EditBone *)(ptr->data); EditBone *hbone = (EditBone *)value.data; @@ -514,9 +514,9 @@ static void rna_EditBone_bbone_next_set(struct ReportList *UNUSED(reports), } } -static void rna_Bone_bbone_next_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Bone_bbone_next_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Bone *bone = (Bone *)ptr->data; Bone *hbone = (Bone *)value.data; diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index bab7075b75b..f5cb29b5e69 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -306,9 +306,9 @@ static PointerRNA rna_ClothSettings_rest_shape_key_get(PointerRNA *ptr) return rna_object_shapekey_index_get(ob->data, sim->shapekey_rest); } -static void rna_ClothSettings_rest_shape_key_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_ClothSettings_rest_shape_key_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Object *ob = (Object *)ptr->id.data; ClothSimSettings *sim = (ClothSimSettings *)ptr->data; diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 8ba1f5440be..30ab591d3c9 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -623,7 +623,7 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *bmain, seq->strip->proxy->anim = NULL; } - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); } else { SEQ_BEGIN (scene->ed, seq) { @@ -1136,7 +1136,7 @@ static void rna_def_colormanage(BlenderRNA *brna) PropertyRNA *prop; static const EnumPropertyItem display_device_items[] = { - {0, "DEFAULT", 0, "Default", ""}, + {0, "NONE", 0, "None", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -1249,7 +1249,10 @@ static void rna_def_colormanage(BlenderRNA *brna) "rna_ColorManagedColorspaceSettings_colorspace_get", "rna_ColorManagedColorspaceSettings_colorspace_set", "rna_ColorManagedColorspaceSettings_colorspace_itemf"); - RNA_def_property_ui_text(prop, "Input Color Space", "Color space of the image or movie on disk"); + RNA_def_property_ui_text( + prop, + "Input Color Space", + "Color space in the image file, to convert to and from when saving and loading the image"); RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update"); prop = RNA_def_property(srna, "is_data", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 252dc40f3f5..ac319a545ac 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -351,9 +351,9 @@ static StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr) } } -static void rna_ConstraintTargetBone_target_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_ConstraintTargetBone_target_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bConstraintTarget *tgt = (bConstraintTarget *)ptr->data; Object *ob = value.data; @@ -667,9 +667,9 @@ static bool rna_Constraint_cameraObject_poll(PointerRNA *ptr, PointerRNA value) return 0; } -static void rna_Constraint_followTrack_camera_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Constraint_followTrack_camera_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bConstraint *con = (bConstraint *)ptr->data; bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data; @@ -686,9 +686,9 @@ static void rna_Constraint_followTrack_camera_set(struct ReportList *UNUSED(repo } } -static void rna_Constraint_followTrack_depthObject_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Constraint_followTrack_depthObject_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bConstraint *con = (bConstraint *)ptr->data; bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data; @@ -718,9 +718,9 @@ static bool rna_Constraint_followTrack_depthObject_poll(PointerRNA *ptr, Pointer return 0; } -static void rna_Constraint_objectSolver_camera_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Constraint_objectSolver_camera_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bConstraint *con = (bConstraint *)ptr->data; bObjectSolverConstraint *data = (bObjectSolverConstraint *)con->data; diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c index a2ac7cb40ba..9986b4c1674 100644 --- a/source/blender/makesrna/intern/rna_context.c +++ b/source/blender/makesrna/intern/rna_context.c @@ -57,6 +57,10 @@ const EnumPropertyItem rna_enum_context_mode_items[] = { #ifdef RNA_RUNTIME +# ifdef WITH_PYTHON +# include "BPY_extern.h" +# endif + # include "RE_engine.h" static PointerRNA rna_Context_manager_get(PointerRNA *ptr) @@ -200,7 +204,20 @@ static int rna_Context_mode_get(PointerRNA *ptr) static struct Depsgraph *rna_Context_evaluated_depsgraph_get(bContext *C) { - return CTX_data_evaluated_depsgraph(C); + struct Depsgraph *depsgraph; + +# ifdef WITH_PYTHON + /* Allow drivers to be evaluated */ + BPy_BEGIN_ALLOW_THREADS; +# endif + + depsgraph = CTX_data_evaluated_depsgraph(C); + +# ifdef WITH_PYTHON + BPy_END_ALLOW_THREADS; +# endif + + return depsgraph; } #else diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 111e8956414..89200240b08 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -438,9 +438,9 @@ static PointerRNA rna_Curve_bevelObject_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, NULL, NULL); } -static void rna_Curve_bevelObject_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Curve_bevelObject_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Curve *cu = (Curve *)ptr->id.data; Object *ob = (Object *)value.data; @@ -483,9 +483,9 @@ static PointerRNA rna_Curve_taperObject_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, NULL, NULL); } -static void rna_Curve_taperObject_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Curve_taperObject_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Curve *cu = (Curve *)ptr->id.data; Object *ob = (Object *)value.data; @@ -734,9 +734,9 @@ static PointerRNA rna_Curve_active_spline_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, NULL, NULL); } -static void rna_Curve_active_spline_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Curve_active_spline_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Curve *cu = (Curve *)ptr->data; Nurb *nu = value.data; diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 8e24e9a8364..b1818cae62a 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -709,6 +709,14 @@ void RNA_define_animate_sdna(bool animate) } #endif +#ifndef RNA_RUNTIME +void RNA_define_fallback_property_update(int noteflag, const char *updatefunc) +{ + DefRNA.fallback.property_update.noteflag = noteflag; + DefRNA.fallback.property_update.updatefunc = updatefunc; +} +#endif + void RNA_struct_free_extension(StructRNA *srna, ExtensionRNA *ext) { #ifdef RNA_RUNTIME @@ -1413,6 +1421,12 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, } /* TODO: do we want that for runtime-defined stuff too? I’d say no, but... maybe yes :/ */ +#ifndef RNA_RUNTIME + /* Both are typically cleared. */ + RNA_def_property_update( + prop, DefRNA.fallback.property_update.noteflag, DefRNA.fallback.property_update.updatefunc); +#endif + rna_addtail(&cont->properties, prop); return prop; diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c index c4a2a64f3f0..df1727ff87c 100644 --- a/source/blender/makesrna/intern/rna_depsgraph.c +++ b/source/blender/makesrna/intern/rna_depsgraph.c @@ -622,21 +622,13 @@ static void rna_def_depsgraph(BlenderRNA *brna) func = RNA_def_function( srna, "debug_relations_graphviz", "rna_Depsgraph_debug_relations_graphviz"); - parm = RNA_def_string_file_path(func, - "filename", - NULL, - FILE_MAX, - "File Name", - "File in which to store graphviz debug output"); + parm = RNA_def_string_file_path( + func, "filename", NULL, FILE_MAX, "File Name", "Output path for the graphviz debug file"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); func = RNA_def_function(srna, "debug_stats_gnuplot", "rna_Depsgraph_debug_stats_gnuplot"); - parm = RNA_def_string_file_path(func, - "filename", - NULL, - FILE_MAX, - "File Name", - "File in which to store graphviz debug output"); + parm = RNA_def_string_file_path( + func, "filename", NULL, FILE_MAX, "File Name", "Output path for the gnuplot debug file"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_string_file_path(func, "output_filename", diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 1edcbf0774d..741b73f4250 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -239,9 +239,9 @@ static void rna_DriverTarget_update_name(Main *bmain, Scene *scene, PointerRNA * /* ----------- */ /* note: this function exists only to avoid id refcounting */ -static void rna_DriverTarget_id_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_DriverTarget_id_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { DriverTarget *dtar = (DriverTarget *)ptr->data; dtar->id = value.data; @@ -448,9 +448,9 @@ static void rna_FCurve_RnaPath_set(PointerRNA *ptr, const char *value) fcu->rna_path = NULL; } -static void rna_FCurve_group_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_FCurve_group_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { ID *pid = (ID *)ptr->id.data; ID *vid = (ID *)value.id.data; @@ -530,18 +530,35 @@ static bool rna_FCurve_is_empty_get(PointerRNA *ptr) return BKE_fcurve_is_empty(fcu); } +static void rna_tag_animation_update(Main *bmain, ID *id, bool flush) +{ + /* Actually recalculate object properties, or just update COW. */ + int tags = flush ? ID_RECALC_ANIMATION : ID_RECALC_ANIMATION_NO_FLUSH; + + AnimData *adt = BKE_animdata_from_id(id); + + if (adt && adt->action) { + /* action is separate datablock, needs separate tag */ + DEG_id_tag_update_ex(bmain, &adt->action->id, tags); + } + + DEG_id_tag_update_ex(bmain, id, tags); +} + /* allow scripts to update curve after editing manually */ -static void rna_FCurve_update_data_ex(FCurve *fcu) +static void rna_FCurve_update_data_ex(ID *id, FCurve *fcu, Main *bmain) { sort_time_fcurve(fcu); calchandles_fcurve(fcu); + + rna_tag_animation_update(bmain, id, true); } /* RNA update callback for F-Curves after curve shape changes */ -static void rna_FCurve_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_FCurve_update_data(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { BLI_assert(ptr->type == &RNA_FCurve); - rna_FCurve_update_data_ex((FCurve *)ptr->data); + rna_FCurve_update_data_ex((ID *)ptr->id.data, (FCurve *)ptr->data, bmain); } static void rna_FCurve_update_data_relations(Main *bmain, @@ -554,13 +571,9 @@ static void rna_FCurve_update_data_relations(Main *bmain, /* RNA update callback for F-Curves to indicate that there are copy-on-write tagging/flushing * needed (e.g. for properties that affect how animation gets evaluated). */ -static void rna_FCurve_update_eval(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_FCurve_update_eval(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - IdAdtTemplate *iat = (IdAdtTemplate *)ptr->id.data; - if (iat && iat->adt && iat->adt->action) { - /* action is separate datablock, needs separate tag */ - DEG_id_tag_update(&iat->adt->action->id, ID_RECALC_ANIMATION); - } + rna_tag_animation_update(bmain, (ID *)ptr->id.data, true); } static PointerRNA rna_FCurve_active_modifier_get(PointerRNA *ptr) @@ -570,9 +583,9 @@ static PointerRNA rna_FCurve_active_modifier_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_FModifier, fcm); } -static void rna_FCurve_active_modifier_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_FCurve_active_modifier_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { FCurve *fcu = (FCurve *)ptr->data; set_active_fmodifier(&fcu->modifiers, (FModifier *)value.data); @@ -671,28 +684,16 @@ static void rna_FModifier_blending_range( *max = fcm->efra - fcm->sfra; } -static void rna_FModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_FModifier_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { ID *id = ptr->id.data; FModifier *fcm = (FModifier *)ptr->data; - AnimData *adt = BKE_animdata_from_id(id); - - DEG_id_tag_update(id, ID_RECALC_ANIMATION); - - /* tag datablock for time update so that animation is recalculated, - * as FModifiers affect how animation plays... - */ - DEG_id_tag_update(id, ID_RECALC_ANIMATION); - if (adt != NULL) { - if (adt->action != NULL) { - /* action is separate datablock, needs separate tag */ - DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION); - } - } if (fcm->curve && fcm->type == FMODIFIER_TYPE_CYCLES) { calchandles_fcurve(fcm->curve); } + + rna_tag_animation_update(bmain, id, true); } static void rna_FModifier_verify_data_update(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -909,14 +910,21 @@ static void rna_FModifierStepped_frame_end_set(PointerRNA *ptr, float value) } static BezTriple *rna_FKeyframe_points_insert( - FCurve *fcu, float frame, float value, int keyframe_type, int flag) + ID *id, FCurve *fcu, Main *bmain, float frame, float value, int keyframe_type, int flag) { int index = insert_vert_fcurve( fcu, frame, value, (char)keyframe_type, flag | INSERTKEY_NO_USERPREF); - return ((fcu->bezt) && (index >= 0)) ? (fcu->bezt + index) : NULL; + + if ((fcu->bezt) && (index >= 0)) { + rna_tag_animation_update(bmain, id, true); + + return fcu->bezt + index; + } + + return NULL; } -static void rna_FKeyframe_points_add(FCurve *fcu, int tot) +static void rna_FKeyframe_points_add(ID *id, FCurve *fcu, Main *bmain, int tot) { if (tot > 0) { BezTriple *bezt; @@ -933,13 +941,13 @@ static void rna_FKeyframe_points_add(FCurve *fcu, int tot) bezt->h1 = bezt->h2 = HD_AUTO_ANIM; bezt++; } + + rna_tag_animation_update(bmain, id, true); } } -static void rna_FKeyframe_points_remove(FCurve *fcu, - ReportList *reports, - PointerRNA *bezt_ptr, - bool do_fast) +static void rna_FKeyframe_points_remove( + ID *id, FCurve *fcu, Main *bmain, ReportList *reports, PointerRNA *bezt_ptr, bool do_fast) { BezTriple *bezt = bezt_ptr->data; int index = (int)(bezt - fcu->bezt); @@ -950,16 +958,19 @@ static void rna_FKeyframe_points_remove(FCurve *fcu, delete_fcurve_key(fcu, index, !do_fast); RNA_POINTER_INVALIDATE(bezt_ptr); + + rna_tag_animation_update(bmain, id, true); } -static FCM_EnvelopeData *rna_FModifierEnvelope_points_add(FModifier *fmod, - ReportList *reports, - float frame) +static FCM_EnvelopeData *rna_FModifierEnvelope_points_add( + ID *id, FModifier *fmod, Main *bmain, ReportList *reports, float frame) { FCM_EnvelopeData fed; FMod_Envelope *env = (FMod_Envelope *)fmod->data; int i; + rna_tag_animation_update(bmain, id, true); + /* init template data */ fed.min = -1.0f; fed.max = 1.0f; @@ -996,9 +1007,8 @@ static FCM_EnvelopeData *rna_FModifierEnvelope_points_add(FModifier *fmod, return (env->data + i); } -static void rna_FModifierEnvelope_points_remove(FModifier *fmod, - ReportList *reports, - PointerRNA *point) +static void rna_FModifierEnvelope_points_remove( + ID *id, FModifier *fmod, Main *bmain, ReportList *reports, PointerRNA *point) { FCM_EnvelopeData *cp = point->data; FMod_Envelope *env = (FMod_Envelope *)fmod->data; @@ -1011,6 +1021,8 @@ static void rna_FModifierEnvelope_points_remove(FModifier *fmod, return; } + rna_tag_animation_update(bmain, id, true); + if (env->totvert > 1) { /* move data after the removed point */ @@ -1034,19 +1046,9 @@ static void rna_FModifierEnvelope_points_remove(FModifier *fmod, RNA_POINTER_INVALIDATE(point); } -static void rna_Keyframe_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_Keyframe_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { - ID *id = ptr->id.data; - AnimData *adt = BKE_animdata_from_id(id); - - DEG_id_tag_update(id, ID_RECALC_ANIMATION); - - if (adt != NULL) { - if (adt->action != NULL) { - /* action is separate datablock, needs separate tag */ - DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION); - } - } + rna_tag_animation_update(bmain, (ID *)ptr->id.data, true); } #else @@ -1217,7 +1219,7 @@ static void rna_def_fmodifier_envelope_control_points(BlenderRNA *brna, Property func = RNA_def_function(srna, "add", "rna_FModifierEnvelope_points_add"); RNA_def_function_ui_description(func, "Add a control point to a FModifierEnvelope"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_float(func, "frame", 0.0f, @@ -1234,7 +1236,7 @@ static void rna_def_fmodifier_envelope_control_points(BlenderRNA *brna, Property func = RNA_def_function(srna, "remove", "rna_FModifierEnvelope_points_remove"); RNA_def_function_ui_description(func, "Remove a control-point from an FModifierEnvelope"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer( func, "point", "FModifierEnvelopeControlPoint", "", "Control-point to remove"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); @@ -2111,6 +2113,7 @@ static void rna_def_fcurve_keyframe_points(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "insert", "rna_FKeyframe_points_insert"); RNA_def_function_ui_description(func, "Add a keyframe point to a F-Curve"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); parm = RNA_def_float(func, "frame", 0.0f, @@ -2143,13 +2146,14 @@ static void rna_def_fcurve_keyframe_points(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "add", "rna_FKeyframe_points_add"); RNA_def_function_ui_description(func, "Add a keyframe point to a F-Curve"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); parm = RNA_def_int( func, "count", 1, 0, INT_MAX, "Number", "Number of points to add to the spline", 0, INT_MAX); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); func = RNA_def_function(srna, "remove", "rna_FKeyframe_points_remove"); RNA_def_function_ui_description(func, "Remove keyframe from an F-Curve"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "keyframe", "Keyframe", "", "Keyframe to remove"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); @@ -2361,6 +2365,7 @@ static void rna_def_fcurve(BlenderRNA *brna) /* -- update / recalculate -- */ func = RNA_def_function(srna, "update", "rna_FCurve_update_data_ex"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN); RNA_def_function_ui_description( func, "Ensure keyframes are sorted in chronological order and handles are set correctly"); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index c7071ee5155..a78eebd2618 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -281,9 +281,9 @@ static void set_parent(bGPDlayer *gpl, Object *par, const int type, const char * } /* set parent object and inverse matrix */ -static void rna_GPencilLayer_parent_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_GPencilLayer_parent_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bGPDlayer *gpl = (bGPDlayer *)ptr->data; Object *par = (Object *)value.data; @@ -377,9 +377,9 @@ static PointerRNA rna_GPencil_active_layer_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, NULL, NULL); } -static void rna_GPencil_active_layer_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_GPencil_active_layer_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bGPdata *gpd = ptr->id.data; @@ -652,6 +652,8 @@ static void rna_GPencil_stroke_point_pop(ID *id, static bGPDstroke *rna_GPencil_stroke_new(bGPDframe *frame) { bGPDstroke *stroke = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); + stroke->gradient_f = 1.0f; + ARRAY_SET_ITEMS(stroke->gradient_s, 1.0f, 1.0f); BLI_addtail(&frame->strokes, stroke); return stroke; @@ -844,7 +846,7 @@ static void rna_def_gpencil_stroke_point(BlenderRNA *brna) prop = RNA_def_property(srna, "pressure", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "pressure"); - RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_range(prop, 0.0f, FLT_MAX); RNA_def_property_ui_text(prop, "Pressure", "Pressure of tablet at point when drawing it"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); @@ -895,11 +897,11 @@ static void rna_def_gpencil_stroke_points_api(BlenderRNA *brna, PropertyRNA *cpr "pressure", 1.0f, 0.0f, - 1.0f, + FLT_MAX, "Pressure", "Pressure for newly created points", 0.0f, - 1.0f); + FLT_MAX); RNA_def_float(func, "strength", 1.0f, diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index afefa66e2ae..cca291a0aae 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -297,7 +297,7 @@ static void greasepencil_modifier_object_set(Object *self, # define RNA_GP_MOD_OBJECT_SET(_type, _prop, _obtype) \ static void rna_##_type##GpencilModifier_##_prop##_set( \ - struct ReportList *UNUSED(reports), PointerRNA *ptr, PointerRNA value) \ + PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \ { \ _type##GpencilModifierData *tmd = (_type##GpencilModifierData *)ptr->data; \ greasepencil_modifier_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \ @@ -309,9 +309,9 @@ RNA_GP_MOD_OBJECT_SET(Mirror, object, OB_EMPTY); # undef RNA_GP_MOD_OBJECT_SET -static void rna_HookGpencilModifier_object_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_HookGpencilModifier_object_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { HookGpencilModifierData *hmd = ptr->data; Object *ob = (Object *)value.data; diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 40c8c7e1582..d5cefaefbb1 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -332,7 +332,10 @@ static int rna_Image_frame_duration_get(PointerRNA *ptr) int duration = 1; if (BKE_image_has_anim(ima)) { - duration = IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN); + struct anim *anim = ((ImageAnim *)ima->anims.first)->anim; + if (anim) { + duration = IMB_anim_get_duration(anim, IMB_TC_RECORD_RUN); + } } else { /* acquire ensures ima->anim is set, if possible! */ @@ -479,9 +482,9 @@ static PointerRNA rna_render_slots_active_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_RenderSlot, render_slot); } -static void rna_render_slots_active_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_render_slots_active_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Image *image = (Image *)ptr->id.data; if (value.id.data == image) { @@ -680,12 +683,26 @@ static void rna_def_image(BlenderRNA *brna) "STRAIGHT", 0, "Straight", - "Transparent RGB and alpha pixels are unmodified"}, + "Store RGB and alpha channels separately with alpha acting as a mask, also known as " + "unassociated alpha. Commonly used by image editing applications and file formats like " + "PNG"}, {IMA_ALPHA_PREMUL, "PREMUL", 0, "Premultiplied", - "Transparent RGB pixels are multiplied by the alpha channel"}, + "Store RGB channels with alpha multipled in, also known as associated alpha. The natural " + "format for renders and used by file formats like OpenEXR"}, + {IMA_ALPHA_CHANNEL_PACKED, + "CHANNEL_PACKED", + 0, + "Channel Packed", + "Different images are packed in the RGB and alpha channels, and they should not " + "affect each other. Channel packing is commonly used by game engines to save memory"}, + {IMA_ALPHA_IGNORE, + "NONE", + 0, + "None", + "Ignore alpha channel from the file and make image fully opaque"}, {0, NULL, 0, NULL, NULL}, }; @@ -744,15 +761,6 @@ static void rna_def_image(BlenderRNA *brna) "Apply render part of display transformation when displaying this image on the screen"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); - prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMA_IGNORE_ALPHA); - RNA_def_property_ui_text( - prop, - "Use Alpha", - "Use the alpha channel information from the image or make image fully opaque"); - RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update"); - prop = RNA_def_property(srna, "use_deinterlace", PROP_BOOLEAN, PROP_NONE); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_DEINTERLACE); @@ -910,8 +918,10 @@ static void rna_def_image(BlenderRNA *brna) prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); RNA_def_property_enum_items(prop, alpha_mode_items); - RNA_def_property_ui_text( - prop, "Alpha Mode", "Representation of alpha information in the RGBA pixels"); + RNA_def_property_ui_text(prop, + "Alpha Mode", + "Representation of alpha in the image file, to convert to and from " + "when saving and loading the image"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update"); /* multiview */ diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 5b7388b49e7..1ea35ed4029 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -116,6 +116,16 @@ typedef struct BlenderDefRNA { ListBase allocs; struct StructRNA *laststruct; int error, silent, preprocess, verify, animate; + /* Keep last. */ +#ifndef RNA_RUNTIME + struct { + /** #RNA_def_property_update */ + struct { + int noteflag; + const char *updatefunc; + } property_update; + } fallback; +#endif } BlenderDefRNA; extern BlenderDefRNA DefRNA; @@ -278,9 +288,9 @@ int rna_object_shapekey_index_set(struct ID *id, PointerRNA value, int current); /* ViewLayer related functions defined in rna_scene.c but required in rna_layer.c */ void rna_def_freestyle_settings(struct BlenderRNA *brna); struct PointerRNA rna_FreestyleLineSet_linestyle_get(struct PointerRNA *ptr); -void rna_FreestyleLineSet_linestyle_set(struct ReportList *reports, - struct PointerRNA *ptr, - struct PointerRNA value); +void rna_FreestyleLineSet_linestyle_set(struct PointerRNA *ptr, + struct PointerRNA value, + struct ReportList *reports); struct FreestyleLineSet *rna_FreestyleSettings_lineset_add(struct ID *id, struct FreestyleSettings *config, struct Main *bmain, @@ -342,6 +352,10 @@ bool rna_GPencil_datablocks_obdata_poll(struct PointerRNA *ptr, const struct Poi char *rna_TextureSlot_path(struct PointerRNA *ptr); char *rna_Node_ImageUser_path(struct PointerRNA *ptr); +/* Set U.is_dirty and redraw. */ +void rna_userdef_is_dirty_update_impl(void); +void rna_userdef_is_dirty_update(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr); + /* API functions */ void RNA_api_action(StructRNA *srna); diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index 14d850be012..ccead626bb6 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -86,9 +86,9 @@ typedef const EnumPropertyItem *(*PropEnumItemFunc)(struct bContext *C, bool *r_free); typedef PointerRNA (*PropPointerGetFunc)(struct PointerRNA *ptr); typedef StructRNA *(*PropPointerTypeFunc)(struct PointerRNA *ptr); -typedef void (*PropPointerSetFunc)(struct ReportList *reports, - struct PointerRNA *ptr, - const PointerRNA value); +typedef void (*PropPointerSetFunc)(struct PointerRNA *ptr, + const PointerRNA value, + struct ReportList *reports); typedef bool (*PropPointerPollFunc)(struct PointerRNA *ptr, const PointerRNA value); typedef bool (*PropPointerPollFuncPy)(struct PointerRNA *ptr, const PointerRNA value, diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index 65233d5ccc1..c5997f27dc2 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -316,9 +316,9 @@ static PointerRNA rna_ShapeKey_relative_key_get(PointerRNA *ptr) return rna_object_shapekey_index_get(ptr->id.data, kb->relative); } -static void rna_ShapeKey_relative_key_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_ShapeKey_relative_key_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { KeyBlock *kb = (KeyBlock *)ptr->data; diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index 63bb091b406..55009aa660d 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -67,9 +67,9 @@ static PointerRNA rna_ViewLayer_active_layer_collection_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_LayerCollection, lc); } -static void rna_ViewLayer_active_layer_collection_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_ViewLayer_active_layer_collection_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { ViewLayer *view_layer = (ViewLayer *)ptr->data; LayerCollection *lc = (LayerCollection *)value.data; @@ -86,9 +86,9 @@ static PointerRNA rna_LayerObjects_active_object_get(PointerRNA *ptr) ptr, &RNA_Object, view_layer->basact ? view_layer->basact->object : NULL); } -static void rna_LayerObjects_active_object_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_LayerObjects_active_object_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { ViewLayer *view_layer = (ViewLayer *)ptr->data; if (value.data) @@ -411,6 +411,7 @@ static void rna_def_object_base(BlenderRNA *brna) prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BASE_HIDDEN); + RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); 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"); diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c index b98b21a7722..1ef5fb17ed8 100644 --- a/source/blender/makesrna/intern/rna_linestyle.c +++ b/source/blender/makesrna/intern/rna_linestyle.c @@ -356,9 +356,9 @@ static PointerRNA rna_LineStyle_active_texture_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_Texture, tex); } -static void rna_LineStyle_active_texture_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_LineStyle_active_texture_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data; diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index bd06cfc1936..aa8de7f23db 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -332,7 +332,11 @@ static Mesh *rna_Main_meshes_new(Main *bmain, const char *name) } /* copied from Mesh_getFromObject and adapted to RNA interface */ -static Mesh *rna_Main_meshes_new_from_object(Main *bmain, ReportList *reports, Object *object) +static Mesh *rna_Main_meshes_new_from_object(Main *bmain, + ReportList *reports, + Object *object, + bool preserve_all_data_layers, + Depsgraph *depsgraph) { switch (object->type) { case OB_FONT: @@ -346,7 +350,7 @@ static Mesh *rna_Main_meshes_new_from_object(Main *bmain, ReportList *reports, O return NULL; } - return BKE_mesh_new_from_object_to_bmain(bmain, object); + return BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object, preserve_all_data_layers); } static Light *rna_Main_lights_new(Main *bmain, const char *name, int type) @@ -966,6 +970,19 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "object", "Object", "", "Object to create mesh from"); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + RNA_def_boolean(func, + "preserve_all_data_layers", + false, + "", + "Preserve all data layers in the mesh, like UV maps and vertex groups. " + "By default Blender only computes the subset of data layers needed for viewport " + "display and rendering, for better performance"); + RNA_def_pointer( + func, + "depsgraph", + "Depsgraph", + "Dependency Graph", + "Evaluated dependency graph which is required when preserve_all_data_layers is true"); parm = RNA_def_pointer(func, "mesh", "Mesh", diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 563372dd4cf..7334c5baec0 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -116,9 +116,9 @@ static void rna_Mask_update_parent(Main *bmain, Scene *scene, PointerRNA *ptr) } /* note: this function exists only to avoid id refcounting */ -static void rna_MaskParent_id_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_MaskParent_id_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { MaskParent *mpar = (MaskParent *)ptr->data; @@ -193,9 +193,9 @@ static PointerRNA rna_Mask_layer_active_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_MaskLayer, masklay); } -static void rna_Mask_layer_active_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Mask_layer_active_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Mask *mask = (Mask *)ptr->id.data; MaskLayer *masklay = (MaskLayer *)value.data; @@ -230,9 +230,9 @@ static PointerRNA rna_MaskLayer_active_spline_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_MaskSpline, masklay->act_spline); } -static void rna_MaskLayer_active_spline_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_MaskLayer_active_spline_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { MaskLayer *masklay = (MaskLayer *)ptr->data; MaskSpline *spline = (MaskSpline *)value.data; @@ -251,9 +251,9 @@ static PointerRNA rna_MaskLayer_active_spline_point_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_MaskSplinePoint, masklay->act_point); } -static void rna_MaskLayer_active_spline_point_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_MaskLayer_active_spline_point_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { MaskLayer *masklay = (MaskLayer *)ptr->data; MaskSpline *spline; diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 0aa7ac67555..5038740b0aa 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -332,9 +332,9 @@ static int rna_GpencilColorData_is_fill_visible_get(PointerRNA *ptr) return ((pcolor->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (pcolor->fill_style > 0)); } -static void rna_GpencilColorData_stroke_image_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_GpencilColorData_stroke_image_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { MaterialGPencilStyle *pcolor = ptr->data; ID *id = value.data; @@ -343,9 +343,9 @@ static void rna_GpencilColorData_stroke_image_set(struct ReportList *UNUSED(repo pcolor->sima = (struct Image *)id; } -static void rna_GpencilColorData_fill_image_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_GpencilColorData_fill_image_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { MaterialGPencilStyle *pcolor = (MaterialGPencilStyle *)ptr->data; ID *id = value.data; diff --git a/source/blender/makesrna/intern/rna_mesh_utils.h b/source/blender/makesrna/intern/rna_mesh_utils.h index 2da35b55bd5..9c5b4f9d5b3 100644 --- a/source/blender/makesrna/intern/rna_mesh_utils.h +++ b/source/blender/makesrna/intern/rna_mesh_utils.h @@ -84,7 +84,7 @@ } \ \ static void rna_Mesh_##collection_name##_##active_type##_set( \ - struct ReportList *UNUSED(reports), PointerRNA *ptr, PointerRNA value) \ + PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \ { \ Mesh *me = rna_mesh(ptr); \ CustomData *data = rna_mesh_##customdata_type(ptr); \ diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index a7fe69134c8..4dca37c8bfd 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -722,7 +722,7 @@ static void modifier_object_set(Object *self, Object **ob_p, int type, PointerRN # define RNA_MOD_OBJECT_SET(_type, _prop, _obtype) \ static void rna_##_type##Modifier_##_prop##_set( \ - struct ReportList *UNUSED(reports), PointerRNA *ptr, PointerRNA value) \ + PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \ { \ _type##ModifierData *tmd = (_type##ModifierData *)ptr->data; \ modifier_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \ @@ -744,9 +744,9 @@ RNA_MOD_OBJECT_SET(Shrinkwrap, target, OB_MESH); RNA_MOD_OBJECT_SET(Shrinkwrap, auxTarget, OB_MESH); RNA_MOD_OBJECT_SET(SurfaceDeform, target, OB_MESH); -static void rna_HookModifier_object_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_HookModifier_object_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Object *owner = (Object *)ptr->id.data; HookModifierData *hmd = ptr->data; @@ -829,9 +829,9 @@ static PointerRNA rna_UVProjector_object_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_Object, *ob); } -static void rna_UVProjector_object_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_UVProjector_object_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Object **ob_p = (Object **)ptr->data; Object *ob = (Object *)value.data; @@ -1403,9 +1403,9 @@ static PointerRNA rna_ParticleInstanceModifier_particle_system_get(PointerRNA *p return rptr; } -static void rna_ParticleInstanceModifier_particle_system_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - const PointerRNA value) +static void rna_ParticleInstanceModifier_particle_system_set(PointerRNA *ptr, + const PointerRNA value, + struct ReportList *UNUSED(reports)) { ParticleInstanceModifierData *psmd = ptr->data; diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 17072a61bcd..d634a34bc5b 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -814,9 +814,9 @@ static PointerRNA rna_NodeTree_active_node_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_Node, node); } -static void rna_NodeTree_active_node_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - const PointerRNA value) +static void rna_NodeTree_active_node_set(PointerRNA *ptr, + const PointerRNA value, + struct ReportList *UNUSED(reports)) { bNodeTree *ntree = (bNodeTree *)ptr->data; bNode *node = (bNode *)value.data; @@ -1610,9 +1610,9 @@ static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create) return node->prop; } -static void rna_Node_parent_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Node_parent_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bNode *node = ptr->data; bNode *parent = value.data; @@ -2687,9 +2687,9 @@ static void rna_NodeGroup_update(Main *bmain, Scene *UNUSED(scene), PointerRNA * ED_node_tag_update_nodetree(bmain, ntree, node); } -static void rna_NodeGroup_node_tree_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - const PointerRNA value) +static void rna_NodeGroup_node_tree_set(PointerRNA *ptr, + const PointerRNA value, + struct ReportList *UNUSED(reports)) { bNodeTree *ntree = ptr->id.data; bNode *node = ptr->data; @@ -2797,9 +2797,9 @@ static void rna_Matte_t2_set(PointerRNA *ptr, float value) chroma->t2 = value; } -static void rna_Node_scene_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Node_scene_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bNode *node = (bNode *)ptr->data; @@ -3353,9 +3353,9 @@ static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr) return value; } -static void rna_ShaderNodePointDensity_psys_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_ShaderNodePointDensity_psys_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bNode *node = ptr->data; NodeShaderTexPointDensity *shader_point_density = node->storage; diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index b4453996095..e2f566cfdab 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -427,7 +427,7 @@ static void rna_Object_dependency_update(Main *bmain, Scene *UNUSED(scene), Poin WM_main_add_notifier(NC_OBJECT | ND_PARENT, ptr->id.data); } -static void rna_Object_data_set(struct ReportList *reports, PointerRNA *ptr, PointerRNA value) +static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, struct ReportList *reports) { Object *ob = (Object *)ptr->data; ID *id = value.data; @@ -534,9 +534,9 @@ static bool rna_Object_data_poll(PointerRNA *ptr, const PointerRNA value) return true; } -static void rna_Object_parent_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Object_parent_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Object *ob = (Object *)ptr->data; Object *par = (Object *)value.data; @@ -621,9 +621,9 @@ static const EnumPropertyItem *rna_Object_instance_type_itemf(bContext *UNUSED(C return item; } -static void rna_Object_dup_collection_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Object_dup_collection_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Object *ob = (Object *)ptr->data; Collection *grp = (Collection *)value.data; @@ -899,9 +899,9 @@ static PointerRNA rna_Object_active_material_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_Material, ma); } -static void rna_Object_active_material_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Object_active_material_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Object *ob = (Object *)ptr->id.data; @@ -1100,9 +1100,9 @@ static PointerRNA rna_MaterialSlot_material_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_Material, ma); } -static void rna_MaterialSlot_material_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_MaterialSlot_material_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Object *ob = (Object *)ptr->id.data; int index = (Material **)ptr->data - ob->mat; @@ -1290,9 +1290,9 @@ static PointerRNA rna_Object_active_constraint_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_Constraint, con); } -static void rna_Object_active_constraint_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Object_active_constraint_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Object *ob = (Object *)ptr->id.data; BKE_constraints_active_set(&ob->constraints, (bConstraint *)value.data); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 7362f6ba610..f5c83df0f45 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -375,7 +375,10 @@ static void rna_Object_camera_fit_coords( } /* copied from Mesh_getFromObject and adapted to RNA interface */ -static Mesh *rna_Object_to_mesh(Object *object, ReportList *reports) +static Mesh *rna_Object_to_mesh(Object *object, + ReportList *reports, + bool preserve_all_data_layers, + Depsgraph *depsgraph) { /* TODO(sergey): Make it more re-usable function, de-duplicate with * rna_Main_meshes_new_from_object. */ @@ -391,7 +394,7 @@ static Mesh *rna_Object_to_mesh(Object *object, ReportList *reports) return NULL; } - return BKE_object_to_mesh(object); + return BKE_object_to_mesh(depsgraph, object, preserve_all_data_layers); } static void rna_Object_to_mesh_clear(Object *object) @@ -703,7 +706,13 @@ void rna_Object_me_eval_info( static bool rna_Object_update_from_editmode(Object *ob, Main *bmain) { /* fail gracefully if we aren't in edit-mode. */ - return ED_object_editmode_load(bmain, ob); + const bool result = ED_object_editmode_load(bmain, ob); + if (result) { + /* Loading edit mesh to mesh changes geometry, and scripts might expect it to be properly + * informed about changes. */ + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + } + return result; } #else /* RNA_RUNTIME */ @@ -898,6 +907,19 @@ void RNA_api_object(StructRNA *srna) "data-block. To force free it use to_mesh_clear(). " "The result is temporary and can not be used by objects from the main database"); RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_boolean(func, + "preserve_all_data_layers", + false, + "", + "Preserve all data layers in the mesh, like UV maps and vertex groups. " + "By default Blender only computes the subset of data layers needed for viewport " + "display and rendering, for better performance"); + RNA_def_pointer( + func, + "depsgraph", + "Depsgraph", + "Dependency Graph", + "Evaluated dependency graph which is required when preserve_all_data_layers is true"); parm = RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh created from object"); RNA_def_function_return(func, parm); diff --git a/source/blender/makesrna/intern/rna_palette.c b/source/blender/makesrna/intern/rna_palette.c index cd6ed9bc7e4..9af6387389c 100644 --- a/source/blender/makesrna/intern/rna_palette.c +++ b/source/blender/makesrna/intern/rna_palette.c @@ -74,9 +74,9 @@ static PointerRNA rna_Palette_active_color_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, NULL, NULL); } -static void rna_Palette_active_color_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Palette_active_color_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Palette *palette = ptr->data; PaletteColor *color = value.data; diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 9ef5bcd4fd1..a3178e0407f 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -534,6 +534,11 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, int uv_no, float r_uv[2]) { + if (modifier->mesh_final == NULL) { + BKE_report(reports, RPT_ERROR, "Object was not yet evaluated"); + zero_v2(r_uv); + return; + } if (!CustomData_has_layer(&modifier->mesh_final->ldata, CD_MLOOPUV)) { BKE_report(reports, RPT_ERROR, "Mesh has no UV data"); zero_v2(r_uv); @@ -792,9 +797,9 @@ static PointerRNA rna_particle_settings_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_ParticleSettings, part); } -static void rna_particle_settings_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_particle_settings_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Object *ob = ptr->id.data; ParticleSystem *psys = (ParticleSystem *)ptr->data; @@ -1320,9 +1325,9 @@ static PointerRNA rna_ParticleSettings_active_texture_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_Texture, tex); } -static void rna_ParticleSettings_active_texture_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_ParticleSettings_active_texture_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { ParticleSettings *part = (ParticleSettings *)ptr->data; diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 7b91248feac..3ab41f72322 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -373,9 +373,9 @@ static void rna_Itasc_update_rebuild(Main *bmain, Scene *scene, PointerRNA *ptr) rna_Itasc_update(bmain, scene, ptr); } -static void rna_PoseChannel_bone_custom_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_PoseChannel_bone_custom_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bPoseChannel *pchan = (bPoseChannel *)ptr->data; @@ -404,9 +404,9 @@ static PointerRNA rna_PoseChannel_bone_group_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_BoneGroup, grp); } -static void rna_PoseChannel_bone_group_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_PoseChannel_bone_group_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Object *ob = (Object *)ptr->id.data; bPose *pose = (ob) ? ob->pose : NULL; @@ -447,9 +447,9 @@ static PointerRNA rna_Pose_active_bone_group_get(PointerRNA *ptr) ptr, &RNA_BoneGroup, BLI_findlink(&pose->agroups, pose->active_group - 1)); } -static void rna_Pose_active_bone_group_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Pose_active_bone_group_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bPose *pose = (bPose *)ptr->data; pose->active_group = BLI_findindex(&pose->agroups, value.data) + 1; @@ -538,9 +538,9 @@ static PointerRNA rna_PoseChannel_active_constraint_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_Constraint, con); } -static void rna_PoseChannel_active_constraint_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_PoseChannel_active_constraint_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bPoseChannel *pchan = (bPoseChannel *)ptr->data; BKE_constraints_active_set(&pchan->constraints, (bConstraint *)value.data); @@ -778,9 +778,9 @@ static bPoseChannel *rna_PoseChannel_ensure_own_pchan(Object *ob, return ref_pchan; } -static void rna_PoseChannel_custom_shape_transform_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_PoseChannel_custom_shape_transform_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { bPoseChannel *pchan = (bPoseChannel *)ptr->data; Object *ob = (Object *)ptr->id.data; diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index c5eff47c3aa..b8d42397841 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -2373,7 +2373,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain), switch (override_op) { case IDOVERRIDESTATIC_OP_REPLACE: - RNA_property_pointer_set(NULL, ptr_dst, prop_dst, value); + RNA_property_pointer_set(ptr_dst, prop_dst, value, NULL); break; default: BLI_assert(0 && "Unsupported RNA override operation on pointer"); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 55e2428235f..1dc9e71e87c 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -773,9 +773,9 @@ static PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter) /* End of read-only Iterator of all the scene objects. */ -static void rna_Scene_set_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Scene_set_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Scene *scene = (Scene *)ptr->data; Scene *set = (Scene *)value.data; @@ -972,9 +972,9 @@ static PointerRNA rna_Scene_active_keying_set_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_KeyingSet, ANIM_scene_get_active_keyingset(scene)); } -static void rna_Scene_active_keying_set_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Scene_active_keying_set_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { Scene *scene = (Scene *)ptr->data; KeyingSet *ks = (KeyingSet *)value.data; @@ -1440,9 +1440,9 @@ static PointerRNA rna_RenderSettings_active_view_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_SceneRenderView, srv); } -static void rna_RenderSettings_active_view_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_RenderSettings_active_view_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { RenderData *rd = (RenderData *)ptr->data; SceneRenderView *srv = (SceneRenderView *)value.data; @@ -2047,9 +2047,9 @@ PointerRNA rna_FreestyleLineSet_linestyle_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineStyle, lineset->linestyle); } -void rna_FreestyleLineSet_linestyle_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { FreestyleLineSet *lineset = (FreestyleLineSet *)ptr->data; @@ -2645,23 +2645,6 @@ static void rna_def_tool_settings(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; - static const EnumPropertyItem edge_tag_items[] = { - {EDGE_MODE_SELECT, "SELECT", 0, "Select", ""}, - {EDGE_MODE_TAG_SEAM, "SEAM", 0, "Tag Seam", ""}, - {EDGE_MODE_TAG_SHARP, "SHARP", 0, "Tag Sharp", ""}, - {EDGE_MODE_TAG_CREASE, "CREASE", 0, "Tag Crease", ""}, - {EDGE_MODE_TAG_BEVEL, "BEVEL", 0, "Tag Bevel", ""}, - {EDGE_MODE_TAG_FREESTYLE, "FREESTYLE", 0, "Tag Freestyle Edge Mark", ""}, - {0, NULL, 0, NULL, NULL}, - }; - - static EnumPropertyItem mod_weighted_strength[] = { - {FACE_STRENGTH_WEAK, "Weak", 0, "Weak", ""}, - {FACE_STRENGTH_MEDIUM, "Medium", 0, "Medium", ""}, - {FACE_STRENGTH_STRONG, "Strong", 0, "Strong", ""}, - {0, NULL, 0, NULL, NULL}, - }; - static const EnumPropertyItem draw_groupuser_items[] = { {OB_DRAW_GROUPUSER_NONE, "NONE", 0, "None", ""}, {OB_DRAW_GROUPUSER_ACTIVE, @@ -2903,8 +2886,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "double_threshold", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "doublimit"); - RNA_def_property_ui_text( - prop, "Double Threshold", "Limit for removing duplicates and 'Auto Merge'"); + RNA_def_property_ui_text(prop, "Merge Threshold", "Threshold distance for Auto Merge"); RNA_def_property_range(prop, 0.0, 1.0); RNA_def_property_ui_range(prop, 0.0, 0.1, 0.01, 6); @@ -2925,7 +2907,8 @@ static void rna_def_tool_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_mesh_automerge", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "automerge", 0); RNA_def_property_ui_text( - prop, "AutoMerge Editing", "Automatically merge vertices moved to the same location"); + prop, "Auto Merge", "Automatically merge vertices moved to the same location"); + RNA_def_property_ui_icon(prop, ICON_AUTOMERGE_OFF, 1); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ prop = RNA_def_property(srna, "use_snap", PROP_BOOLEAN, PROP_NONE); @@ -3203,13 +3186,6 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "vgroup_weight"); RNA_def_property_ui_text(prop, "Vertex Group Weight", "Weight to assign in vertex groups"); - /* use with MESH_OT_shortest_path_pick */ - prop = RNA_def_property(srna, "edge_path_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "edge_mode"); - RNA_def_property_enum_items(prop, edge_tag_items); - RNA_def_property_ui_text( - prop, "Edge Tag Mode", "The edge flag to tag when selecting the shortest path"); - prop = RNA_def_property(srna, "use_edge_path_live_unwrap", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_mode_live_unwrap", 1); RNA_def_property_ui_text(prop, "Live Unwrap", "Changing edges seam re-calculates UV unwrap"); @@ -3218,10 +3194,6 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Normal Vector", "Normal Vector used to copy, add or multiply"); RNA_def_property_ui_range(prop, -10000.0, 10000.0, 1, 3); - prop = RNA_def_property(srna, "face_strength", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, mod_weighted_strength); - RNA_def_property_ui_text(prop, "Face Strength", "Set strength of face to specified value"); - /* Unified Paint Settings */ prop = RNA_def_property(srna, "unified_paint_settings", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); @@ -6663,7 +6635,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna) RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC); prop = RNA_def_property(srna, "gi_filter_quality", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_float_default(prop, 3.0f); RNA_def_property_ui_text( prop, "Filter Quality", "Take more samples during cubemap filtering to remove artifacts"); RNA_def_property_range(prop, 1.0f, 8.0f); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 687ba96abc2..5a80dc5fe8c 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -106,12 +106,14 @@ static void rna_SequenceElement_update(Main *UNUSED(bmain), Scene *UNUSED(scene) /* slow but we can't avoid! */ seq = BKE_sequencer_from_elem(&ed->seqbase, se); if (seq) { - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_raw(scene, seq); } } } -static void rna_Sequence_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_Sequence_invalidate_raw_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *ptr) { Scene *scene = (Scene *)ptr->id.data; Editing *ed = BKE_sequencer_editing_get(scene, false); @@ -119,7 +121,35 @@ static void rna_Sequence_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point if (ed) { Sequence *seq = (Sequence *)ptr->data; - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_raw(scene, seq); + } +} + +static void rna_Sequence_invalidate_preprocessed_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *ptr) +{ + Scene *scene = (Scene *)ptr->id.data; + Editing *ed = BKE_sequencer_editing_get(scene, false); + + if (ed) { + Sequence *seq = (Sequence *)ptr->data; + + BKE_sequence_invalidate_cache_preprocessed(scene, seq); + } +} + +static void rna_Sequence_invalidate_composite_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *ptr) +{ + Scene *scene = (Scene *)ptr->id.data; + Editing *ed = BKE_sequencer_editing_get(scene, false); + + if (ed) { + Sequence *seq = (Sequence *)ptr->data; + + BKE_sequence_invalidate_cache_composite(scene, seq); } } @@ -141,6 +171,7 @@ static void rna_SequenceEditor_update_cache(Main *UNUSED(bmain), Editing *ed = scene->ed; BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); + BKE_sequencer_cache_cleanup(scene); } static void rna_SequenceEditor_sequences_all_next(CollectionPropertyIterator *iter) @@ -193,7 +224,7 @@ static void rna_SequenceEditor_elements_begin(CollectionPropertyIterator *iter, static void rna_Sequence_views_format_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - rna_Sequence_update(bmain, scene, ptr); + rna_Sequence_invalidate_raw_update(bmain, scene, ptr); } static void do_sequence_frame_change_update(Scene *scene, Sequence *seq) @@ -227,7 +258,7 @@ static void rna_Sequence_frame_change_update(Main *bmain, Scene *UNUSED(scene), { Scene *scene = (Scene *)ptr->id.data; do_sequence_frame_change_update(scene, (Sequence *)ptr->data); - rna_Sequence_update(bmain, scene, ptr); + rna_Sequence_invalidate_preprocessed_update(bmain, scene, ptr); } static void rna_Sequence_start_frame_set(PointerRNA *ptr, int value) @@ -412,7 +443,7 @@ static void rna_SequenceTransform_update(Main *UNUSED(bmain), Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_transform(ed, ptr->data); - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); } static int crop_seq_cmp_cb(Sequence *seq, void *arg_pt) @@ -462,12 +493,12 @@ static void rna_SequenceCrop_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_crop(ed, ptr->data); - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); } -static void rna_Sequence_text_font_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA ptr_value) +static void rna_Sequence_text_font_set(PointerRNA *ptr, + PointerRNA ptr_value, + struct ReportList *UNUSED(reports)) { Sequence *seq = ptr->data; TextVars *data = seq->effectdata; @@ -748,26 +779,24 @@ static void rna_SequenceElement_filename_set(PointerRNA *ptr, const char *value) } # endif -static void rna_Sequence_update_reopen_files(Main *UNUSED(bmain), - Scene *UNUSED(scene), - PointerRNA *ptr) +static void rna_Sequence_reopen_files_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->id.data; Editing *ed = BKE_sequencer_editing_get(scene, false); BKE_sequencer_free_imbuf(scene, &ed->seqbase, false); + rna_Sequence_invalidate_raw_update(bmain, scene, ptr); if (RNA_struct_is_a(ptr->type, &RNA_SoundSequence)) BKE_sequencer_update_sound_bounds(scene, ptr->data); } -static void rna_Sequence_mute_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_Sequence_mute_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->id.data; Editing *ed = BKE_sequencer_editing_get(scene, false); BKE_sequencer_update_muting(ed); - rna_Sequence_update(bmain, scene, ptr); } static void rna_Sequence_filepath_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) @@ -776,16 +805,15 @@ static void rna_Sequence_filepath_update(Main *bmain, Scene *UNUSED(scene), Poin Sequence *seq = (Sequence *)(ptr->data); BKE_sequence_reload_new_file(scene, seq, true); BKE_sequence_calc(scene, seq); - rna_Sequence_update(bmain, scene, ptr); + rna_Sequence_invalidate_raw_update(bmain, scene, ptr); } -static void rna_Sequence_sound_update(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_Sequence_sound_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Sequence *seq = (Sequence *)ptr->data; if (seq->sound != NULL) { BKE_sound_update_scene_sound(seq->scene_sound, seq->sound); } - rna_Sequence_update(bmain, scene, ptr); } static int seqproxy_seq_cmp_cb(Sequence *seq, void *arg_pt) @@ -826,7 +854,7 @@ static void rna_SequenceProxy_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_proxy(ed, ptr->data); - BKE_sequence_invalidate_cache(scene, seq); + BKE_sequence_invalidate_cache_raw(scene, seq); } /* do_versions? */ @@ -922,10 +950,7 @@ static void rna_SequenceColorBalance_update(Main *UNUSED(bmain), SequenceModifierData *smd; Sequence *seq = sequence_get_by_colorbalance(ed, ptr->data, &smd); - if (smd == NULL) - BKE_sequence_invalidate_cache(scene, seq); - else - BKE_sequence_invalidate_cache_for_modifier(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); } static void rna_SequenceEditor_overlay_lock_set(PointerRNA *ptr, bool value) @@ -1079,7 +1104,7 @@ static void rna_SequenceModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = sequence_get_by_modifier(ed, ptr->data); - BKE_sequence_invalidate_cache_for_modifier(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); } static bool rna_SequenceModifier_otherSequence_poll(PointerRNA *ptr, PointerRNA value) @@ -1110,7 +1135,7 @@ static SequenceModifierData *rna_Sequence_modifier_new( smd = BKE_sequence_modifier_new(seq, name, type); - BKE_sequence_invalidate_cache_for_modifier(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); @@ -1132,7 +1157,7 @@ static void rna_Sequence_modifier_remove(Sequence *seq, } RNA_POINTER_INVALIDATE(smd_ptr); - BKE_sequence_invalidate_cache_for_modifier(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); } @@ -1143,7 +1168,7 @@ static void rna_Sequence_modifier_clear(Sequence *seq, bContext *C) BKE_sequence_modifier_clear(seq); - BKE_sequence_invalidate_cache_for_modifier(scene, seq); + BKE_sequence_invalidate_cache_preprocessed(scene, seq); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); } @@ -1342,12 +1367,12 @@ static void rna_def_strip_proxy(BlenderRNA *brna) prop = RNA_def_property(srna, "use_proxy_custom_directory", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "storage", SEQ_STORAGE_PROXY_CUSTOM_DIR); RNA_def_property_ui_text(prop, "Proxy Custom Directory", "Use a custom directory to store data"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "use_proxy_custom_file", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "storage", SEQ_STORAGE_PROXY_CUSTOM_FILE); RNA_def_property_ui_text(prop, "Proxy Custom File", "Use a custom file to read proxy data from"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); } static void rna_def_color_balance(BlenderRNA *brna) @@ -1555,7 +1580,7 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_property_enum_items(prop, seq_type_items); RNA_def_property_ui_text(prop, "Type", ""); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SEQUENCE); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); /* flags */ prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); @@ -1596,7 +1621,8 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_property_int_funcs( prop, "rna_Sequence_frame_length_get", "rna_Sequence_frame_length_set", NULL); RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "frame_duration", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "len"); @@ -1612,7 +1638,8 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_property_int_funcs( prop, NULL, "rna_Sequence_start_frame_set", NULL); /* overlap tests and calc_seq_disp */ RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "frame_final_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "startdisp"); @@ -1625,7 +1652,8 @@ static void rna_def_sequence(BlenderRNA *brna) /* overlap tests and calc_seq_disp */ RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_start_frame_final_set", NULL); RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "frame_final_end", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "enddisp"); @@ -1635,7 +1663,8 @@ static void rna_def_sequence(BlenderRNA *brna) /* overlap tests and calc_seq_disp */ RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_end_frame_final_set", NULL); RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "frame_offset_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "startofs"); @@ -1671,14 +1700,16 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_property_range(prop, 1, MAXSEQ); RNA_def_property_ui_text(prop, "Channel", "Y position of the sequence strip"); RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_channel_set", NULL); /* overlap test */ - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "use_linear_modifiers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_LINEAR_MODIFIERS); RNA_def_property_ui_text(prop, "Use Linear Modifiers", "Calculate modifiers in linear space instead of sequencer's space"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); /* blending */ @@ -1687,7 +1718,8 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_property_enum_items(prop, blend_mode_items); RNA_def_property_ui_text( prop, "Blend Mode", "Method for controlling how the strip combines with other strips"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "blend_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -1695,14 +1727,16 @@ static void rna_def_sequence(BlenderRNA *brna) prop, "Blend Opacity", "Percentage of how much the strip's colors affect other strips"); /* stupid 0-100 -> 0-1 */ RNA_def_property_float_funcs(prop, "rna_Sequence_opacity_get", "rna_Sequence_opacity_set", NULL); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_composite_update"); prop = RNA_def_property(srna, "effect_fader", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); RNA_def_property_float_sdna(prop, NULL, "effect_fader"); RNA_def_property_ui_text(prop, "Effect fader position", "Custom fade value"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "use_default_fade", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_EFFECT_DEFAULT_FADE); @@ -1711,7 +1745,8 @@ static void rna_def_sequence(BlenderRNA *brna) "Use Default Fade", "Fade effect using the built-in default (usually make transition as long as " "effect strip)"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "speed_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "speed_fader"); @@ -1720,7 +1755,8 @@ static void rna_def_sequence(BlenderRNA *brna) "Speed factor", "Multiply the current speed of the sequence with this number or remap current frame " "to this frame"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); /* modifiers */ prop = RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE); @@ -1918,40 +1954,41 @@ static void rna_def_filter_video(StructRNA *srna) prop = RNA_def_property(srna, "use_deinterlace", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_FILTERY); RNA_def_property_ui_text(prop, "Deinterlace", "Remove fields from video movies"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update_reopen_files"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_reopen_files_update"); prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, alpha_mode_items); RNA_def_property_ui_text( prop, "Alpha Mode", "Representation of alpha information in the RGBA pixels"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_FLIPX); RNA_def_property_ui_text(prop, "Flip X", "Flip on the X axis"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "use_flip_y", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_FLIPY); RNA_def_property_ui_text(prop, "Flip Y", "Flip on the Y axis"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "use_float", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_MAKE_FLOAT); RNA_def_property_ui_text(prop, "Convert Float", "Convert input to float data"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "use_reverse_frames", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_REVERSE_FRAMES); RNA_def_property_ui_text(prop, "Flip Time", "Reverse frame order"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "color_multiply", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "mul"); RNA_def_property_range(prop, 0.0f, 20.0f); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Multiply Colors", ""); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "color_saturation", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "sat"); @@ -1959,18 +1996,19 @@ static void rna_def_filter_video(StructRNA *srna) RNA_def_property_ui_range(prop, 0.0f, 2.0f, 3, 3); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Saturation", "Adjust the intensity of the input's color"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "strobe", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 1.0f, 30.0f); RNA_def_property_ui_text(prop, "Strobe", "Only display every nth frame"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "use_translation", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_TRANSFORM); RNA_def_property_ui_text(prop, "Use Translation", "Translate image before processing"); RNA_def_property_boolean_funcs(prop, NULL, "rna_Sequence_use_translation_set"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "transform", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "strip->transform"); @@ -1980,7 +2018,7 @@ static void rna_def_filter_video(StructRNA *srna) RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_CROP); RNA_def_property_ui_text(prop, "Use Crop", "Crop image before processing"); RNA_def_property_boolean_funcs(prop, NULL, "rna_Sequence_use_crop_set"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "crop", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "strip->crop"); @@ -2012,7 +2050,8 @@ static void rna_def_input(StructRNA *srna) RNA_def_property_int_funcs( prop, NULL, "rna_Sequence_anim_startofs_final_set", NULL); /* overlap tests */ RNA_def_property_ui_text(prop, "Animation Start Offset", "Animation start offset (trim start)"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "animation_offset_end", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "anim_endofs"); @@ -2020,7 +2059,8 @@ static void rna_def_input(StructRNA *srna) RNA_def_property_int_funcs( prop, NULL, "rna_Sequence_anim_endofs_final_set", NULL); /* overlap tests */ RNA_def_property_ui_text(prop, "Animation End Offset", "Animation end offset (trim end)"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); } static void rna_def_effect_inputs(StructRNA *srna, int count) @@ -2087,7 +2127,7 @@ static void rna_def_image(BlenderRNA *brna) prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_sdna(prop, NULL, "strip->dir"); RNA_def_property_ui_text(prop, "Directory", ""); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "elements", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "strip->stripdata", NULL); @@ -2161,25 +2201,25 @@ static void rna_def_scene(BlenderRNA *brna) prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Scene", "Scene that this sequence uses"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "scene_camera", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Camera_object_poll"); RNA_def_property_ui_text(prop, "Camera Override", "Override the scenes active camera"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "use_sequence", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SCENE_STRIPS); RNA_def_property_ui_text( prop, "Use Sequence", "Use scenes sequence strips directly, instead of rendering"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "use_grease_pencil", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_SCENE_NO_GPENCIL); RNA_def_property_ui_text( prop, "Use Grease Pencil", "Show Grease Pencil strokes in OpenGL previews"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); rna_def_filter_video(srna); rna_def_proxy(srna); @@ -2202,7 +2242,7 @@ static void rna_def_movie(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "anim_preseek"); RNA_def_property_range(prop, 0, 50); RNA_def_property_ui_text(prop, "MPEG Preseek", "For MPEG movies, preseek this many frames"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); prop = RNA_def_property(srna, "stream_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "streamindex"); @@ -2211,7 +2251,7 @@ static void rna_def_movie(BlenderRNA *brna) prop, "Stream Index", "For files with several movie streams, use the stream with the given index"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update_reopen_files"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_reopen_files_update"); prop = RNA_def_property(srna, "elements", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "strip->stripdata", NULL); @@ -2284,12 +2324,12 @@ static void rna_def_movieclip(BlenderRNA *brna) prop = RNA_def_property(srna, "undistort", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "clip_flag", SEQ_MOVIECLIP_RENDER_UNDISTORTED); RNA_def_property_ui_text(prop, "Undistort Clip", "Use the undistorted version of the clip"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); prop = RNA_def_property(srna, "stabilize2d", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "clip_flag", SEQ_MOVIECLIP_RENDER_STABILIZED); RNA_def_property_ui_text(prop, "Stabilize 2D Clip", "Use the 2D stabilized version of the clip"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); rna_def_filter_video(srna); rna_def_input(srna); @@ -2308,7 +2348,7 @@ static void rna_def_mask(BlenderRNA *brna) prop = RNA_def_property(srna, "mask", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Mask", "Mask that this sequence uses"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); rna_def_filter_video(srna); rna_def_input(srna); @@ -2337,7 +2377,7 @@ static void rna_def_sound(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Volume", "Playback volume of the sound"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND); RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_volume_set", NULL); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); prop = RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pitch"); @@ -2345,14 +2385,14 @@ static void rna_def_sound(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND); RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pitch_set", NULL); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); prop = RNA_def_property(srna, "pan", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "pan"); RNA_def_property_range(prop, -2.0f, 2.0f); RNA_def_property_ui_text(prop, "Pan", "Playback panning of the sound (only for Mono sources)"); RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pan_set", NULL); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); prop = RNA_def_property(srna, "show_waveform", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_AUDIO_DRAW_WAVEFORM); @@ -2385,7 +2425,7 @@ static void rna_def_multicam(StructRNA *srna) RNA_def_property_int_sdna(prop, NULL, "multicam_source"); RNA_def_property_range(prop, 0, MAXSEQ - 1); RNA_def_property_ui_text(prop, "Multicam Source Channel", ""); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update"); rna_def_input(srna); } @@ -2417,25 +2457,29 @@ static void rna_def_wipe(StructRNA *srna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text( prop, "Blur Width", "Width of the blur edge, in percentage relative to the image size"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE); RNA_def_property_range(prop, DEG2RADF(-90.0f), DEG2RADF(90.0f)); RNA_def_property_ui_text(prop, "Angle", "Edge angle"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "direction", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "forward"); RNA_def_property_enum_items(prop, wipe_direction_items); RNA_def_property_ui_text(prop, "Direction", "Wipe direction"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "transition_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "wipetype"); RNA_def_property_enum_items(prop, wipe_type_items); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SEQUENCE); RNA_def_property_ui_text(prop, "Transition Type", ""); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); } static void rna_def_glow(StructRNA *srna) @@ -2448,36 +2492,42 @@ static void rna_def_glow(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "fMini"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Threshold", "Minimum intensity to trigger a glow"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "clamp", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "fClamp"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Clamp", "Brightness limit of intensity"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "boost_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fBoost"); RNA_def_property_range(prop, 0.0f, 10.0f); RNA_def_property_ui_text(prop, "Boost Factor", "Brightness multiplier"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "blur_radius", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "dDist"); RNA_def_property_range(prop, 0.5f, 20.0f); RNA_def_property_ui_text(prop, "Blur Distance", "Radius of glow effect"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "quality", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dQuality"); RNA_def_property_range(prop, 1, 5); RNA_def_property_ui_text(prop, "Quality", "Accuracy of the blur effect"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "use_only_boost", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "bNoComp", 0); RNA_def_property_ui_text(prop, "Only Boost", "Show the glow buffer only"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); } static void rna_def_transform(StructRNA *srna) @@ -2503,49 +2553,57 @@ static void rna_def_transform(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "ScalexIni"); RNA_def_property_ui_text(prop, "Scale X", "Amount to scale the input in the X axis"); RNA_def_property_ui_range(prop, 0, 10, 3, 6); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "scale_start_y", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "ScaleyIni"); RNA_def_property_ui_text(prop, "Scale Y", "Amount to scale the input in the Y axis"); RNA_def_property_ui_range(prop, 0, 10, 3, 6); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "use_uniform_scale", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uniform_scale", 0); RNA_def_property_ui_text(prop, "Uniform Scale", "Scale uniformly, preserving aspect ratio"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "translate_start_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "xIni"); RNA_def_property_ui_text(prop, "Translate X", "Amount to move the input on the X axis"); RNA_def_property_ui_range(prop, -4000.0f, 4000.0f, 3, 6); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "translate_start_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "yIni"); RNA_def_property_ui_text(prop, "Translate Y", "Amount to move the input on the Y axis"); RNA_def_property_ui_range(prop, -4000.0f, 4000.0f, 3, 6); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "rotation_start", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rotIni"); RNA_def_property_ui_text(prop, "Rotation", "Degrees to rotate the input"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "translation_unit", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "percent"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */ RNA_def_property_enum_items(prop, translation_unit_items); RNA_def_property_ui_text(prop, "Translation Unit", "Unit of measure to translate the input"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, interpolation_items); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */ RNA_def_property_ui_text( prop, "Interpolation", "Method to determine how missing pixels are created"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); } static void rna_def_solid_color(StructRNA *srna) @@ -2557,7 +2615,8 @@ static void rna_def_solid_color(StructRNA *srna) prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "col"); RNA_def_property_ui_text(prop, "Color", "Effect Strip color"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); } static void rna_def_speed_control(StructRNA *srna) @@ -2572,19 +2631,22 @@ static void rna_def_speed_control(StructRNA *srna) RNA_def_property_ui_text( prop, "Multiply Speed", "Multiply the resulting speed after the speed factor"); RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, -1); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "use_as_speed", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", SEQ_SPEED_INTEGRATE); RNA_def_property_ui_text( prop, "Use as speed", "Interpret the value as speed instead of a frame number"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "use_scale_to_length", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", SEQ_SPEED_COMPRESS_IPO_Y); RNA_def_property_ui_text( prop, "Scale to length", "Scale values from 0.0 to 1.0 to target sequence length"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); } static void rna_def_gaussian_blur(StructRNA *srna) @@ -2595,12 +2657,14 @@ static void rna_def_gaussian_blur(StructRNA *srna) prop = RNA_def_property(srna, "size_x", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_ui_text(prop, "Size X", "Size of the blur along X axis"); RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, -1); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "size_y", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_ui_text(prop, "Size Y", "Size of the blur along Y axis"); RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, -1); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); } static void rna_def_text(StructRNA *srna) @@ -2628,59 +2692,69 @@ static void rna_def_text(StructRNA *srna) RNA_def_property_ui_text(prop, "Font", "Font of the text. Falls back to the UI font by default"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_pointer_funcs(prop, NULL, "rna_Sequence_text_font_set", NULL, NULL); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "font_size", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "text_size"); RNA_def_property_ui_text(prop, "Size", "Size of the text"); RNA_def_property_range(prop, 0.0, 2000); RNA_def_property_ui_range(prop, 0.0f, 1000, 1, -1); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "color"); RNA_def_property_ui_text(prop, "Color", "Text color"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "shadow_color"); RNA_def_property_ui_text(prop, "Shadow Color", ""); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "loc"); RNA_def_property_ui_text(prop, "Location", "Location of the text"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); RNA_def_property_ui_range(prop, 0.0, 1.0, 1, -1); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "wrap_width", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "wrap_width"); RNA_def_property_ui_text(prop, "Wrap Width", "Word wrap width as factor, zero disables"); RNA_def_property_range(prop, 0, FLT_MAX); RNA_def_property_ui_range(prop, 0.0, 1.0, 1, -1); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "align_x", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "align"); RNA_def_property_enum_items(prop, text_align_x_items); RNA_def_property_ui_text(prop, "Align X", "Align the text along the X axis"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "align_y", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "align_y"); RNA_def_property_enum_items(prop, text_align_y_items); RNA_def_property_ui_text(prop, "Align Y", "Align the image along the Y axis"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Text", "Text that will be displayed"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "use_shadow", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_TEXT_SHADOW); RNA_def_property_ui_text(prop, "Shadow", "Draw text with shadow"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); } static void rna_def_color_mix(StructRNA *srna) @@ -2719,13 +2793,15 @@ static void rna_def_color_mix(StructRNA *srna) RNA_def_property_enum_items(prop, blend_color_items); RNA_def_property_ui_text( prop, "Blend Effect", "Method for controlling how the strip combines with other strips"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text( prop, "Blend Factor", "Percentage of how much the strip's colors affect other strips"); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); } static EffectInfo def_effects[] = { diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c index 8696023fbe6..4aa87055e1b 100644 --- a/source/blender/makesrna/intern/rna_shader_fx.c +++ b/source/blender/makesrna/intern/rna_shader_fx.c @@ -186,7 +186,7 @@ static void shaderfx_object_set(Object *self, Object **ob_p, int type, PointerRN # define RNA_FX_OBJECT_SET(_type, _prop, _obtype) \ static void rna_##_type##ShaderFx_##_prop##_set( \ - struct ReportList *UNUSED(reports), PointerRNA *ptr, PointerRNA value) \ + PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \ { \ _type##ShaderFxData *tmd = (_type##ShaderFxData *)ptr->data; \ shaderfx_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index dd1735027d9..8063b947a9c 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -346,15 +346,15 @@ const EnumPropertyItem rna_enum_shading_type_items[] = { }; static const EnumPropertyItem rna_enum_viewport_lighting_items[] = { - {V3D_LIGHTING_FLAT, "FLAT", 0, "Flat", "Display using flat lighting"}, {V3D_LIGHTING_STUDIO, "STUDIO", 0, "Studio", "Display using studio lighting"}, {V3D_LIGHTING_MATCAP, "MATCAP", 0, "MatCap", "Display using matcap material and lighting"}, + {V3D_LIGHTING_FLAT, "FLAT", 0, "Flat", "Display using flat lighting"}, {0, NULL, 0, NULL, NULL}, }; static const EnumPropertyItem rna_enum_shading_color_type_items[] = { - {V3D_SHADING_SINGLE_COLOR, "SINGLE", 0, "Single", "Show scene in a single color"}, {V3D_SHADING_MATERIAL_COLOR, "MATERIAL", 0, "Material", "Show material color"}, + {V3D_SHADING_SINGLE_COLOR, "SINGLE", 0, "Single", "Show scene in a single color"}, {V3D_SHADING_OBJECT_COLOR, "OBJECT", 0, "Object", "Show object color"}, {V3D_SHADING_RANDOM_COLOR, "RANDOM", 0, "Random", "Show random object color"}, {V3D_SHADING_VERTEX_COLOR, "VERTEX", 0, "Vertex", "Show active vertex color"}, @@ -1083,10 +1083,10 @@ static const EnumPropertyItem *rna_View3DShading_color_type_itemf(bContext *UNUS if (shading->type == OB_SOLID) { RNA_enum_items_add_value( - &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_SINGLE_COLOR); - RNA_enum_items_add_value( &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_MATERIAL_COLOR); RNA_enum_items_add_value( + &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_SINGLE_COLOR); + RNA_enum_items_add_value( &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_OBJECT_COLOR); RNA_enum_items_add_value( &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_RANDOM_COLOR); @@ -1329,9 +1329,9 @@ static bool rna_SpaceImageEditor_show_maskedit_get(PointerRNA *ptr) return ED_space_image_check_show_maskedit(sima, view_layer); } -static void rna_SpaceImageEditor_image_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_SpaceImageEditor_image_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { SpaceImage *sima = (SpaceImage *)(ptr->data); bScreen *sc = (bScreen *)ptr->id.data; @@ -1343,9 +1343,9 @@ static void rna_SpaceImageEditor_image_set(struct ReportList *UNUSED(reports), ED_space_image_set(G_MAIN, sima, obedit, (Image *)value.data, false); } -static void rna_SpaceImageEditor_mask_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_SpaceImageEditor_mask_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { SpaceImage *sima = (SpaceImage *)(ptr->data); @@ -1511,9 +1511,9 @@ static void rna_SpaceTextEditor_word_wrap_set(PointerRNA *ptr, bool value) st->left = 0; } -static void rna_SpaceTextEditor_text_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_SpaceTextEditor_text_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { SpaceText *st = (SpaceText *)(ptr->data); @@ -1535,9 +1535,9 @@ static void rna_SpaceTextEditor_updateEdited(Main *UNUSED(bmain), /* Space Properties */ /* note: this function exists only to avoid id refcounting */ -static void rna_SpaceProperties_pin_id_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_SpaceProperties_pin_id_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { SpaceProperties *sbuts = (SpaceProperties *)(ptr->data); sbuts->pinid = value.data; @@ -1739,9 +1739,9 @@ static void rna_ConsoleLine_cursor_index_range( /* Space Dopesheet */ -static void rna_SpaceDopeSheetEditor_action_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_SpaceDopeSheetEditor_action_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { SpaceAction *saction = (SpaceAction *)(ptr->data); bAction *act = (bAction *)value.data; @@ -1963,9 +1963,9 @@ static void rna_Sequencer_view_type_update(Main *UNUSED(bmain), /* Space Node Editor */ -static void rna_SpaceNodeEditor_node_tree_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - const PointerRNA value) +static void rna_SpaceNodeEditor_node_tree_set(PointerRNA *ptr, + const PointerRNA value, + struct ReportList *UNUSED(reports)) { SpaceNode *snode = (SpaceNode *)ptr->data; ED_node_tree_start(snode, (bNodeTree *)value.data, NULL, NULL); @@ -2076,9 +2076,9 @@ static void rna_SpaceNodeEditor_cursor_location_from_region(SpaceNode *snode, snode->cursor[1] /= UI_DPI_FAC; } -static void rna_SpaceClipEditor_clip_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_SpaceClipEditor_clip_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { SpaceClip *sc = (SpaceClip *)(ptr->data); bScreen *screen = (bScreen *)ptr->id.data; @@ -2086,9 +2086,9 @@ static void rna_SpaceClipEditor_clip_set(struct ReportList *UNUSED(reports), ED_space_clip_set_clip(NULL, screen, sc, (MovieClip *)value.data); } -static void rna_SpaceClipEditor_mask_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_SpaceClipEditor_mask_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { SpaceClip *sc = (SpaceClip *)(ptr->data); @@ -2484,7 +2484,7 @@ static void rna_def_space_generic_show_region_toggles(StructRNA *srna, int regio if (region_type_mask & (1 << RGN_TYPE_TOOL_HEADER)) { region_type_mask &= ~(1 << RGN_TYPE_TOOL_HEADER); - DEF_SHOW_REGION_PROPERTY(show_region_tool_header, "Tool Header", ""); + DEF_SHOW_REGION_PROPERTY(show_region_tool_header, "Tool Settings", ""); } if (region_type_mask & (1 << RGN_TYPE_HEADER)) { region_type_mask &= ~(1 << RGN_TYPE_HEADER); @@ -3403,14 +3403,12 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) prop = RNA_def_property(srna, "show_edges", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_EDGES); - RNA_def_property_ui_text( - prop, "Draw Edges", "Display selected edges using highlights in the 3D view and UV editor"); + RNA_def_property_ui_text(prop, "Draw Edges", "Display selected edges using highlights"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "show_faces", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_FACES); - RNA_def_property_ui_text( - prop, "Draw Faces", "Display all faces as shades in the 3D view and UV editor"); + RNA_def_property_ui_text(prop, "Draw Faces", "Display shading over all faces"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "show_face_center", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_space_api.c b/source/blender/makesrna/intern/rna_space_api.c index 58a9429e528..52a197240da 100644 --- a/source/blender/makesrna/intern/rna_space_api.c +++ b/source/blender/makesrna/intern/rna_space_api.c @@ -50,7 +50,7 @@ static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d, bContext *C) ViewLayer *view_layer = WM_window_get_active_view_layer(win); Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); - ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL); + ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL, false); break; } } diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 9be277aa15f..d08f7bc6035 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -144,9 +144,9 @@ static PointerRNA rna_tracking_active_track_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingTrack, act_track); } -static void rna_tracking_active_track_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_tracking_active_track_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { MovieClip *clip = (MovieClip *)ptr->id.data; MovieTrackingTrack *track = (MovieTrackingTrack *)value.data; @@ -167,9 +167,9 @@ static PointerRNA rna_tracking_active_plane_track_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingPlaneTrack, act_plane_track); } -static void rna_tracking_active_plane_track_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_tracking_active_plane_track_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { MovieClip *clip = (MovieClip *)ptr->id.data; MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)value.data; @@ -480,9 +480,9 @@ static PointerRNA rna_tracking_active_object_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingObject, object); } -static void rna_tracking_active_object_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_tracking_active_object_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { MovieClip *clip = (MovieClip *)ptr->id.data; MovieTrackingObject *object = (MovieTrackingObject *)value.data; diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index faa16f4f146..0dbafbde71c 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -317,19 +317,21 @@ static StructRNA *rna_Panel_register(Main *bmain, pt->draw_header = (have_function[2]) ? panel_draw_header : NULL; pt->draw_header_preset = (have_function[3]) ? panel_draw_header_preset : NULL; - /* XXX use "no header" flag for some ordering of panels until we have real panel ordering */ - if (pt->flag & PNL_NO_HEADER) { - PanelType *pth = art->paneltypes.first; - while (pth && pth->flag & PNL_NO_HEADER) - pth = pth->next; - - if (pth) - BLI_insertlinkbefore(&art->paneltypes, pth, pt); - else - BLI_addtail(&art->paneltypes, pt); + /* Find position to insert panel based on order. */ + PanelType *pt_iter = art->paneltypes.last; + + for (; pt_iter; pt_iter = pt_iter->prev) { + /* No header has priority. */ + if ((pt->flag & PNL_NO_HEADER) && !(pt_iter->flag & PNL_NO_HEADER)) { + continue; + } + if (pt_iter->order <= pt->order) { + break; + } } - else - BLI_addtail(&art->paneltypes, pt); + + /* Insert into list. */ + BLI_insertlinkafter(&art->paneltypes, pt_iter, pt); if (parent) { pt->parent = parent; @@ -1347,6 +1349,14 @@ static void rna_def_panel(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); RNA_def_property_ui_text(prop, "Units X", "When set, defines popup panel width"); + prop = RNA_def_property(srna, "bl_order", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "type->order"); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + RNA_def_property_ui_text( + prop, + "Order", + "Panels with lower numbers are default ordered before panels with higher numbers"); + prop = RNA_def_property(srna, "use_pin", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PNL_PIN); RNA_def_property_ui_text(prop, "Pin", ""); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 7ce9155e3d9..d50f97e88ca 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -95,13 +95,14 @@ static void rna_uiItemR(uiLayout *layout, int icon, bool expand, bool slider, - bool toggle, + int toggle, bool icon_only, bool event, bool full_event, bool emboss, int index, - int icon_value) + int icon_value, + bool invert_checkbox) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); int flag = 0; @@ -120,11 +121,17 @@ static void rna_uiItemR(uiLayout *layout, flag |= (slider) ? UI_ITEM_R_SLIDER : 0; flag |= (expand) ? UI_ITEM_R_EXPAND : 0; - flag |= (toggle) ? UI_ITEM_R_TOGGLE : 0; + if (toggle == 1) { + flag |= UI_ITEM_R_TOGGLE; + } + else if (toggle == 0) { + flag |= UI_ITEM_R_ICON_NEVER; + } flag |= (icon_only) ? UI_ITEM_R_ICON_ONLY : 0; flag |= (event) ? UI_ITEM_R_EVENT : 0; flag |= (full_event) ? UI_ITEM_R_FULL_EVENT : 0; flag |= (emboss) ? 0 : UI_ITEM_R_NO_BG; + flag |= (invert_checkbox) ? UI_ITEM_R_CHECKBOX_INVERT : 0; uiItemFullR(layout, ptr, prop, index, 0, flag, name, icon); } @@ -771,7 +778,17 @@ void RNA_api_ui_layout(StructRNA *srna) api_ui_item_common(func); RNA_def_boolean(func, "expand", false, "", "Expand button to show more detail"); RNA_def_boolean(func, "slider", false, "", "Use slider widget for numeric values"); - RNA_def_boolean(func, "toggle", false, "", "Use toggle widget for boolean values"); + RNA_def_int(func, + "toggle", + -1, + -1, + 1, + "", + "Use toggle widget for boolean values, " + "or a checkbox when disabled " + "(the default is -1 which uses toggle only when an icon is displayed)", + -1, + 1); RNA_def_boolean(func, "icon_only", false, "", "Draw only icons in buttons, no text"); RNA_def_boolean(func, "event", false, "", "Use button to input key events"); RNA_def_boolean( @@ -789,6 +806,7 @@ void RNA_api_ui_layout(StructRNA *srna) INT_MAX); /* RNA_NO_INDEX == -1 */ parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED); RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item"); + RNA_def_boolean(func, "invert_checkbox", false, "", "Draw checkbox value inverted"); func = RNA_def_function(srna, "props_enum", "uiItemsEnumR"); api_ui_item_rna_common(func); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 217beea7dae..d06e938b262 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -184,6 +184,31 @@ static void rna_userdef_version_get(PointerRNA *ptr, int *value) value[2] = userdef->subversionfile; } +# define USERDEF_TAG_DIRTY rna_userdef_is_dirty_update_impl() + +/* Use single function so we can more easily breakpoint it. */ +void rna_userdef_is_dirty_update_impl(void) +{ + /* We can't use 'ptr->data' because this update function + * is used for themes and other nested data. */ + if (U.runtime.is_dirty == false) { + U.runtime.is_dirty = true; + WM_main_add_notifier(NC_WINDOW, NULL); + } +} + +/** + * Use as a fallback update handler, + * never use 'ptr' unless it's type is checked. + */ +void rna_userdef_is_dirty_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *UNUSED(ptr)) +{ + rna_userdef_is_dirty_update_impl(); +} + +/** Take care not to use this if we expet 'is_dirty' to be tagged. */ static void rna_userdef_ui_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) @@ -193,11 +218,8 @@ static void rna_userdef_ui_update(Main *UNUSED(bmain), 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); + USERDEF_TAG_DIRTY; } static void rna_userdef_theme_update(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -224,24 +246,27 @@ static void rna_userdef_dpi_update(Main *UNUSED(bmain), WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */ + USERDEF_TAG_DIRTY; } -static void rna_userdef_update_ui(Main *UNUSED(bmain), - Scene *UNUSED(scene), - PointerRNA *UNUSED(ptr)) +static void rna_userdef_screen_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *UNUSED(ptr)) { WM_main_add_notifier(NC_WINDOW, NULL); WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */ + USERDEF_TAG_DIRTY; } -static void rna_userdef_update_ui_header_default(Main *bmain, Scene *scene, PointerRNA *ptr) +static void rna_userdef_screen_update_header_default(Main *bmain, Scene *scene, PointerRNA *ptr) { if (U.uiflag & USER_HEADER_FROM_PREF) { for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { BKE_screen_header_alignment_reset(screen); } - rna_userdef_update_ui(bmain, scene, ptr); + rna_userdef_screen_update(bmain, scene, ptr); } + USERDEF_TAG_DIRTY; } static void rna_userdef_language_update(Main *UNUSED(bmain), @@ -251,6 +276,7 @@ static void rna_userdef_language_update(Main *UNUSED(bmain), BLF_cache_clear(); BLT_lang_set(NULL); UI_reinit_font(); + USERDEF_TAG_DIRTY; } static void rna_userdef_script_autoexec_update(Main *UNUSED(bmain), @@ -262,6 +288,8 @@ static void rna_userdef_script_autoexec_update(Main *UNUSED(bmain), G.f &= ~G_FLAG_SCRIPT_AUTOEXEC; else G.f |= G_FLAG_SCRIPT_AUTOEXEC; + + USERDEF_TAG_DIRTY; } static void rna_userdef_load_ui_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -271,6 +299,8 @@ static void rna_userdef_load_ui_update(Main *UNUSED(bmain), Scene *UNUSED(scene) G.fileflags |= G_FILE_NO_UI; else G.fileflags &= ~G_FILE_NO_UI; + + USERDEF_TAG_DIRTY; } static void rna_userdef_anisotropic_update(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -323,6 +353,7 @@ static void rna_userdef_tablet_api_update(Main *UNUSED(bmain), PointerRNA *UNUSED(ptr)) { WM_init_tablet_api(); + USERDEF_TAG_DIRTY; } # ifdef WITH_INPUT_NDOF @@ -332,6 +363,7 @@ static void rna_userdef_ndof_deadzone_update(Main *UNUSED(bmain), { UserDef *userdef = ptr->data; WM_ndof_deadzone_set(userdef->ndof_deadzone); + USERDEF_TAG_DIRTY; } # endif @@ -341,6 +373,7 @@ static void rna_userdef_keyconfig_reload_update(bContext *C, PointerRNA *UNUSED(ptr)) { WM_keyconfig_reload(C); + USERDEF_TAG_DIRTY; } static void rna_userdef_timecode_style_set(PointerRNA *ptr, int value) @@ -410,6 +443,7 @@ static PointerRNA rna_UserDef_system_get(PointerRNA *ptr) static void rna_UserDef_audio_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) { BKE_sound_init(bmain); + USERDEF_TAG_DIRTY; } static void rna_Userdef_memcache_update(Main *UNUSED(bmain), @@ -417,6 +451,7 @@ static void rna_Userdef_memcache_update(Main *UNUSED(bmain), PointerRNA *UNUSED(ptr)) { MEM_CacheLimiter_set_maximum(((size_t)U.memcachelimit) * 1024 * 1024); + USERDEF_TAG_DIRTY; } static void rna_UserDef_weight_color_update(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -459,7 +494,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; + USERDEF_TAG_DIRTY; return addon; } @@ -474,14 +509,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; + USERDEF_TAG_DIRTY; } 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; + USERDEF_TAG_DIRTY; return path_cmp; } @@ -495,7 +530,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; + USERDEF_TAG_DIRTY; } static void rna_userdef_temp_update(Main *UNUSED(bmain), @@ -503,6 +538,7 @@ static void rna_userdef_temp_update(Main *UNUSED(bmain), PointerRNA *UNUSED(ptr)) { BKE_tempdir_init(U.tempdir); + USERDEF_TAG_DIRTY; } static void rna_userdef_text_update(Main *UNUSED(bmain), @@ -512,6 +548,7 @@ static void rna_userdef_text_update(Main *UNUSED(bmain), BLF_cache_clear(); UI_reinit_font(); WM_main_add_notifier(NC_WINDOW, NULL); + USERDEF_TAG_DIRTY; } static PointerRNA rna_Theme_space_generic_get(PointerRNA *ptr) @@ -578,6 +615,7 @@ static void rna_userdef_opensubdiv_update(Main *bmain, for (object = bmain->objects.first; object; object = object->id.next) { DEG_id_tag_update(&object->id, ID_RECALC_TRANSFORM); } + USERDEF_TAG_DIRTY; } # endif @@ -900,6 +938,11 @@ static void rna_UserDef_studiolight_light_ambient_get(PointerRNA *ptr, float *va #else +# define USERDEF_TAG_DIRTY_PROPERTY_UPDATE_ENABLE \ + RNA_define_fallback_property_update(0, "rna_userdef_is_dirty_update") + +# define USERDEF_TAG_DIRTY_PROPERTY_UPDATE_DISABLE RNA_define_fallback_property_update(0, NULL) + /* TODO(sergey): This technically belongs to blenlib, but we don't link * makesrna against it. */ @@ -2140,7 +2183,7 @@ 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); + prop = RNA_def_property(srna, "time_scrub_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"); @@ -2502,8 +2545,6 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna) rna_def_userdef_theme_spaces_main(srna); rna_def_userdef_theme_spaces_list_main(srna); - rna_def_userdef_theme_spaces_gpencil(srna); - prop = RNA_def_property(srna, "node_selected", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "select"); RNA_def_property_array(prop, 3); @@ -2678,7 +2719,6 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Theme Image Editor", "Theme settings for the Image Editor"); rna_def_userdef_theme_spaces_main(srna); - rna_def_userdef_theme_spaces_gpencil(srna); rna_def_userdef_theme_spaces_vertex(srna); rna_def_userdef_theme_spaces_face(srna); @@ -2787,7 +2827,6 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Theme Sequence Editor", "Theme settings for the Sequence Editor"); rna_def_userdef_theme_spaces_main(srna); - rna_def_userdef_theme_spaces_gpencil(srna); prop = RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); @@ -2859,7 +2898,7 @@ 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); + prop = RNA_def_property(srna, "time_scrub_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"); @@ -2921,7 +2960,7 @@ 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); + prop = RNA_def_property(srna, "time_scrub_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"); @@ -3219,7 +3258,7 @@ static void rna_def_userdef_theme_space_nla(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); + prop = RNA_def_property(srna, "time_scrub_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"); @@ -3274,8 +3313,6 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna) rna_def_userdef_theme_spaces_main(srna); rna_def_userdef_theme_spaces_list_main(srna); - rna_def_userdef_theme_spaces_gpencil(srna); - prop = RNA_def_property(srna, "marker_outline", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "marker_outline"); RNA_def_property_array(prop, 3); @@ -3330,7 +3367,7 @@ 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); + prop = RNA_def_property(srna, "time_scrub_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"); @@ -3743,12 +3780,16 @@ static void rna_def_userdef_addon_pref(BlenderRNA *brna) RNA_def_struct_idprops_func(srna, "rna_AddonPref_idprops"); RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); /* Mandatory! */ + USERDEF_TAG_DIRTY_PROPERTY_UPDATE_DISABLE; + /* registration */ RNA_define_verify_sdna(0); prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "module"); RNA_def_property_flag(prop, PROP_REGISTER); RNA_define_verify_sdna(1); + + USERDEF_TAG_DIRTY_PROPERTY_UPDATE_ENABLE; } static void rna_def_userdef_dothemes(BlenderRNA *brna) @@ -4065,7 +4106,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_boolean_negative_sdna(prop, NULL, "app_flag", USER_APP_LOCK_UI_LAYOUT); RNA_def_property_ui_text( prop, "Editor Corner Splitting", "Split and join editors by dragging from corners"); - RNA_def_property_update(prop, 0, "rna_userdef_update_ui"); + RNA_def_property_update(prop, 0, "rna_userdef_screen_update"); /* menus */ prop = RNA_def_property(srna, "use_mouse_over_open", PROP_BOOLEAN, PROP_NONE); @@ -4166,7 +4207,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_enum_items(prop, header_align_items); RNA_def_property_enum_bitflag_sdna(prop, NULL, "uiflag"); RNA_def_property_ui_text(prop, "Header Position", "Default header position for new space-types"); - RNA_def_property_update(prop, 0, "rna_userdef_update_ui_header_default"); + RNA_def_property_update(prop, 0, "rna_userdef_screen_update_header_default"); static const EnumPropertyItem text_hinting_items[] = { {0, "AUTO", 0, "Auto", ""}, @@ -5580,6 +5621,8 @@ static void rna_def_userdef_autoexec_path_collection(BlenderRNA *brna, PropertyR void RNA_def_userdef(BlenderRNA *brna) { + USERDEF_TAG_DIRTY_PROPERTY_UPDATE_ENABLE; + StructRNA *srna; PropertyRNA *prop; @@ -5740,6 +5783,8 @@ void RNA_def_userdef(BlenderRNA *brna) rna_def_userdef_studiolights(brna); rna_def_userdef_studiolight(brna); rna_def_userdef_pathcompare(brna); + + USERDEF_TAG_DIRTY_PROPERTY_UPDATE_DISABLE; } #endif diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index f3080d6f659..14994340ad3 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -49,6 +49,8 @@ static const EnumPropertyItem event_keymouse_value_items[] = { {KM_CLICK, "CLICK", 0, "Click", ""}, {KM_DBL_CLICK, "DOUBLE_CLICK", 0, "Double Click", ""}, {KM_CLICK_DRAG, "CLICK_DRAG", 0, "Click Drag", ""}, + /* Used for NDOF and trackpad events. */ + {KM_NOTHING, "NOTHING", 0, "Nothing", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -382,7 +384,6 @@ const EnumPropertyItem rna_enum_event_type_items[] = { const EnumPropertyItem rna_enum_event_value_items[] = { {KM_ANY, "ANY", 0, "Any", ""}, - {KM_NOTHING, "NOTHING", 0, "Nothing", ""}, {KM_PRESS, "PRESS", 0, "Press", ""}, {KM_RELEASE, "RELEASE", 0, "Release", ""}, {KM_CLICK, "CLICK", 0, "Click", ""}, @@ -396,6 +397,7 @@ const EnumPropertyItem rna_enum_event_value_items[] = { {EVT_GESTURE_SW, "SOUTH_WEST", 0, "South-West", ""}, {EVT_GESTURE_W, "WEST", 0, "West", ""}, {EVT_GESTURE_NW, "NORTH_WEST", 0, "North-West", ""}, + {KM_NOTHING, "NOTHING", 0, "Nothing", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -451,11 +453,6 @@ static const EnumPropertyItem operator_flag_items[] = { "is enabled"}, {OPTYPE_PRESET, "PRESET", 0, "Preset", "Display a preset button with the operators settings"}, {OPTYPE_INTERNAL, "INTERNAL", 0, "Internal", "Removes the operator from search results"}, - {OPTYPE_USE_EVAL_DATA, - "USE_EVAL_DATA", - 0, - "Use Evaluated Data", - "Uses evaluated data (i.e. needs a valid depsgraph for current context)"}, {0, NULL, 0, NULL, NULL}, }; #endif @@ -694,9 +691,9 @@ static PointerRNA rna_PieMenu_layout_get(PointerRNA *ptr) return rptr; } -static void rna_Window_scene_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Window_scene_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { wmWindow *win = ptr->data; @@ -740,9 +737,9 @@ static PointerRNA rna_Window_workspace_get(PointerRNA *ptr) ptr, &RNA_WorkSpace, BKE_workspace_active_get(win->workspace_hook)); } -static void rna_Window_workspace_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Window_workspace_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { wmWindow *win = (wmWindow *)ptr->data; @@ -778,9 +775,9 @@ PointerRNA rna_Window_screen_get(PointerRNA *ptr) ptr, &RNA_Screen, BKE_workspace_active_screen_get(win->workspace_hook)); } -static void rna_Window_screen_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Window_screen_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { wmWindow *win = ptr->data; WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook); @@ -830,9 +827,9 @@ static PointerRNA rna_Window_view_layer_get(PointerRNA *ptr) return rna_pointer_inherit_refine(&scene_ptr, &RNA_ViewLayer, view_layer); } -static void rna_Window_view_layer_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_Window_view_layer_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { wmWindow *win = ptr->data; ViewLayer *view_layer = value.data; @@ -1036,9 +1033,9 @@ static PointerRNA rna_WindowManager_active_keyconfig_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_KeyConfig, kc); } -static void rna_WindowManager_active_keyconfig_set(struct ReportList *UNUSED(reports), - PointerRNA *ptr, - PointerRNA value) +static void rna_WindowManager_active_keyconfig_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *UNUSED(reports)) { wmWindowManager *wm = ptr->data; wmKeyConfig *kc = value.data; diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c index 22162aa017b..b13c5da7002 100644 --- a/source/blender/makesrna/intern/rna_wm_gizmo.c +++ b/source/blender/makesrna/intern/rna_wm_gizmo.c @@ -744,7 +744,10 @@ static void rna_gizmogroup_draw_prepare_cb(const bContext *C, wmGizmoGroup *gzgr RNA_parameter_list_free(&list); } -static void rna_gizmogroup_invoke_prepare_cb(const bContext *C, wmGizmoGroup *gzgroup, wmGizmo *gz) +static void rna_gizmogroup_invoke_prepare_cb(const bContext *C, + wmGizmoGroup *gzgroup, + wmGizmo *gz, + const wmEvent *event) { extern FunctionRNA rna_GizmoGroup_invoke_prepare_func; @@ -759,6 +762,7 @@ static void rna_gizmogroup_invoke_prepare_cb(const bContext *C, wmGizmoGroup *gz RNA_parameter_list_create(&list, &gzgroup_ptr, func); RNA_parameter_set_lookup(&list, "context", &C); RNA_parameter_set_lookup(&list, "gizmo", &gz); + RNA_parameter_set_lookup(&list, "event", &event); gzgroup->type->ext.call((bContext *)C, &gzgroup_ptr, func, &list); RNA_parameter_list_free(&list); diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index 7fbaa24b579..0accbe607eb 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -35,6 +35,8 @@ #include "MOD_modifiertypes.h" #include "MOD_util.h" +#include "bmesh.h" + #define CLNORS_VALID_VEC_LEN (1e-6f) typedef struct ModePair { 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 6c3e082f36a..48065cb10c9 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c @@ -164,7 +164,7 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, else if (use_subsurf && use_diffuse && !use_refract && !use_clear) { static char name[] = "node_bsdf_principled_subsurface"; node_name = name; - flag = GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_SSS | GPU_MATFLAG_GLOSSY; + flag = GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY; } else if (!use_subsurf && !use_diffuse && use_refract && !use_clear && !socket_not_zero(4)) { static char name[] = "node_bsdf_principled_glass"; @@ -174,7 +174,11 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, else { static char name[] = "node_bsdf_principled"; node_name = name; - flag = GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY | GPU_MATFLAG_SSS | GPU_MATFLAG_REFRACT; + flag = GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY | GPU_MATFLAG_REFRACT; + } + + if (use_subsurf) { + flag |= GPU_MATFLAG_SSS; } GPU_material_flag_set(mat, flag); 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 a9183cd10ef..786386bb63e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -180,8 +180,12 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, } if (out[0].hasoutput) { + /* When the alpha socket is used, unpremultiply alpha. This makes it so + * that if we blend the color with a transparent shader using alpha as + * a factor, we don't multiply alpha into the color twice. */ if (out[1].hasoutput && - !IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) { + !(ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) || + IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name))) { GPU_link(mat, "tex_color_alpha_unpremultiply", out[0].link, &out[0].link); } else { diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c index cdd4d66d485..d64846e4dcc 100644 --- a/source/blender/physics/intern/implicit_blender.c +++ b/source/blender/physics/intern/implicit_blender.c @@ -608,17 +608,16 @@ DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][3]) /* STATUS: verified */ DO_INLINE void mul_bfmatrix_lfvector(float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector) { - unsigned int i = 0; unsigned int vcount = from[0].vcount; lfVector *temp = create_lfvector(vcount); zero_lfvector(to, vcount); -# pragma omp parallel sections private(i) if (vcount > CLOTH_OPENMP_LIMIT) +# pragma omp parallel sections if (vcount > CLOTH_OPENMP_LIMIT) { # pragma omp section { - for (i = from[0].vcount; i < from[0].vcount + from[0].scount; i++) { + for (unsigned int i = from[0].vcount; i < from[0].vcount + from[0].scount; i++) { /* This is the lower triangle of the sparse matrix, * therefore multiplication occurs with transposed submatrices. */ muladd_fmatrixT_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); @@ -626,7 +625,7 @@ DO_INLINE void mul_bfmatrix_lfvector(float (*to)[3], fmatrix3x3 *from, lfVector } # pragma omp section { - for (i = 0; i < from[0].vcount + from[0].scount; i++) { + for (unsigned int i = 0; i < from[0].vcount + from[0].scount; i++) { muladd_fmatrix_fvector(temp[from[i].r], from[i].m, fLongVector[from[i].c]); } } diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index 7134bf520ac..dde3d026d47 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -61,6 +61,7 @@ static PyStructSequence_Field app_cb_info_fields[] = { {(char *)"depsgraph_update_pre", (char *)"on depsgraph update (pre)"}, {(char *)"depsgraph_update_post", (char *)"on depsgraph update (post)"}, {(char *)"version_update", (char *)"on ending the versioning code"}, + {(char *)"load_factory_preferences_post", (char *)"on loading factory preferences (after)"}, {(char *)"load_factory_startup_post", (char *)"on loading factory startup (after)"}, /* sets the permanent tag */ diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index e5487a6a0c9..092c9061bb7 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -2032,7 +2032,7 @@ static int pyrna_py_to_prop( ReportList reports; BKE_reports_init(&reports, RPT_STORE); RNA_property_pointer_set( - &reports, ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr); + ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr, &reports); int err = (BPy_reports_to_error(&reports, PyExc_RuntimeError, true)); if (err == -1) { Py_XDECREF(value_new); diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 7cc9ba50d90..2e664616639 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -585,6 +585,34 @@ static PyObject *C_Matrix_Translation(PyObject *cls, PyObject *value) return Matrix_CreatePyObject(&mat[0][0], 4, 4, (PyTypeObject *)cls); } +/* ----------------------------------mathutils.Matrix.Diagonal() ------------- */ +PyDoc_STRVAR(C_Matrix_Diagonal_doc, + ".. classmethod:: Diagonal(vector)\n" + "\n" + " Create a diagonal (scaling) matrix using the values from the vector.\n" + "\n" + " :arg vector: The vector of values for the diagonal.\n" + " :type vector: :class:`Vector`\n" + " :return: A diagonal matrix.\n" + " :rtype: :class:`Matrix`\n"); +static PyObject *C_Matrix_Diagonal(PyObject *cls, PyObject *value) +{ + float mat[16] = {0.0f}; + float vec[4]; + + int size = mathutils_array_parse( + vec, 2, 4, value, "mathutils.Matrix.Diagonal(vector), invalid vector arg"); + + if (size == -1) { + return NULL; + } + + for (int i = 0; i < size; i++) { + mat[size * i + i] = vec[i]; + } + + return Matrix_CreatePyObject(mat, size, size, (PyTypeObject *)cls); +} /* ----------------------------------mathutils.Matrix.Scale() ------------- */ /* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */ PyDoc_STRVAR(C_Matrix_Scale_doc, @@ -3085,6 +3113,7 @@ static struct PyMethodDef Matrix_methods[] = { {"Rotation", (PyCFunction)C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc}, {"Scale", (PyCFunction)C_Matrix_Scale, METH_VARARGS | METH_CLASS, C_Matrix_Scale_doc}, {"Shear", (PyCFunction)C_Matrix_Shear, METH_VARARGS | METH_CLASS, C_Matrix_Shear_doc}, + {"Diagonal", (PyCFunction)C_Matrix_Diagonal, METH_O | METH_CLASS, C_Matrix_Diagonal_doc}, {"Translation", (PyCFunction)C_Matrix_Translation, METH_O | METH_CLASS, diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 63fd3f1d0bd..efa328cf14d 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -37,6 +37,7 @@ #include "RE_pipeline.h" +struct GHash; struct Main; struct Object; struct RenderEngine; @@ -112,11 +113,16 @@ struct Render { struct Object *camera_override; ThreadRWMutex partsmutex; - ListBase parts; + struct GHash *parts; /* render engine */ struct RenderEngine *engine; + /* NOTE: This is a minimal dependency graph and evaluated scene which is enough to access view + * layer visibility and use for post-precessing (compositor and sequencer). */ + Depsgraph *pipeline_depsgraph; + Scene *pipeline_scene_eval; + #ifdef WITH_FREESTYLE struct Main *freestyle_bmain; ListBase freestyle_renders; diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 9a955b5e8f5..a5bf5adc243 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -29,9 +29,11 @@ #include "BLT_translation.h" +#include "BLI_utildefines.h" +#include "BLI_ghash.h" #include "BLI_listbase.h" +#include "BLI_rect.h" #include "BLI_string.h" -#include "BLI_utildefines.h" #include "DNA_object_types.h" @@ -169,18 +171,10 @@ void RE_engine_free(RenderEngine *engine) static RenderPart *get_part_from_result(Render *re, RenderResult *result) { - RenderPart *pa; - - for (pa = re->parts.first; pa; pa = pa->next) { - if (result->tilerect.xmin == pa->disprect.xmin - re->disprect.xmin && - result->tilerect.ymin == pa->disprect.ymin - re->disprect.ymin && - result->tilerect.xmax == pa->disprect.xmax - re->disprect.xmin && - result->tilerect.ymax == pa->disprect.ymax - re->disprect.ymin) { - return pa; - } - } + rcti key = result->tilerect; + BLI_rcti_translate(&key, re->disprect.xmin, re->disprect.ymin); - return NULL; + return BLI_ghash_lookup(re->parts, &key); } RenderResult *RE_engine_begin_result( @@ -458,7 +452,6 @@ rcti *RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_ { static rcti tiles_static[BLENDER_MAX_THREADS]; const int allocation_step = BLENDER_MAX_THREADS; - RenderPart *pa; int total_tiles = 0; rcti *tiles = tiles_static; int allocation_size = BLENDER_MAX_THREADS; @@ -467,13 +460,15 @@ rcti *RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_ *r_needs_free = false; - if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) { + if (!re->parts || (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0)) { *r_total_tiles = 0; BLI_rw_mutex_unlock(&re->partsmutex); return NULL; } - for (pa = re->parts.first; pa; pa = pa->next) { + GHashIterator pa_iter; + GHASH_ITER (pa_iter, re->parts) { + RenderPart *pa = BLI_ghashIterator_getValue(&pa_iter); if (pa->status == PART_STATUS_IN_PROGRESS) { if (total_tiles >= allocation_size) { /* Just in case we're using crazy network rendering with more diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index c147794dae7..1aa16dc1019 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -233,7 +233,7 @@ int imagewrap(Tex *tex, /* keep this before interpolation [#29761] */ if (ima) { - if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) { + if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) { if ((tex->imaflag & TEX_CALCALPHA) == 0) { texres->talpha = true; } @@ -1056,7 +1056,7 @@ static int imagewraposa_aniso(Tex *tex, image_mipmap_test(tex, ibuf); if (ima) { - if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) { + if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) { if ((tex->imaflag & TEX_CALCALPHA) == 0) { texres->talpha = 1; } @@ -1512,7 +1512,7 @@ int imagewraposa(Tex *tex, image_mipmap_test(tex, ibuf); if (ima) { - if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) { + if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) { if ((tex->imaflag & TEX_CALCALPHA) == 0) { texres->talpha = true; } diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index 4540e4e2cc2..acdd801bd86 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -31,6 +31,7 @@ #include "MEM_guardedalloc.h" #include "BLI_math.h" +#include "BLI_ghash.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" @@ -245,7 +246,10 @@ void RE_GetCameraModelMatrix(Render *re, struct Object *camera, float r_mat[4][4 void RE_parts_free(Render *re) { - BLI_freelistN(&re->parts); + if (re->parts) { + BLI_ghash_free(re->parts, NULL, MEM_freeN); + re->parts = NULL; + } } void RE_parts_clamp(Render *re) @@ -262,6 +266,9 @@ void RE_parts_init(Render *re) RE_parts_free(re); + re->parts = BLI_ghash_new( + BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, "render parts"); + /* this is render info for caller, is not reset when parts are freed! */ re->i.totpart = 0; re->i.curpart = 0; @@ -323,7 +330,7 @@ void RE_parts_init(Render *re) pa->rectx = rectx; pa->recty = recty; - BLI_addtail(&re->parts, pa); + BLI_ghash_insert(re->parts, &pa->disprect, pa); re->i.totpart++; } } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 9c1c713ab94..76767d0d1d8 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -74,6 +74,7 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_debug.h" #include "DEG_depsgraph_query.h" #include "PIL_time.h" @@ -1430,10 +1431,10 @@ static void free_all_freestyle_renders(void) /* returns fully composited render-result on given time step (in RenderData) */ static void do_render_composite(Render *re) { - bNodeTree *ntree = re->scene->nodetree; + bNodeTree *ntree = re->pipeline_scene_eval->nodetree; int update_newframe = 0; - if (composite_needs_render(re->scene, 1)) { + if (composite_needs_render(re->pipeline_scene_eval, 1)) { /* save memory... free all cached images */ ntreeFreeCache(ntree); @@ -1471,7 +1472,7 @@ static void do_render_composite(Render *re) if (!re->test_break(re->tbh)) { if (ntree) { - ntreeCompositTagRender(re->scene); + ntreeCompositTagRender(re->pipeline_scene_eval); } if (ntree && re->scene->use_nodes && re->r.scemode & R_DOCOMP) { @@ -1494,7 +1495,7 @@ static void do_render_composite(Render *re) RenderView *rv; for (rv = re->result->views.first; rv; rv = rv->next) { - ntreeCompositExecTree(re->scene, + ntreeCompositExecTree(re->pipeline_scene_eval, ntree, &re->r, true, @@ -1595,12 +1596,8 @@ static void do_render_seq(Render *re) tot_views = BKE_scene_multiview_num_views_get(&re->r); ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs"); - /* TODO(sergey): Currently depsgraph is only used to check whether it is an active - * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet, - * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph - * within tjhe render pipeline, somehow. - */ - BKE_sequencer_new_render_data(re->main, NULL, re->scene, re_x, re_y, 100, true, &context); + BKE_sequencer_new_render_data( + re->main, re->pipeline_depsgraph, re->scene, re_x, re_y, 100, true, &context); /* the renderresult gets destroyed during the rendering, so we first collect all ibufs * and then we populate the final renderesult */ @@ -1613,7 +1610,7 @@ static void do_render_seq(Render *re) ibuf_arr[view_id] = IMB_dupImBuf(out); IMB_metadata_copy(ibuf_arr[view_id], out); IMB_freeImBuf(out); - BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf_arr[view_id]); + BKE_sequencer_imbuf_from_sequencer_space(re->pipeline_scene_eval, ibuf_arr[view_id]); } else { ibuf_arr[view_id] = NULL; @@ -1641,9 +1638,9 @@ static void do_render_seq(Render *re) } if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */ - Editing *ed = re->scene->ed; + Editing *ed = re->pipeline_scene_eval->ed; if (ed) { - BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, true); + BKE_sequencer_free_imbuf(re->pipeline_scene_eval, &ed->seqbase, true); } } IMB_freeImBuf(ibuf_arr[view_id]); @@ -2071,6 +2068,32 @@ void RE_SetReports(Render *re, ReportList *reports) re->reports = reports; } +static void render_update_depsgraph(Render *re) +{ + Scene *scene = re->scene; + /* TODO(sergey): This doesn't run any callbacks and doesn't do sound update. But we can not use + * BKE_scene_graph_update_for_newframe() because that one builds dependency graph for view layer + * and not for the render pipeline. */ + DEG_evaluate_on_framechange(re->main, re->pipeline_depsgraph, CFRA); +} + +static void render_init_depsgraph(Render *re) +{ + Scene *scene = re->scene; + ViewLayer *view_layer = BKE_view_layer_default_render(re->scene); + + re->pipeline_depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER); + DEG_debug_name_set(re->pipeline_depsgraph, "RENDER PIPELINE"); + + /* Make sure there is a correct evaluated scene pointer. */ + DEG_graph_build_for_render_pipeline(re->pipeline_depsgraph, re->main, scene, view_layer); + + /* Update immediately so we have proper evaluated scene. */ + render_update_depsgraph(re); + + re->pipeline_scene_eval = DEG_get_evaluated_scene(re->pipeline_depsgraph); +} + /* general Blender frame render call */ void RE_RenderFrame(Render *re, Main *bmain, @@ -2093,6 +2116,8 @@ void RE_RenderFrame(Render *re, const RenderData rd = scene->r; MEM_reset_peak_memory(); + render_init_depsgraph(re); + BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE); do_render_all_options(re); @@ -2490,6 +2515,8 @@ void RE_RenderAnim(Render *re, return; } + render_init_depsgraph(re); + if (is_movie) { size_t width, height; int i; @@ -2556,6 +2583,8 @@ void RE_RenderAnim(Render *re, BKE_animsys_evaluate_animdata(NULL, scene, &scene->id, adt, ctime, ADT_RECALC_ALL); } + render_update_depsgraph(re); + /* only border now, todo: camera lens. (ton) */ render_initialize_from_main(re, &rd, bmain, scene, single_layer, camera_override, 1, 0); @@ -2746,6 +2775,11 @@ void RE_CleanAfterRender(Render *re) { /* Destroy the opengl context in the correct thread. */ RE_gl_context_destroy(re); + if (re->pipeline_depsgraph != NULL) { + DEG_graph_free(re->pipeline_depsgraph); + } + re->pipeline_depsgraph = NULL; + re->pipeline_scene_eval = NULL; } /* note; repeated win/disprect calc... solve that nicer, also in compo */ diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 9ca9472e571..04dabad611f 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -29,6 +29,7 @@ #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" +#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_hash_md5.h" #include "BLI_path_util.h" @@ -1174,13 +1175,14 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, cons void render_result_save_empty_result_tiles(Render *re) { - RenderPart *pa; RenderResult *rr; RenderLayer *rl; for (rr = re->result; rr; rr = rr->next) { for (rl = rr->layers.first; rl; rl = rl->next) { - for (pa = re->parts.first; pa; pa = pa->next) { + GHashIterator pa_iter; + GHASH_ITER (pa_iter, re->parts) { + RenderPart *pa = BLI_ghashIterator_getValue(&pa_iter); if (pa->status != PART_STATUS_MERGED) { int party = pa->disprect.ymin - re->disprect.ymin; int partx = pa->disprect.xmin - re->disprect.xmin; diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 7e53c652ab5..64f506f03a8 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -74,6 +74,7 @@ set(SRC intern/wm_toolsystem.c intern/wm_tooltip.c intern/wm_uilist_type.c + intern/wm_utils.c intern/wm_window.c gizmo/intern/wm_gizmo.c gizmo/intern/wm_gizmo_group.c diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 70f986732ad..a5eb892841c 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -60,6 +60,7 @@ struct wmEvent; struct wmEventHandler; struct wmEventHandler_Keymap; struct wmEventHandler_UI; +struct wmGenericUserData; struct wmGesture; struct wmJob; struct wmMsgSubscribeKey; @@ -598,6 +599,7 @@ bool WM_gesture_is_modal_first(const struct wmGesture *gesture); /* fileselecting support */ void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op); void WM_event_fileselect_event(struct wmWindowManager *wm, void *ophandle, int eventval); +int WM_event_modifier_flag(const struct wmEvent *event); void WM_event_print(const struct wmEvent *event); void WM_operator_region_active_win_set(struct bContext *C); @@ -795,6 +797,12 @@ void WM_tooltip_init(struct bContext *C, struct wmWindow *win); void WM_tooltip_refresh(struct bContext *C, struct wmWindow *win); double WM_tooltip_time_closed(void); +/* wm_utils.c */ +struct wmGenericCallback *WM_generic_callback_steal(struct wmGenericCallback *callback); +void WM_generic_callback_free(struct wmGenericCallback *callback); + +void WM_generic_user_data_free(struct wmGenericUserData *user_data); + #ifdef __cplusplus } #endif diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h index 53488cd1f71..4a9a9cf8705 100644 --- a/source/blender/windowmanager/WM_keymap.h +++ b/source/blender/windowmanager/WM_keymap.h @@ -114,6 +114,8 @@ void WM_keymap_add_context_enum_set_items(wmKeyMap *keymap, wmKeyMap *WM_keymap_guess_from_context(const struct bContext *C); wmKeyMap *WM_keymap_guess_opname(const struct bContext *C, const char *opname); +bool WM_keymap_uses_event_modifier(wmKeyMap *keymap, const int event_modifier); + void WM_keymap_fix_linking(void); /* Modal Keymap */ diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index b3c36857dce..eddea3b2062 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -120,6 +120,19 @@ struct wmWindowManager; /* Include external gizmo API's */ #include "gizmo/WM_gizmo_api.h" +typedef struct wmGenericUserData { + void *data; + /** When NULL, use #MEM_freeN. */ + void (*free_fn)(void *data); + bool use_free; +} wmGenericUserData; + +typedef struct wmGenericCallback { + void (*exec)(struct bContext *C, void *user_data); + void *user_data; + void (*free_user_data)(void *user_data); +} wmGenericCallback; + /* ************** wmOperatorType ************************ */ /* flag */ @@ -442,8 +455,7 @@ typedef struct wmGesture { /* customdata for straight line is a recti: (xmin,ymin) is start, (xmax, ymax) is end */ /* free pointer to use for operator allocs (if set, its freed on exit)*/ - void *userdata; - bool userdata_free; + wmGenericUserData user_data; } wmGesture; /* ************** wmEvent ************************ */ diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_api.h b/source/blender/windowmanager/gizmo/WM_gizmo_api.h index 9a272b27f87..bef3cd51aea 100644 --- a/source/blender/windowmanager/gizmo/WM_gizmo_api.h +++ b/source/blender/windowmanager/gizmo/WM_gizmo_api.h @@ -235,10 +235,21 @@ void WM_gizmo_target_property_subscribe_all(struct wmGizmo *gz, /* wmGizmoGroup */ /* Callbacks for 'wmGizmoGroupType.setup_keymap' */ -struct wmKeyMap *WM_gizmogroup_keymap_common(const struct wmGizmoGroupType *gzgt, - struct wmKeyConfig *config); -struct wmKeyMap *WM_gizmogroup_keymap_common_select(const struct wmGizmoGroupType *gzgt, - struct wmKeyConfig *config); +struct wmKeyMap *WM_gizmogroup_keymap_template_ex(struct wmKeyConfig *config, + const char *idname, + const struct wmGizmoMapType_Params *params); +struct wmKeyMap *WM_gizmogroup_keymap_template(const struct wmGizmoGroupType *gzgt, + struct wmKeyConfig *config); + +struct wmKeyMap *WM_gizmogroup_keymap_template_select_ex( + struct wmKeyConfig *config, const char *idname, const struct wmGizmoMapType_Params *params); +struct wmKeyMap *WM_gizmogroup_keymap_template_select(const struct wmGizmoGroupType *gzgt, + struct wmKeyConfig *config); + +struct wmKeyMap *WM_gizmogroup_keymap_generic(const struct wmGizmoGroupType *gzgt, + struct wmKeyConfig *config); +struct wmKeyMap *WM_gizmogroup_keymap_generic_select(const struct wmGizmoGroupType *gzgt, + struct wmKeyConfig *config); void WM_gizmogroup_ensure_init(const struct bContext *C, struct wmGizmoGroup *gzgroup); diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h index 7d38194db1b..cd8bcc6696b 100644 --- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h +++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h @@ -182,6 +182,9 @@ struct wmGizmo { /** Pointer back to group this gizmo is in (just for quick access). */ struct wmGizmoGroup *parent_gzgroup; + /** Optional keymap to use for this gizmo (overrides #wmGizmoGroupType.keymap) */ + struct wmKeyMap *keymap; + void *py_instance; /** Rna pointer to access properties. */ @@ -195,7 +198,11 @@ struct wmGizmo { /** Optional ID for highlighting different parts of this gizmo. * -1 when unset, otherwise a valid index. (Used as index to 'op_data'). */ int highlight_part; - /** For single click button gizmos, use a different part as a fallback, -1 when unused. */ + + /** + * For gizmos that differentiate between click & drag, + * use a different part for any drag events, -1 when unused. + */ int drag_part; /** Distance to bias this gizmo above others when picking diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c index 5aecab122a2..f0e4c45843f 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c @@ -31,6 +31,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_buffer.h" #include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_math.h" @@ -58,10 +59,6 @@ # include "BPY_extern.h" #endif -/* Allow gizmo part's to be single click only, - * dragging falls back to activating their 'drag_part' action. */ -#define USE_DRAG_DETECT - /* -------------------------------------------------------------------- */ /** \name wmGizmoGroup * @@ -171,14 +168,48 @@ int WM_gizmo_cmp_temp_fl_reverse(const void *gz_a_ptr, const void *gz_b_ptr) } } -wmGizmo *wm_gizmogroup_find_intersected_gizmo(const wmGizmoGroup *gzgroup, +static bool wm_gizmo_keymap_uses_event_modifier(wmWindowManager *wm, + const wmGizmoGroup *gzgroup, + wmGizmo *gz, + const int event_modifier, + int *r_gzgroup_keymap_uses_modifier) +{ + if (gz->keymap) { + wmKeyMap *keymap = WM_keymap_active(wm, gz->keymap); + if (!WM_keymap_uses_event_modifier(keymap, event_modifier)) { + return false; + } + } + else if (gzgroup->type->keymap) { + if (*r_gzgroup_keymap_uses_modifier == -1) { + wmKeyMap *keymap = WM_keymap_active(wm, gzgroup->type->keymap); + *r_gzgroup_keymap_uses_modifier = WM_keymap_uses_event_modifier(keymap, event_modifier); + } + if (*r_gzgroup_keymap_uses_modifier == 0) { + return false; + } + } + return true; +} + +wmGizmo *wm_gizmogroup_find_intersected_gizmo(wmWindowManager *wm, + const wmGizmoGroup *gzgroup, bContext *C, - const wmEvent *event, + const int event_modifier, + const int mval[2], int *r_part) { + int gzgroup_keymap_uses_modifier = -1; + for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) { if (gz->type->test_select && (gz->flag & (WM_GIZMO_HIDDEN | WM_GIZMO_HIDDEN_SELECT)) == 0) { - if ((*r_part = gz->type->test_select(C, gz, event->mval)) != -1) { + + if (!wm_gizmo_keymap_uses_event_modifier( + wm, gzgroup, gz, event_modifier, &gzgroup_keymap_uses_modifier)) { + continue; + } + + if ((*r_part = gz->type->test_select(C, gz, mval)) != -1) { return gz; } } @@ -191,14 +222,24 @@ wmGizmo *wm_gizmogroup_find_intersected_gizmo(const wmGizmoGroup *gzgroup, * Adds all gizmos of \a gzgroup that can be selected to the head of \a listbase. * Added items need freeing! */ -void wm_gizmogroup_intersectable_gizmos_to_list(const wmGizmoGroup *gzgroup, ListBase *listbase) +void wm_gizmogroup_intersectable_gizmos_to_list(wmWindowManager *wm, + const wmGizmoGroup *gzgroup, + const int event_modifier, + BLI_Buffer *visible_gizmos) { - for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) { + int gzgroup_keymap_uses_modifier = -1; + for (wmGizmo *gz = gzgroup->gizmos.last; gz; gz = gz->prev) { if ((gz->flag & (WM_GIZMO_HIDDEN | WM_GIZMO_HIDDEN_SELECT)) == 0) { if (((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) && (gz->type->draw_select || gz->type->test_select)) || ((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0 && gz->type->test_select)) { - BLI_addhead(listbase, BLI_genericNodeN(gz)); + + if (!wm_gizmo_keymap_uses_event_modifier( + wm, gzgroup, gz, event_modifier, &gzgroup_keymap_uses_modifier)) { + continue; + } + + BLI_buffer_append(visible_gizmos, wmGizmo *, gz); } } } @@ -349,22 +390,6 @@ typedef struct GizmoTweakData { int init_event; /* initial event type */ int flag; /* tweak flags */ -#ifdef USE_DRAG_DETECT - /* True until the mouse is moved (only use when the operator has no modal). - * this allows some gizmos to be click-only. */ - enum { - /* Don't detect dragging. */ - DRAG_NOP = 0, - /* Detect dragging (wait until a drag or click is detected). */ - DRAG_DETECT, - /* Drag has started, idle until there is no active modal operator. - * This is needed because finishing the modal operator also exits - * the modal gizmo state (un-grabbs the cursor). - * Ideally this workaround could be removed later. */ - DRAG_IDLE, - } drag_state; -#endif - } GizmoTweakData; static bool gizmo_tweak_start(bContext *C, wmGizmoMap *gzmap, wmGizmo *gz, const wmEvent *event) @@ -409,7 +434,7 @@ static bool gizmo_tweak_start_and_finish( } else { if (gz->parent_gzgroup->type->invoke_prepare) { - gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz); + gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz, event); } /* Allow for 'button' gizmos, single click to run an action. */ WM_gizmo_operator_invoke(C, gz, gzop); @@ -449,47 +474,6 @@ static int gizmo_tweak_modal(bContext *C, wmOperator *op, const wmEvent *event) return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } -#ifdef USE_DRAG_DETECT - wmGizmoMap *gzmap = mtweak->gzmap; - if (mtweak->drag_state == DRAG_DETECT) { - if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { - if (len_manhattan_v2v2_int(&event->x, gzmap->gzmap_context.event_xy) >= - WM_EVENT_CURSOR_CLICK_DRAG_THRESHOLD) { - mtweak->drag_state = DRAG_IDLE; - gz->highlight_part = gz->drag_part; - } - } - else if (event->type == mtweak->init_event && event->val == KM_RELEASE) { - mtweak->drag_state = DRAG_NOP; - retval = OPERATOR_FINISHED; - } - - if (mtweak->drag_state != DRAG_DETECT) { - /* Follow logic in 'gizmo_tweak_invoke' */ - bool is_modal = false; - if (gizmo_tweak_start_and_finish(C, gzmap, gz, event, &is_modal)) { - if (is_modal) { - clear_modal = false; - } - } - else { - if (!gizmo_tweak_start(C, gzmap, gz, event)) { - retval = OPERATOR_FINISHED; - } - } - } - } - if (mtweak->drag_state == DRAG_IDLE) { - if (gzmap->gzmap_context.modal != NULL) { - return OPERATOR_PASS_THROUGH; - } - else { - gizmo_tweak_finish(C, op, false, false); - return OPERATOR_FINISHED; - } - } -#endif /* USE_DRAG_DETECT */ - if (retval == OPERATOR_FINISHED) { /* pass */ } @@ -560,35 +544,22 @@ static int gizmo_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *event) return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); } - bool use_drag_fallback = false; + const int highlight_part_init = gz->highlight_part; -#ifdef USE_DRAG_DETECT - use_drag_fallback = !ELEM(gz->drag_part, -1, gz->highlight_part); -#endif - - if (use_drag_fallback == false) { - if (gizmo_tweak_start_and_finish(C, gzmap, gz, event, NULL)) { - return OPERATOR_FINISHED; + if (gz->drag_part != -1) { + if (ISTWEAK(event->type) || (event->val == KM_CLICK_DRAG)) { + gz->highlight_part = gz->drag_part; } } - bool use_drag_detect = false; -#ifdef USE_DRAG_DETECT - if (use_drag_fallback) { - wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, gz->highlight_part); - if (gzop && gzop->type) { - if (gzop->type->modal == NULL) { - use_drag_detect = true; - } - } + if (gizmo_tweak_start_and_finish(C, gzmap, gz, event, NULL)) { + return OPERATOR_FINISHED; } -#endif - if (use_drag_detect == false) { - if (!gizmo_tweak_start(C, gzmap, gz, event)) { - /* failed to start */ - return OPERATOR_PASS_THROUGH; - } + if (!gizmo_tweak_start(C, gzmap, gz, event)) { + /* failed to start */ + gz->highlight_part = highlight_part_init; + return OPERATOR_PASS_THROUGH; } GizmoTweakData *mtweak = MEM_mallocN(sizeof(GizmoTweakData), __func__); @@ -599,10 +570,6 @@ static int gizmo_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *event) mtweak->gzmap = gzmap; mtweak->flag = 0; -#ifdef USE_DRAG_DETECT - mtweak->drag_state = use_drag_detect ? DRAG_DETECT : DRAG_NOP; -#endif - op->customdata = mtweak; WM_event_add_modal_handler(C, op); @@ -630,7 +597,7 @@ void GIZMOGROUP_OT_gizmo_tweak(wmOperatorType *ot) /** \} */ -static wmKeyMap *gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char *gzgroupname) +wmKeyMap *wm_gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf) { wmKeyMap *keymap; char name[KMAP_MAX_NAME]; @@ -645,7 +612,7 @@ static wmKeyMap *gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char {0, NULL, 0, NULL, NULL}, }; - BLI_snprintf(name, sizeof(name), "%s Tweak Modal Map", gzgroupname); + STRNCPY(name, "Generic Gizmo Tweak Modal Map"); keymap = WM_modalkeymap_get(keyconf, name); /* this function is called for each spacetype, only needs to add map once */ @@ -678,30 +645,54 @@ static wmKeyMap *gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char } /** - * Common default keymap for gizmo groups + * Common default keymap for gizmo groups. + * + * \param name: Typically #wmGizmoGroupType.name + * \param params: Typically #wmGizmoGroupType.gzmap_params */ -wmKeyMap *WM_gizmogroup_keymap_common(const wmGizmoGroupType *gzgt, wmKeyConfig *config) +wmKeyMap *WM_gizmogroup_keymap_template_ex(wmKeyConfig *config, + const char *name, + const struct wmGizmoMapType_Params *params) { /* Use area and region id since we might have multiple gizmos * with the same name in different areas/regions. */ - wmKeyMap *km = WM_keymap_ensure( - config, gzgt->name, gzgt->gzmap_params.spaceid, gzgt->gzmap_params.regionid); - - WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", LEFTMOUSE, KM_PRESS, KM_ANY, 0); - gizmogroup_tweak_modal_keymap(config, gzgt->name); + wmKeyMap *km = WM_keymap_ensure(config, name, params->spaceid, params->regionid); + if (BLI_listbase_is_empty(&km->items)) { + WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", LEFTMOUSE, KM_PRESS, KM_ANY, 0); + } return km; } +wmKeyMap *WM_gizmogroup_keymap_template(const wmGizmoGroupType *gzgt, wmKeyConfig *config) +{ + return WM_gizmogroup_keymap_template_ex(config, gzgt->name, &gzgt->gzmap_params); +} + +wmKeyMap *WM_gizmogroup_keymap_generic(const wmGizmoGroupType *UNUSED(gzgt), wmKeyConfig *config) +{ + struct wmGizmoMapType_Params params = { + .spaceid = SPACE_EMPTY, + .regionid = RGN_TYPE_WINDOW, + }; + return WM_gizmogroup_keymap_template_ex(config, "Generic Gizmo", ¶ms); +} + /** * Variation of #WM_gizmogroup_keymap_common but with keymap items for selection + * + * \param name: Typically #wmGizmoGroupType.name + * \param params: Typically #wmGizmoGroupType.gzmap_params */ -wmKeyMap *WM_gizmogroup_keymap_common_select(const wmGizmoGroupType *gzgt, wmKeyConfig *config) +wmKeyMap *WM_gizmogroup_keymap_template_select_ex(wmKeyConfig *config, + const char *name, + const struct wmGizmoMapType_Params *params) { /* Use area and region id since we might have multiple gizmos * with the same name in different areas/regions. */ - wmKeyMap *km = WM_keymap_ensure( - config, gzgt->name, gzgt->gzmap_params.spaceid, gzgt->gzmap_params.regionid); + wmKeyMap *km = WM_keymap_ensure(config, name, params->spaceid, params->regionid); + const bool do_init = BLI_listbase_is_empty(&km->items); + /* FIXME(campbell) */ #if 0 const int select_mouse = (U.flag & USER_LMOUSESELECT) ? LEFTMOUSE : RIGHTMOUSE; @@ -713,23 +704,42 @@ wmKeyMap *WM_gizmogroup_keymap_common_select(const wmGizmoGroupType *gzgt, wmKey const int action_mouse = LEFTMOUSE; #endif - WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", action_mouse, KM_PRESS, KM_ANY, 0); - WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", select_tweak, KM_ANY, 0, 0); - gizmogroup_tweak_modal_keymap(config, gzgt->name); + if (do_init) { + WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", action_mouse, KM_PRESS, KM_ANY, 0); + WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", select_tweak, KM_ANY, 0, 0); + } - wmKeyMapItem *kmi = WM_keymap_add_item( - km, "GIZMOGROUP_OT_gizmo_select", select_mouse, KM_PRESS, 0, 0); - RNA_boolean_set(kmi->ptr, "extend", false); - RNA_boolean_set(kmi->ptr, "deselect", false); - RNA_boolean_set(kmi->ptr, "toggle", false); - kmi = WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_select", select_mouse, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "extend", false); - RNA_boolean_set(kmi->ptr, "deselect", false); - RNA_boolean_set(kmi->ptr, "toggle", true); + if (do_init) { + wmKeyMapItem *kmi = WM_keymap_add_item( + km, "GIZMOGROUP_OT_gizmo_select", select_mouse, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "extend", false); + RNA_boolean_set(kmi->ptr, "deselect", false); + RNA_boolean_set(kmi->ptr, "toggle", false); + kmi = WM_keymap_add_item( + km, "GIZMOGROUP_OT_gizmo_select", select_mouse, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "extend", false); + RNA_boolean_set(kmi->ptr, "deselect", false); + RNA_boolean_set(kmi->ptr, "toggle", true); + } return km; } +wmKeyMap *WM_gizmogroup_keymap_template_select(const wmGizmoGroupType *gzgt, wmKeyConfig *config) +{ + return WM_gizmogroup_keymap_template_select_ex(config, gzgt->name, &gzgt->gzmap_params); +} + +wmKeyMap *WM_gizmogroup_keymap_generic_select(const wmGizmoGroupType *UNUSED(gzgt), + wmKeyConfig *config) +{ + struct wmGizmoMapType_Params params = { + .spaceid = SPACE_EMPTY, + .regionid = RGN_TYPE_WINDOW, + }; + return WM_gizmogroup_keymap_template_select_ex(config, "Generic Gizmo Select", ¶ms); +} + /** \} */ /* wmGizmoGroup */ /* -------------------------------------------------------------------- */ @@ -874,8 +884,12 @@ void WM_gizmomaptype_group_unlink(bContext *C, WM_gizmomaptype_group_free(gzgt_ref); } + /* TODO(campbell): Gizmos may share keymaps, for now don't + * remove however we could flag them as temporary/owned by the gizmo. */ +#if 0 /* Note, we may want to keep this keymap for editing */ WM_keymap_remove(gzgt->keyconf, gzgt->keymap); +#endif BLI_assert(WM_gizmomaptype_group_find_ptr(gzmap_type, gzgt) == NULL); } diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c index 7c8db18c0ca..d09e088af7f 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c @@ -97,10 +97,10 @@ static void wm_gizmogrouptype_append__end(wmGizmoGroupType *gzgt) /* if not set, use default */ if (gzgt->setup_keymap == NULL) { if (gzgt->flag & WM_GIZMOGROUPTYPE_SELECT) { - gzgt->setup_keymap = WM_gizmogroup_keymap_common_select; + gzgt->setup_keymap = WM_gizmogroup_keymap_generic_select; } else { - gzgt->setup_keymap = WM_gizmogroup_keymap_common; + gzgt->setup_keymap = WM_gizmogroup_keymap_generic; } } diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h index 1a0babdccb5..1018cc4d58b 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h @@ -21,6 +21,7 @@ #ifndef __WM_GIZMO_INTERN_H__ #define __WM_GIZMO_INTERN_H__ +struct BLI_Buffer; struct GHashIterator; struct GizmoGeomInfo; struct wmGizmoMap; @@ -60,17 +61,23 @@ struct wmGizmoGroup *wm_gizmogroup_new_from_type(struct wmGizmoMap *gzmap, struct wmGizmoGroupType *gzgt); void wm_gizmogroup_free(bContext *C, struct wmGizmoGroup *gzgroup); void wm_gizmogroup_gizmo_register(struct wmGizmoGroup *gzgroup, struct wmGizmo *gz); -struct wmGizmo *wm_gizmogroup_find_intersected_gizmo(const struct wmGizmoGroup *gzgroup, +struct wmGizmo *wm_gizmogroup_find_intersected_gizmo(wmWindowManager *wm, + const struct wmGizmoGroup *gzgroup, struct bContext *C, - const struct wmEvent *event, + const int event_modifier, + const int mval[2], int *r_part); -void wm_gizmogroup_intersectable_gizmos_to_list(const struct wmGizmoGroup *gzgroup, - struct ListBase *listbase); +void wm_gizmogroup_intersectable_gizmos_to_list(wmWindowManager *wm, + const struct wmGizmoGroup *gzgroup, + const int event_modifier, + struct BLI_Buffer *visible_gizmos); bool wm_gizmogroup_is_visible_in_drawstep(const struct wmGizmoGroup *gzgroup, const eWM_GizmoFlagMapDrawStep drawstep); void wm_gizmogrouptype_setup_keymap(struct wmGizmoGroupType *gzgt, struct wmKeyConfig *keyconf); +wmKeyMap *wm_gizmogroup_tweak_modal_keymap(struct wmKeyConfig *keyconf); + /* -------------------------------------------------------------------- */ /* wmGizmoMap */ diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c index 9f36af8b616..6783a294500 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c @@ -23,12 +23,12 @@ #include <string.h> +#include "BLI_buffer.h" #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,24 +470,19 @@ void WM_gizmomap_draw(wmGizmoMap *gzmap, BLI_assert(BLI_listbase_is_empty(&draw_gizmos)); } -static void gizmo_draw_select_3D_loop(const bContext *C, - ListBase *visible_gizmos, - const wmGizmo *gz_stop, +static void gizmo_draw_select_3d_loop(const bContext *C, + wmGizmo **visible_gizmos, + const int visible_gizmos_len, bool *r_use_select_bias) { - int select_id = 0; - wmGizmo *gz; /* TODO(campbell): this depends on depth buffer being written to, * currently broken for the 3D view. */ bool is_depth_prev = false; bool is_depth_skip_prev = false; - for (LinkData *link = visible_gizmos->first; link; link = link->next, select_id++) { - gz = link->data; - if (gz == gz_stop) { - break; - } + for (int select_id = 0; select_id < visible_gizmos_len; select_id++) { + wmGizmo *gz = visible_gizmos[select_id]; if (gz->type->draw_select == NULL) { continue; } @@ -531,11 +526,11 @@ static void gizmo_draw_select_3D_loop(const bContext *C, } } -static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos, +static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos, + const int visible_gizmos_len, const bContext *C, const int co[2], - const int hotspot, - const wmGizmo *gz_stop) + const int hotspot) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); @@ -554,13 +549,13 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos, 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, &use_select_bias); + gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &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, &use_select_bias); + gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias); GPU_select_end(); } @@ -568,11 +563,6 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos, CTX_wm_window(C), CTX_data_depsgraph(C), CTX_data_scene(C), ar, v3d, NULL, NULL, NULL); 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); @@ -590,7 +580,7 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos, for (int i = 0; i < hits; i++, buf_iter += 4) { BLI_assert(buf_iter[3] != -1); - wmGizmo *gz = gizmo_table[buf_iter[3] >> 8]; + wmGizmo *gz = visible_gizmos[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); @@ -605,7 +595,6 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos, hit_found = buf_iter[3]; } } - BLI_array_free(gizmo_table); return hit_found; } else { @@ -619,10 +608,12 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos, */ static wmGizmo *gizmo_find_intersected_3d(bContext *C, const int co[2], - ListBase *visible_gizmos, + wmGizmo **visible_gizmos, + const int visible_gizmos_len, int *r_part) { wmGizmo *result = NULL; + int visible_gizmos_len_trim = visible_gizmos_len; int hit = -1; *r_part = 0; @@ -633,14 +624,15 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C, /* Search for 3D gizmo's that use the 2D callback for checking intersections. */ bool has_3d = false; { - int select_id = 0; - for (LinkData *link = visible_gizmos->first; link; link = link->next, select_id++) { - wmGizmo *gz = link->data; + for (int select_id = 0; select_id < visible_gizmos_len; select_id++) { + wmGizmo *gz = visible_gizmos[select_id]; /* With both defined, favor the 3D, incase the gizmo can be used in 2D or 3D views. */ if (gz->type->test_select && (gz->type->draw_select == NULL)) { if ((*r_part = gz->type->test_select(C, gz, co)) != -1) { hit = select_id; result = gz; + /* Don't search past this when checking intersections. */ + visible_gizmos_len_trim = select_id; break; } } @@ -659,23 +651,19 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C, 10 * U.pixelsize, }; for (int i = 0; i < ARRAY_SIZE(hotspot_radii); i++) { - hit = gizmo_find_intersected_3d_intern(visible_gizmos, C, co, hotspot_radii[i], result); + hit = gizmo_find_intersected_3d_intern( + visible_gizmos, visible_gizmos_len_trim, C, co, hotspot_radii[i]); if (hit != -1) { break; } } if (hit != -1) { - LinkData *link = BLI_findlink(visible_gizmos, hit >> 8); - if (link != NULL) { - *r_part = hit & 255; - result = link->data; - } - else { - /* All gizmos should use selection ID they're given as part of the callback, - * if they don't it will attempt tp lookup non-existing index. */ - BLI_assert(0); - } + const int select_id = hit >> 8; + const int select_part = hit & 0xff; + BLI_assert(select_id < visible_gizmos_len); + *r_part = select_part; + result = visible_gizmos[select_id]; } } @@ -691,14 +679,26 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap, const wmEvent *event, int *r_part) { + wmWindowManager *wm = CTX_wm_manager(C); wmGizmo *gz = NULL; - ListBase visible_3d_gizmos = {NULL}; + BLI_buffer_declare_static(wmGizmo *, visible_3d_gizmos, BLI_BUFFER_NOP, 128); bool do_step[WM_GIZMOMAP_DRAWSTEP_MAX]; + int mval[2] = {UNPACK2(event->mval)}; + + /* Ensure for drag events we use the location where the user clicked. + * Without this click-dragging on a gizmo can accidentally act on the wrong gizmo. */ + if (ISTWEAK(event->type) || (event->val == KM_CLICK_DRAG)) { + mval[0] += event->x - event->prevclickx; + mval[1] += event->y - event->prevclicky; + } + for (int i = 0; i < ARRAY_SIZE(do_step); i++) { do_step[i] = WM_gizmo_context_check_drawstep(C, i); } + const int event_modifier = WM_event_modifier_flag(event); + for (wmGizmoGroup *gzgroup = gzmap->groups.first; gzgroup; gzgroup = gzgroup->next) { /* If it were important we could initialize here, @@ -724,10 +724,12 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap, /* cleared below */ } if (step == WM_GIZMOMAP_DRAWSTEP_3D) { - wm_gizmogroup_intersectable_gizmos_to_list(gzgroup, &visible_3d_gizmos); + wm_gizmogroup_intersectable_gizmos_to_list( + wm, gzgroup, event_modifier, &visible_3d_gizmos); } else if (step == WM_GIZMOMAP_DRAWSTEP_2D) { - if ((gz = wm_gizmogroup_find_intersected_gizmo(gzgroup, C, event, r_part))) { + if ((gz = wm_gizmogroup_find_intersected_gizmo( + wm, gzgroup, C, event_modifier, mval, r_part))) { break; } } @@ -735,13 +737,14 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap, } } - if (!BLI_listbase_is_empty(&visible_3d_gizmos)) { + if (visible_3d_gizmos.count) { /* 2D gizmos get priority. */ if (gz == NULL) { - gz = gizmo_find_intersected_3d(C, event->mval, &visible_3d_gizmos, r_part); + gz = gizmo_find_intersected_3d( + C, mval, visible_3d_gizmos.data, visible_3d_gizmos.count, r_part); } - BLI_freelistN(&visible_3d_gizmos); } + BLI_buffer_free(&visible_3d_gizmos); gzmap->update_flag[WM_GIZMOMAP_DRAWSTEP_3D] &= ~GIZMOMAP_IS_REFRESH_CALLBACK; gzmap->update_flag[WM_GIZMOMAP_DRAWSTEP_2D] &= ~GIZMOMAP_IS_REFRESH_CALLBACK; @@ -1021,7 +1024,7 @@ void wm_gizmomap_modal_set( /* Use even if we don't have invoke, so we can setup data before an operator runs. */ if (gz->parent_gzgroup->type->invoke_prepare) { - gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz); + gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz, event); } if (gz->type->invoke && (gz->type->modal || gz->custom_modal)) { @@ -1216,6 +1219,8 @@ void wm_gizmos_keymap(wmKeyConfig *keyconf) wm_gizmogrouptype_setup_keymap(gzgt_ref->type, keyconf); } } + + wm_gizmogroup_tweak_modal_keymap(keyconf); } /** \} */ /* wmGizmoMapType */ diff --git a/source/blender/windowmanager/gizmo/wm_gizmo_fn.h b/source/blender/windowmanager/gizmo/wm_gizmo_fn.h index 2aada0f202a..242b0f6de80 100644 --- a/source/blender/windowmanager/gizmo/wm_gizmo_fn.h +++ b/source/blender/windowmanager/gizmo/wm_gizmo_fn.h @@ -33,7 +33,8 @@ typedef void (*wmGizmoGroupFnRefresh)(const struct bContext *, struct wmGizmoGro typedef void (*wmGizmoGroupFnDrawPrepare)(const struct bContext *, struct wmGizmoGroup *); typedef void (*wmGizmoGroupFnInvokePrepare)(const struct bContext *, struct wmGizmoGroup *, - struct wmGizmo *); + struct wmGizmo *, + const struct wmEvent *); typedef struct wmKeyMap *(*wmGizmoGroupFnSetupKeymap)(const struct wmGizmoGroupType *, struct wmKeyConfig *)ATTR_WARN_UNUSED_RESULT; typedef void (*wmGizmoGroupFnMsgBusSubscribe)(const struct bContext *, diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 6ecbf4ef5ac..6b6a04cacad 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -917,6 +917,17 @@ void WM_draw_region_free(ARegion *ar) ar->visible = 0; } +void wm_draw_region_test(bContext *C, ScrArea *sa, ARegion *ar) +{ + /* Function for redraw timer benchmark. */ + bool use_viewport = wm_region_use_viewport(sa, ar); + wm_draw_region_buffer_create(ar, false, use_viewport); + wm_draw_region_bind(ar, 0); + ED_region_do_draw(C, ar); + wm_draw_region_unbind(ar, 0); + ar->do_draw = false; +} + void WM_redraw_windows(bContext *C) { wmWindow *win_prev = CTX_wm_window(C); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 6683085e6d3..51b2ca6a3d0 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -732,6 +732,24 @@ void WM_operator_region_active_win_set(bContext *C) } } +int WM_event_modifier_flag(const wmEvent *event) +{ + int flag = 0; + if (event->ctrl) { + flag |= KM_CTRL; + } + if (event->alt) { + flag |= KM_ALT; + } + if (event->shift) { + flag |= KM_SHIFT; + } + if (event->oskey) { + flag |= KM_OSKEY; + } + return flag; +} + /* for debugging only, getting inspecting events manually is tedious */ void WM_event_print(const wmEvent *event) { @@ -2484,15 +2502,134 @@ static int wm_action_not_handled(int action) return action == WM_HANDLER_CONTINUE || action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL); } +#define PRINT \ + if (do_debug_handler) \ + printf + +static int wm_handlers_do_keymap_with_keymap_handler( + /* From 'wm_handlers_do_intern' */ + bContext *C, + wmEvent *event, + ListBase *handlers, + wmEventHandler_Keymap *handler, + /* Additional. */ + wmKeyMap *keymap, + const bool do_debug_handler) +{ + int action = WM_HANDLER_CONTINUE; + + PRINT("%s: checking '%s' ...", __func__, keymap->idname); + + if (keymap == NULL) { + /* Only callback is allowed to have NULL keymaps. */ + BLI_assert(handler->dynamic.keymap_fn); + } + else { + if (WM_keymap_poll(C, keymap)) { + + PRINT("pass\n"); + + for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { + if (wm_eventmatch(event, kmi)) { + struct wmEventHandler_KeymapPost keymap_post = handler->post; + + PRINT("%s: item matched '%s'\n", __func__, kmi->idname); + + /* weak, but allows interactive callback to not use rawkey */ + event->keymap_idname = kmi->idname; + + action |= wm_handler_operator_call(C, handlers, &handler->head, event, kmi->ptr); + + if (action & WM_HANDLER_BREAK) { + /* not always_pass here, it denotes removed handler_base */ + CLOG_INFO(WM_LOG_HANDLERS, 2, "handled! '%s'", kmi->idname); + if (keymap_post.post_fn != NULL) { + keymap_post.post_fn(keymap, kmi, keymap_post.user_data); + } + break; + } + else { + if (action & WM_HANDLER_HANDLED) { + CLOG_INFO(WM_LOG_HANDLERS, 2, "handled - and pass on! '%s'", kmi->idname); + } + else { + CLOG_INFO(WM_LOG_HANDLERS, 2, "un-handled '%s'", kmi->idname); + } + } + } + } + } + else { + PRINT("fail\n"); + } + } + + return action; +} + +static bool wm_handlers_do_keymap_with_gizmo_handler( + /* From 'wm_handlers_do_intern' */ + bContext *C, + wmEvent *event, + ListBase *handlers, + wmEventHandler_Gizmo *handler, + /* Additional. */ + wmGizmoGroup *gzgroup, + wmKeyMap *keymap, + const bool do_debug_handler) +{ + int action = WM_HANDLER_CONTINUE; + wmKeyMapItem *kmi; + + PRINT("%s: checking '%s' ...", __func__, keymap->idname); + + if (WM_keymap_poll(C, keymap)) { + PRINT("pass\n"); + for (kmi = keymap->items.first; kmi; kmi = kmi->next) { + if (wm_eventmatch(event, kmi)) { + PRINT("%s: item matched '%s'\n", __func__, kmi->idname); + + /* weak, but allows interactive callback to not use rawkey */ + event->keymap_idname = kmi->idname; + + CTX_wm_gizmo_group_set(C, gzgroup); + + /* handler->op is called later, we want keymap op to be triggered here */ + action |= wm_handler_operator_call(C, handlers, &handler->head, event, kmi->ptr); + + CTX_wm_gizmo_group_set(C, NULL); + + if (action & WM_HANDLER_BREAK) { + if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) { + printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname); + } + break; + } + else { + if (action & WM_HANDLER_HANDLED) { + if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) { + printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname); + } + } + else { + PRINT("%s: un-handled '%s'\n", __func__, kmi->idname); + } + } + } + } + } + else { + PRINT("fail\n"); + } + return action; +} + static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers) { const bool do_debug_handler = (G.debug & G_DEBUG_HANDLERS) && /* comment this out to flood the console! (if you really want to test) */ !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE); -#define PRINT \ - if (do_debug_handler) \ - printf wmWindowManager *wm = CTX_wm_manager(C); int action = WM_HANDLER_CONTINUE; @@ -2530,50 +2667,8 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) { wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); - - PRINT("%s: checking '%s' ...", __func__, keymap->idname); - - if (keymap == NULL) { - /* Only callback is allowed to have NULL keymaps. */ - BLI_assert(handler->dynamic.keymap_fn); - } - else if (WM_keymap_poll(C, keymap)) { - - PRINT("pass\n"); - - for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { - if (wm_eventmatch(event, kmi)) { - struct wmEventHandler_KeymapPost keymap_post = handler->post; - - PRINT("%s: item matched '%s'\n", __func__, kmi->idname); - - /* weak, but allows interactive callback to not use rawkey */ - event->keymap_idname = kmi->idname; - - action |= wm_handler_operator_call(C, handlers, handler_base, event, kmi->ptr); - - if (action & WM_HANDLER_BREAK) { - /* not always_pass here, it denotes removed handler_base */ - CLOG_INFO(WM_LOG_HANDLERS, 2, "handled! '%s'", kmi->idname); - if (keymap_post.post_fn != NULL) { - keymap_post.post_fn(keymap, kmi, keymap_post.user_data); - } - break; - } - else { - if (action & WM_HANDLER_HANDLED) { - CLOG_INFO(WM_LOG_HANDLERS, 2, "handled - and pass on! '%s'", kmi->idname); - } - else { - CLOG_INFO(WM_LOG_HANDLERS, 2, "un-handled '%s'", kmi->idname); - } - } - } - } - } - else { - PRINT("fail\n"); - } + action |= wm_handlers_do_keymap_with_keymap_handler( + C, event, handlers, handler, keymap, do_debug_handler); } else if (handler_base->type == WM_HANDLER_TYPE_UI) { wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base; @@ -2644,8 +2739,27 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers wm_gizmomap_handler_context_gizmo(C, handler); wm_region_mouse_co(C, event); + /* Drag events use the previous click location to highlight the gizmos, + * Get the highlight again in case the user dragged off the gizmo. */ + const bool is_event_drag = ISTWEAK(event->type) || (event->val == KM_CLICK_DRAG); + const bool is_event_modifier = ISKEYMODIFIER(event->type); + + bool handle_highlight = false; + bool handle_keymap = false; + /* handle gizmo highlighting */ - if (event->type == MOUSEMOVE && !wm_gizmomap_modal_get(gzmap)) { + if (!wm_gizmomap_modal_get(gzmap) && + ((event->type == MOUSEMOVE) || is_event_modifier || is_event_drag)) { + handle_highlight = true; + if (is_event_modifier || is_event_drag) { + handle_keymap = true; + } + } + else { + handle_keymap = true; + } + + if (handle_highlight) { int part; gz = wm_gizmomap_highlight_find(gzmap, C, event, &part); if (wm_gizmomap_highlight_set(gzmap, C, gz, part) && gz != NULL) { @@ -2654,98 +2768,35 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers } } } - else { - /* Either we operate on a single highlighted item - * or groups attached to the selected gizmos. - * To simplify things both cases loop over an array of items. */ - wmGizmoGroup *gzgroup_first; - bool is_gzgroup_single; - - if (ISMOUSE(event->type)) { - /* Keep gz set as-is, just fake single selection. */ - if (gz) { - gzgroup_first = gz->parent_gzgroup; - } - else { - gzgroup_first = NULL; - } - is_gzgroup_single = true; - } - else { - if (WM_gizmomap_is_any_selected(gzmap)) { - const ListBase *groups = WM_gizmomap_group_list(gzmap); - gzgroup_first = groups->first; - } - else { - gzgroup_first = NULL; - } - is_gzgroup_single = false; + + if (handle_keymap) { + /* Handle highlight gizmo. */ + if (gz != NULL) { + wmGizmoGroup *gzgroup = gz->parent_gzgroup; + wmKeyMap *keymap = WM_keymap_active(wm, + gz->keymap ? gz->keymap : gzgroup->type->keymap); + action |= wm_handlers_do_keymap_with_gizmo_handler( + C, event, handlers, handler, gzgroup, keymap, do_debug_handler); } /* Don't use from now on. */ gz = NULL; - for (wmGizmoGroup *gzgroup = gzgroup_first; gzgroup; gzgroup = gzgroup->next) { - /* get user customized keymap from default one */ - - if ((is_gzgroup_single == false) && - /* We might want to change the logic here and use some kind of gizmo edit-mode. - * For now just use keymap when a selection exists. */ - wm_gizmogroup_is_any_selected(gzgroup) == false) { - continue; - } - - wmKeyMap *keymap = WM_keymap_active(wm, gzgroup->type->keymap); - wmKeyMapItem *kmi; - - PRINT("%s: checking '%s' ...", __func__, keymap->idname); - - if (WM_keymap_poll(C, keymap)) { - PRINT("pass\n"); - for (kmi = keymap->items.first; kmi; kmi = kmi->next) { - if (wm_eventmatch(event, kmi)) { - PRINT("%s: item matched '%s'\n", __func__, kmi->idname); - - /* weak, but allows interactive callback to not use rawkey */ - event->keymap_idname = kmi->idname; - - CTX_wm_gizmo_group_set(C, gzgroup); - - /* handler->op is called later, we want keymap op to be triggered here */ - action |= wm_handler_operator_call(C, handlers, handler_base, event, kmi->ptr); - - CTX_wm_gizmo_group_set(C, NULL); - + /* Fallback to selected gizmo (when un-handled). */ + if ((action & WM_HANDLER_BREAK) == 0) { + if (WM_gizmomap_is_any_selected(gzmap)) { + const ListBase *groups = WM_gizmomap_group_list(gzmap); + for (wmGizmoGroup *gzgroup = groups->first; gzgroup; gzgroup = gzgroup->next) { + if (wm_gizmogroup_is_any_selected(gzgroup)) { + wmKeyMap *keymap = WM_keymap_active(wm, gzgroup->type->keymap); + action |= wm_handlers_do_keymap_with_gizmo_handler( + C, event, handlers, handler, gzgroup, keymap, do_debug_handler); if (action & WM_HANDLER_BREAK) { - if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) { - printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname); - } break; } - else { - if (action & WM_HANDLER_HANDLED) { - if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) { - printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname); - } - } - else { - PRINT("%s: un-handled '%s'\n", __func__, kmi->idname); - } - } } } } - else { - PRINT("fail\n"); - } - - if (action & WM_HANDLER_BREAK) { - break; - } - - if (is_gzgroup_single) { - break; - } } } @@ -2802,11 +2853,11 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers wm_cursor_arrow_move(CTX_wm_window(C), event); } -#undef PRINT - return action; } +#undef PRINT + /* this calls handlers twice - to solve (double-)click events */ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) { diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 9e9619c698d..d93d4a618d7 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -490,18 +490,21 @@ void wm_file_read_report(bContext *C, Main *bmain) static void wm_file_read_post(bContext *C, const bool is_startup_file, const bool is_factory_startup, + const bool use_data, + const bool use_userdef, const bool reset_app_template) { bool addons_loaded = false; wmWindowManager *wm = CTX_wm_manager(C); - if (!G.background) { - /* remove windows which failed to be added via WM_check */ - wm_window_ghostwindows_remove_invalid(C, wm); + if (use_data) { + if (!G.background) { + /* remove windows which failed to be added via WM_check */ + wm_window_ghostwindows_remove_invalid(C, wm); + } + CTX_wm_window_set(C, wm->windows.first); } - CTX_wm_window_set(C, wm->windows.first); - #ifdef WITH_PYTHON if (is_startup_file) { /* possible python hasn't been initialized */ @@ -515,41 +518,56 @@ static void wm_file_read_post(bContext *C, /* sync addons, these may have changed from the defaults */ BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()"); } - BPY_python_reset(C); + if (use_data) { + BPY_python_reset(C); + } addons_loaded = true; } } else { /* run any texts that were loaded in and flagged as modules */ - BPY_python_reset(C); + if (use_data) { + BPY_python_reset(C); + } addons_loaded = true; } #else UNUSED_VARS(is_startup_file, reset_app_template); #endif /* WITH_PYTHON */ - WM_operatortype_last_properties_clear_all(); - - /* important to do before NULL'ing the context */ Main *bmain = CTX_data_main(C); - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_VERSION_UPDATE); - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_POST); - if (is_factory_startup) { - BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_FACTORY_STARTUP_POST); + + if (use_userdef) { + if (is_factory_startup) { + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_FACTORY_USERDEF_POST); + } } - /* After load post, so for example the driver namespace can be filled - * before evaluating the depsgraph. */ - DEG_on_visible_update(bmain, true); - wm_event_do_depsgraph(C); + if (use_data) { + /* important to do before NULL'ing the context */ + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_VERSION_UPDATE); + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_POST); + if (is_factory_startup) { + BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_FACTORY_STARTUP_POST); + } + } + + if (use_data) { + WM_operatortype_last_properties_clear_all(); - ED_editors_init(C); + /* After load post, so for example the driver namespace can be filled + * before evaluating the depsgraph. */ + DEG_on_visible_update(bmain, true); + wm_event_do_depsgraph(C); + + ED_editors_init(C); #if 1 - WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); + WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL); #else - WM_msg_publish_static(CTX_wm_message_bus(C), WM_MSG_STATICTYPE_FILE_READ); + WM_msg_publish_static(CTX_wm_message_bus(C), WM_MSG_STATICTYPE_FILE_READ); #endif + } /* report any errors. * currently disabled if addons aren't yet loaded */ @@ -557,25 +575,29 @@ static void wm_file_read_post(bContext *C, wm_file_read_report(C, bmain); } - if (!G.background) { - if (wm->undo_stack == NULL) { - wm->undo_stack = BKE_undosys_stack_create(); - } - else { - BKE_undosys_stack_clear(wm->undo_stack); + if (use_data) { + if (!G.background) { + if (wm->undo_stack == NULL) { + wm->undo_stack = BKE_undosys_stack_create(); + } + else { + BKE_undosys_stack_clear(wm->undo_stack); + } + BKE_undosys_stack_init_from_main(wm->undo_stack, bmain); + BKE_undosys_stack_init_from_context(wm->undo_stack, C); } - BKE_undosys_stack_init_from_main(wm->undo_stack, bmain); - BKE_undosys_stack_init_from_context(wm->undo_stack, C); } - if (!G.background) { - /* in background mode this makes it hard to load - * a blend file and do anything since the screen - * won't be set to a valid value again */ - CTX_wm_window_set(C, NULL); /* exits queues */ + if (use_data) { + if (!G.background) { + /* in background mode this makes it hard to load + * a blend file and do anything since the screen + * won't be set to a valid value again */ + CTX_wm_window_set(C, NULL); /* exits queues */ - /* Ensure tools are registered. */ - WM_toolsystem_init(C); + /* Ensure tools are registered. */ + WM_toolsystem_init(C); + } } } @@ -602,6 +624,8 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) /* we didn't succeed, now try to read Blender file */ if (retval == BKE_READ_EXOTIC_OK_BLEND) { + bool use_data = true; + bool use_userdef = false; const int G_f_orig = G.f; ListBase wmbase; @@ -640,6 +664,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) if (retval == BKE_BLENDFILE_READ_OK_USERPREFS) { /* in case a userdef is read from regular .blend */ wm_init_userdef(bmain, false); + use_userdef = true; } if (retval != BKE_BLENDFILE_READ_FAIL) { @@ -648,7 +673,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) } } - wm_file_read_post(C, false, false, false); + wm_file_read_post(C, false, false, use_data, use_userdef, false); success = true; } @@ -953,7 +978,7 @@ void wm_homefile_read(bContext *C, } } } - if (BLI_listbase_is_empty(&wmbase)) { + if (use_data && BLI_listbase_is_empty(&wmbase)) { wm_clear_default_size(C); } } @@ -1041,10 +1066,10 @@ void wm_homefile_read(bContext *C, /* 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, use_data, use_userdef, reset_app_template); + if (r_is_factory_startup) { *r_is_factory_startup = is_factory_startup; } @@ -1245,7 +1270,6 @@ static ImBuf *blend_file_thumb(const bContext *C, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2, IB_rect, - V3D_OFSDRAW_NONE, R_ALPHAPREMUL, 0, NULL, @@ -1653,6 +1677,7 @@ static int wm_userpref_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED { bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare"); BLI_addtail(&U.autoexec_paths, path_cmp); + U.runtime.is_dirty = true; return OPERATOR_FINISHED; } @@ -1673,6 +1698,7 @@ static int wm_userpref_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op) bPathCompare *path_cmp = BLI_findlink(&U.autoexec_paths, index); if (path_cmp) { BLI_freelinkN(&U.autoexec_paths, path_cmp); + U.runtime.is_dirty = true; } return OPERATOR_FINISHED; } @@ -1939,7 +1965,7 @@ static void wm_free_operator_properties_callback(void *user_data) static int wm_homefile_read_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (U.uiflag & USER_SAVE_PROMPT && wm_file_or_image_is_modified(C)) { - GenericCallback *callback = MEM_callocN(sizeof(*callback), __func__); + wmGenericCallback *callback = MEM_callocN(sizeof(*callback), __func__); callback->exec = wm_homefile_read_after_dialog_callback; callback->user_data = IDP_CopyProperty(op->properties); callback->free_user_data = wm_free_operator_properties_callback; @@ -2105,7 +2131,7 @@ static int wm_open_mainfile__discard_changes(bContext *C, wmOperator *op) } if (U.uiflag & USER_SAVE_PROMPT && wm_file_or_image_is_modified(C)) { - GenericCallback *callback = MEM_callocN(sizeof(*callback), __func__); + wmGenericCallback *callback = MEM_callocN(sizeof(*callback), __func__); callback->exec = wm_open_mainfile_after_dialog_callback; callback->user_data = IDP_CopyProperty(op->properties); callback->free_user_data = wm_free_operator_properties_callback; @@ -2855,7 +2881,7 @@ static void wm_block_file_close_cancel(bContext *C, void *arg_block, void *UNUSE static void wm_block_file_close_discard(bContext *C, void *arg_block, void *arg_data) { - GenericCallback *callback = wm_generic_callback_steal((GenericCallback *)arg_data); + wmGenericCallback *callback = WM_generic_callback_steal((wmGenericCallback *)arg_data); /* Close the popup before executing the callback. Otherwise * the popup might be closed by the callback, which will lead @@ -2864,12 +2890,12 @@ static void wm_block_file_close_discard(bContext *C, void *arg_block, void *arg_ UI_popup_block_close(C, win, arg_block); callback->exec(C, callback->user_data); - wm_generic_callback_free(callback); + WM_generic_callback_free(callback); } static void wm_block_file_close_save(bContext *C, void *arg_block, void *arg_data) { - GenericCallback *callback = wm_generic_callback_steal((GenericCallback *)arg_data); + wmGenericCallback *callback = WM_generic_callback_steal((wmGenericCallback *)arg_data); bool execute_callback = true; wmWindow *win = CTX_wm_window(C); @@ -2897,10 +2923,10 @@ static void wm_block_file_close_save(bContext *C, void *arg_block, void *arg_dat if (execute_callback) { callback->exec(C, callback->user_data); } - wm_generic_callback_free(callback); + WM_generic_callback_free(callback); } -static void wm_block_file_close_cancel_button(uiBlock *block, GenericCallback *post_action) +static void wm_block_file_close_cancel_button(uiBlock *block, wmGenericCallback *post_action) { uiBut *but = uiDefIconTextBut( block, UI_BTYPE_BUT, 0, 0, IFACE_("Cancel"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, ""); @@ -2908,7 +2934,7 @@ static void wm_block_file_close_cancel_button(uiBlock *block, GenericCallback *p UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT); } -static void wm_block_file_close_discard_button(uiBlock *block, GenericCallback *post_action) +static void wm_block_file_close_discard_button(uiBlock *block, wmGenericCallback *post_action) { uiBut *but = uiDefIconTextBut( block, UI_BTYPE_BUT, 0, 0, IFACE_("Discard Changes"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, ""); @@ -2916,7 +2942,7 @@ static void wm_block_file_close_discard_button(uiBlock *block, GenericCallback * UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT); } -static void wm_block_file_close_save_button(uiBlock *block, GenericCallback *post_action) +static void wm_block_file_close_save_button(uiBlock *block, wmGenericCallback *post_action) { uiBut *but = uiDefIconTextBut( block, UI_BTYPE_BUT, 0, 0, IFACE_("Save"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, ""); @@ -2925,13 +2951,15 @@ static void wm_block_file_close_save_button(uiBlock *block, GenericCallback *pos UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT); } +static const char *close_file_dialog_name = "file_close_popup"; + static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegion *ar, void *arg1) { - GenericCallback *post_action = (GenericCallback *)arg1; + wmGenericCallback *post_action = (wmGenericCallback *)arg1; Main *bmain = CTX_data_main(C); uiStyle *style = UI_style_get(); - uiBlock *block = UI_block_begin(C, ar, "file_close_popup", UI_EMBOSS); + uiBlock *block = UI_block_begin(C, ar, close_file_dialog_name, UI_EMBOSS); UI_block_flag_enable( block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT); @@ -3020,13 +3048,13 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi else { /* macOS and Linux standard layout. */ uiLayout *col = uiLayoutColumn(split, false); - wm_block_file_close_cancel_button(block, post_action); + wm_block_file_close_discard_button(block, post_action); col = uiLayoutColumn(split, false); uiItemS(col); col = uiLayoutColumn(split, false); - wm_block_file_close_discard_button(block, post_action); + wm_block_file_close_cancel_button(block, post_action); col = uiLayoutColumn(split, false); wm_block_file_close_save_button(block, post_action); @@ -3038,14 +3066,19 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi static void free_post_file_close_action(void *arg) { - GenericCallback *action = (GenericCallback *)arg; - wm_generic_callback_free(action); + wmGenericCallback *action = (wmGenericCallback *)arg; + WM_generic_callback_free(action); } -void wm_close_file_dialog(bContext *C, GenericCallback *post_action) +void wm_close_file_dialog(bContext *C, wmGenericCallback *post_action) { - UI_popup_block_invoke( - C, block_create__close_file_dialog, post_action, free_post_file_close_action); + if (!UI_popup_block_name_exists(C, close_file_dialog_name)) { + UI_popup_block_invoke( + C, block_create__close_file_dialog, post_action, free_post_file_close_action); + } + else { + WM_generic_callback_free(post_action); + } } bool wm_file_or_image_is_modified(const bContext *C) @@ -3054,25 +3087,4 @@ bool wm_file_or_image_is_modified(const bContext *C) return !wm->file_saved || ED_image_should_save_modified(C); } -void wm_generic_callback_free(GenericCallback *callback) -{ - if (callback->free_user_data) { - callback->free_user_data(callback->user_data); - } - MEM_freeN(callback); -} - -static void do_nothing(bContext *UNUSED(C), void *UNUSED(user_data)) -{ -} - -GenericCallback *wm_generic_callback_steal(GenericCallback *callback) -{ - GenericCallback *new_callback = MEM_dupallocN(callback); - callback->exec = do_nothing; - callback->free_user_data = NULL; - callback->user_data = NULL; - return new_callback; -} - /** \} */ diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index 0cb3e5e3088..1a46a4550d9 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -729,7 +729,10 @@ static void lib_relocate_do(Main *bmain, } if (new_id) { #ifdef PRINT_DEBUG - printf("before remap, old_id users: %d, new_id users: %d\n", old_id->us, new_id->us); + printf("before remap of %s, old_id users: %d, new_id users: %d\n", + old_id->name, + old_id->us, + new_id->us); #endif BKE_libblock_remap_locked(bmain, old_id, new_id, remap_flags); @@ -739,7 +742,10 @@ static void lib_relocate_do(Main *bmain, } #ifdef PRINT_DEBUG - printf("after remap, old_id users: %d, new_id users: %d\n", old_id->us, new_id->us); + printf("after remap of %s, old_id users: %d, new_id users: %d\n", + old_id->name, + old_id->us, + new_id->us); #endif /* In some cases, new_id might become direct link, remove parent of library in this case. */ diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index b12bb89ea9f..e117a1bcdfe 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -62,7 +62,7 @@ wmGesture *WM_gesture_new(bContext *C, const wmEvent *event, int type) gesture->type = type; gesture->event_type = event->type; gesture->winrct = ar->winrct; - gesture->userdata_free = true; /* Free if userdata is set. */ + gesture->user_data.use_free = true; /* Free if userdata is set. */ gesture->modal_state = GESTURE_MODAL_NOP; if (ELEM(type, @@ -106,9 +106,7 @@ void WM_gesture_end(bContext *C, wmGesture *gesture) } BLI_remlink(&win->gesture, gesture); MEM_freeN(gesture->customdata); - if (gesture->userdata && gesture->userdata_free) { - MEM_freeN(gesture->userdata); - } + WM_generic_user_data_free(&gesture->user_data); MEM_freeN(gesture); } diff --git a/source/blender/windowmanager/intern/wm_keymap_utils.c b/source/blender/windowmanager/intern/wm_keymap_utils.c index 626e9e88845..4603f14729d 100644 --- a/source/blender/windowmanager/intern/wm_keymap_utils.c +++ b/source/blender/windowmanager/intern/wm_keymap_utils.c @@ -451,6 +451,46 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname) return km; } +static bool wm_keymap_item_uses_modifier(wmKeyMapItem *kmi, const int event_modifier) +{ + if (kmi->ctrl != KM_ANY) { + if ((kmi->ctrl == KM_NOTHING) != ((event_modifier & KM_CTRL) == 0)) { + return false; + } + } + + if (kmi->alt != KM_ANY) { + if ((kmi->alt == KM_NOTHING) != ((event_modifier & KM_ALT) == 0)) { + return false; + } + } + + if (kmi->shift != KM_ANY) { + if ((kmi->shift == KM_NOTHING) != ((event_modifier & KM_SHIFT) == 0)) { + return false; + } + } + + if (kmi->oskey != KM_ANY) { + if ((kmi->oskey == KM_NOTHING) != ((event_modifier & KM_OSKEY) == 0)) { + return false; + } + } + return true; +} + +bool WM_keymap_uses_event_modifier(wmKeyMap *keymap, const int event_modifier) +{ + for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { + if ((kmi->flag & KMI_INACTIVE) == 0) { + if (wm_keymap_item_uses_modifier(kmi, event_modifier)) { + return true; + } + } + } + return false; +} + void WM_keymap_fix_linking(void) { } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 0bb2fd58824..4a99c2de6e7 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3085,8 +3085,7 @@ static void redraw_timer_step(bContext *C, { if (type == eRTDrawRegion) { if (ar) { - ED_region_do_draw(C, ar); - ar->do_draw = false; + wm_draw_region_test(C, sa, ar); } } else if (type == eRTDrawRegionSwap) { @@ -3110,8 +3109,7 @@ static void redraw_timer_step(bContext *C, for (ar_iter = sa_iter->regionbase.first; ar_iter; ar_iter = ar_iter->next) { if (ar_iter->visible) { CTX_wm_region_set(C, ar_iter); - ED_region_do_draw(C, ar_iter); - ar_iter->do_draw = false; + wm_draw_region_test(C, sa_iter, ar_iter); } } } @@ -3156,6 +3154,7 @@ static int redraw_timer_exec(bContext *C, wmOperator *op) wmWindow *win = CTX_wm_window(C); ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); + wmWindowManager *wm = CTX_wm_manager(C); double time_start, time_delta; const int type = RNA_enum_get(op->ptr, "type"); const int iter = RNA_int_get(op->ptr, "iterations"); @@ -3169,6 +3168,8 @@ static int redraw_timer_exec(bContext *C, wmOperator *op) time_start = PIL_check_seconds_timer(); + wm_window_make_drawable(wm, win); + for (a = 0; a < iter; a++) { redraw_timer_step(C, bmain, scene, depsgraph, win, sa, ar, type, cfra); iter_steps += 1; diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c index 92ef235722b..3ea58d8c4e5 100644 --- a/source/blender/windowmanager/intern/wm_toolsystem.c +++ b/source/blender/windowmanager/intern/wm_toolsystem.c @@ -726,7 +726,7 @@ static const char *toolsystem_default_tool(const bToolKey *tkey) case SPACE_IMAGE: switch (tkey->mode) { case SI_MODE_PAINT: - return "builtin_brush.draw"; + return "builtin_brush.Draw"; } break; case SPACE_NODE: { diff --git a/source/blender/windowmanager/intern/wm_utils.c b/source/blender/windowmanager/intern/wm_utils.c new file mode 100644 index 00000000000..c0ee1ec44db --- /dev/null +++ b/source/blender/windowmanager/intern/wm_utils.c @@ -0,0 +1,71 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup wm + * + * Generic helper utilies that aren't assosiated with a particular area. + */ + +#include "WM_types.h" +#include "WM_api.h" + +#include "MEM_guardedalloc.h" + +/* -------------------------------------------------------------------- */ +/** \name Generic Callback + * \{ */ + +void WM_generic_callback_free(wmGenericCallback *callback) +{ + if (callback->free_user_data) { + callback->free_user_data(callback->user_data); + } + MEM_freeN(callback); +} + +static void do_nothing(struct bContext *UNUSED(C), void *UNUSED(user_data)) +{ +} + +wmGenericCallback *WM_generic_callback_steal(wmGenericCallback *callback) +{ + wmGenericCallback *new_callback = MEM_dupallocN(callback); + callback->exec = do_nothing; + callback->free_user_data = NULL; + callback->user_data = NULL; + return new_callback; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Generic User Data + * \{ */ + +void WM_generic_user_data_free(wmGenericUserData *wm_userdata) +{ + if (wm_userdata->data && wm_userdata->use_free) { + if (wm_userdata->free_fn) { + wm_userdata->free_fn(wm_userdata->data); + } + else { + MEM_freeN(wm_userdata->data); + } + } +} + +/** \} */ diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 1ac23754972..7ae572e5685 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -368,7 +368,7 @@ static void wm_save_file_on_quit_dialog_callback(bContext *C, void *UNUSED(user_ */ static void wm_confirm_quit(bContext *C) { - GenericCallback *action = MEM_callocN(sizeof(*action), __func__); + wmGenericCallback *action = MEM_callocN(sizeof(*action), __func__); action->exec = wm_save_file_on_quit_dialog_callback; wm_close_file_dialog(C, action); } diff --git a/source/blender/windowmanager/wm_draw.h b/source/blender/windowmanager/wm_draw.h index ede2b3191b9..0a07eb998cf 100644 --- a/source/blender/windowmanager/wm_draw.h +++ b/source/blender/windowmanager/wm_draw.h @@ -38,6 +38,7 @@ typedef struct wmDrawBuffer { } wmDrawBuffer; struct ARegion; +struct ScrArea; struct bContext; struct wmWindow; @@ -45,6 +46,7 @@ struct wmWindow; void wm_draw_update(struct bContext *C); void wm_draw_region_clear(struct wmWindow *win, struct ARegion *ar); void wm_draw_region_blend(struct ARegion *ar, int view, bool blend); +void wm_draw_region_test(struct bContext *C, struct ScrArea *sa, struct ARegion *ar); struct GPUTexture *wm_draw_region_texture(struct ARegion *ar, int view); diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h index 8b3f1ead215..0aa4357a8f4 100644 --- a/source/blender/windowmanager/wm_files.h +++ b/source/blender/windowmanager/wm_files.h @@ -25,6 +25,7 @@ #define __WM_FILES_H__ struct Main; +struct wmGenericCallback; struct wmOperatorType; /* wm_files.c */ @@ -40,15 +41,7 @@ void wm_homefile_read(struct bContext *C, bool *r_is_factory_startup); void wm_file_read_report(bContext *C, struct Main *bmain); -typedef struct GenericCallback { - void (*exec)(bContext *C, void *user_data); - void *user_data; - void (*free_user_data)(void *user_data); -} GenericCallback; - -GenericCallback *wm_generic_callback_steal(GenericCallback *callback); -void wm_generic_callback_free(GenericCallback *callback); -void wm_close_file_dialog(bContext *C, GenericCallback *post_action); +void wm_close_file_dialog(bContext *C, struct wmGenericCallback *post_action); bool wm_file_or_image_is_modified(const struct bContext *C); void WM_OT_save_homefile(struct wmOperatorType *ot); |